<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>eScience Center Blog</title><description>Research software engineering, data science, and digital scholarship — by the Netherlands eScience Center</description><link>https://blog2.esciencecenter.nl/</link><language>en</language><item><title>Making 3D Real: How 3DLab Is Bringing Scientific Data to Life</title><link>https://blog2.esciencecenter.nl/posts/2026-06-25---making-3d-real-how-3dlab-is-bringing-scientific-data-to-life</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-06-25---making-3d-real-how-3dlab-is-bringing-scientific-data-to-life</guid><description>&lt;p&gt;&lt;img alt=&quot;3D Gaussian Splatting visualization&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;628&quot; height=&quot;599&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mAnikgybC6AM9aFcDx5Oxg.DR0rUdzV_Z11NQQ4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Imagine trying to understand the structural integrity of a Roman ruin, or the complex vascular network of a biological organ, by looking at a flat map or static 2D photographs. You might get the general idea, but the depth, the context, and the reality are lost in translation.&lt;/p&gt;
&lt;p&gt;We live in a three-dimensional world, yet so much of our scientific data remains trapped on two-dimensional screens. For researchers in fields ranging from digital humanities to environmental science, this is not just an aesthetic issue. It’s a barrier to discovery.&lt;/p&gt;
&lt;p&gt;Luckily, there is research software to overcome this barrier and get more insight by intuitive and photo-realistic 3D visualization. However, this software comes with another barrier: ease of use. This is where &lt;strong&gt;3DLab&lt;/strong&gt; can help you: to easily access this powerful technology.&lt;/p&gt;
&lt;h2 id=&quot;the-challenge-capturing-the-world-around-you&quot;&gt;The Challenge: Capturing the World Around You&lt;/h2&gt;
&lt;p&gt;There is an active field of computer vision research trying to tackle how we explore new places. In simultaneous localization and mapping (SLAM), a camera with location sensors (e.g. GPS and IMU) has to both accurately track its location while simultaneously creating a digital representation of the surroundings.&lt;/p&gt;
&lt;p&gt;In recent years, SLAM has seen a huge boom in interest with the application of novel machine learning techniques. Novel scene representations like neural radiance fields have made the resulting digital models photo-realistic. In turn, 3D Gaussian Splatting has made it possible to create such photo-realistic models in under an hour and render them at high frame-rates.&lt;/p&gt;
&lt;h2 id=&quot;the-approach-gaussian-splatting&quot;&gt;The Approach: Gaussian Splatting&lt;/h2&gt;
&lt;video controls width=&quot;560&quot; height=&quot;315&quot; style=&quot;display: block; max-width: 100%; height: auto; margin: 0 auto;&quot;&gt;
  &lt;source src=&quot;https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/content/videos/bicycle.mp4&quot; type=&quot;video/mp4&quot;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;p class=&quot;caption&quot;&gt;Source: https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/&lt;/p&gt;
&lt;p&gt;If traditional 3D models (meshes) are like origami sculptures, Gaussian Splatting is like 3D impressionist painting. It represents a scene using millions of fuzzy 3D ellipses (“splats”). These splats can overlap and blend, allowing for incredibly realistic rendering of complex scenes, like the fuzzy texture of moss on a stone or the reflective sheen of polished marble, that traditional methods struggle to capture.&lt;/p&gt;
&lt;p&gt;However, Gaussian Splatting is complex to set up and use. It requires very specific software dependencies and careful manual workflows. 3DLab focuses on removing these hurdles, allowing researchers to input raw data and receive a high-fidelity 3D visualization without needing a second PhD in computer science.&lt;/p&gt;
&lt;p&gt;Key features of the 3DLab approach include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Accessibility:&lt;/strong&gt; ease of installation through detailed step-by-step installation instructions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation:&lt;/strong&gt; scripts that handle the heavy lifting of pre-processing your data and training the 3D models.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organization:&lt;/strong&gt; guided by a single configuration file that organizes your data and parameter settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;impact-from-artifacts-to-algorithms&quot;&gt;Impact: From Artifacts to Algorithms&lt;/h2&gt;
&lt;video controls width=&quot;560&quot; height=&quot;315&quot; style=&quot;display: block; max-width: 100%; height: auto; margin: 0 auto;&quot;&gt;
  &lt;source src=&quot;https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/content/videos/garden.mp4&quot; type=&quot;video/mp4&quot;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;p class=&quot;caption&quot;&gt;Source: https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/&lt;/p&gt;
&lt;p&gt;While the project has applications in medicine and engineering, its potential in the &lt;strong&gt;Social Sciences and Humanities (SH)&lt;/strong&gt; is particularly exciting.&lt;/p&gt;
&lt;p&gt;Consider the field of art history. Capturing and preserving historical sites is a meticulous process. By using the tools developed in 3DLab, researchers can create “digital twins” of heritage sites with unprecedented photo-realism. This preserves the site digitally for remote or future study. It also allows an immersive way to present this history to the public.&lt;/p&gt;
&lt;p&gt;The impact of 3DLab goes beyond just pretty pictures. It aligns with the &lt;strong&gt;FAIR principles&lt;/strong&gt; (Findable, Accessible, Interoperable, Reusable). By providing open-source automation tools, the project ensures that 3D visualizations are not just one-off artistic projects, but reproducible scientific outputs.&lt;/p&gt;
&lt;h2 id=&quot;building-a-community-of-visualizers&quot;&gt;Building a Community of Visualizers&lt;/h2&gt;
&lt;p&gt;3DLab is not developed in a vacuum. It represents a strategic effort to embed 3D expertise into the Dutch research ecosystem. The project aims to leverage the vibrant &lt;strong&gt;NL-RSE (Research Software Engineers in the Netherlands)&lt;/strong&gt; community, sharing knowledge and code to ensure these tools survive beyond the initial funding cycle.&lt;/p&gt;
&lt;p&gt;The project also highlights the collaborative nature of modern science. It sits at the intersection of computer vision, software engineering, and domain-specific research. By making the code open source on GitHub, the eScience Center invites contributions from developers and researchers worldwide, fostering a culture of shared innovation.&lt;/p&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;
&lt;p&gt;The work on 3DLab is just the beginning. As techniques like Gaussian Splatting mature, we gaze at the branching possibilities, like integrating these visualizations into virtual reality (VR) and augmented reality (AR) environments. Imagine a medical student walking inside a simulation of a patient’s heart, or a historian walking through a digital reconstruction of 17th-century Amsterdam.&lt;/p&gt;
&lt;p&gt;By lowering the barrier to entry, 3DLab is ensuring that the future of science isn’t just data-driven but it’s immersive, interactive, and accessible to all.&lt;/p&gt;
&lt;h2 id=&quot;get-involved&quot;&gt;Get Involved&lt;/h2&gt;
&lt;p&gt;Are you a researcher struggling to visualize high-dimensional data? Or an RSE interested in the bleeding edge of computer graphics?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explore the Code:&lt;/strong&gt; Check out the &lt;a href=&quot;https://github.com/NLeSC/3dgs_automation&quot;&gt;3D Gaussian Splatting automation repository on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read the Report:&lt;/strong&gt; Dive deeper into the technical details in the &lt;a href=&quot;https://nlesc-my.sharepoint.com/:w:/g/personal/t_vanlankveld_esciencecenter_nl/IQDcC5wodS0xTYJHQKD2wM1NAZ6h-z-12IevTwMOFfgEUp0?e=3oC24W&quot;&gt;3D Lab project report&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect:&lt;/strong&gt; Reach out to &lt;em&gt;Thijs van Lankveld&lt;/em&gt; or the &lt;em&gt;eScience Center&lt;/em&gt; team to discuss how 3D visualization can transform your research.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;3D Gaussian Splatting visualization&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;628&quot; height=&quot;599&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mAnikgybC6AM9aFcDx5Oxg.DR0rUdzV_Z11NQQ4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Imagine trying to understand the structural integrity of a Roman ruin, or the complex vascular network of a biological organ, by looking at a flat map or static 2D photographs. You might get the general idea, but the depth, the context, and the reality are lost in translation.&lt;/p&gt;
&lt;p&gt;We live in a three-dimensional world, yet so much of our scientific data remains trapped on two-dimensional screens. For researchers in fields ranging from digital humanities to environmental science, this is not just an aesthetic issue. It’s a barrier to discovery.&lt;/p&gt;
&lt;p&gt;Luckily, there is research software to overcome this barrier and get more insight by intuitive and photo-realistic 3D visualization. However, this software comes with another barrier: ease of use. This is where &lt;strong&gt;3DLab&lt;/strong&gt; can help you: to easily access this powerful technology.&lt;/p&gt;
&lt;h2 id=&quot;the-challenge-capturing-the-world-around-you&quot;&gt;The Challenge: Capturing the World Around You&lt;/h2&gt;
&lt;p&gt;There is an active field of computer vision research trying to tackle how we explore new places. In simultaneous localization and mapping (SLAM), a camera with location sensors (e.g. GPS and IMU) has to both accurately track its location while simultaneously creating a digital representation of the surroundings.&lt;/p&gt;
&lt;p&gt;In recent years, SLAM has seen a huge boom in interest with the application of novel machine learning techniques. Novel scene representations like neural radiance fields have made the resulting digital models photo-realistic. In turn, 3D Gaussian Splatting has made it possible to create such photo-realistic models in under an hour and render them at high frame-rates.&lt;/p&gt;
&lt;h2 id=&quot;the-approach-gaussian-splatting&quot;&gt;The Approach: Gaussian Splatting&lt;/h2&gt;
&lt;video controls width=&quot;560&quot; height=&quot;315&quot; style=&quot;display: block; max-width: 100%; height: auto; margin: 0 auto;&quot;&gt;
  &lt;source src=&quot;https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/content/videos/bicycle.mp4&quot; type=&quot;video/mp4&quot;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;p class=&quot;caption&quot;&gt;Source: https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/&lt;/p&gt;
&lt;p&gt;If traditional 3D models (meshes) are like origami sculptures, Gaussian Splatting is like 3D impressionist painting. It represents a scene using millions of fuzzy 3D ellipses (“splats”). These splats can overlap and blend, allowing for incredibly realistic rendering of complex scenes, like the fuzzy texture of moss on a stone or the reflective sheen of polished marble, that traditional methods struggle to capture.&lt;/p&gt;
&lt;p&gt;However, Gaussian Splatting is complex to set up and use. It requires very specific software dependencies and careful manual workflows. 3DLab focuses on removing these hurdles, allowing researchers to input raw data and receive a high-fidelity 3D visualization without needing a second PhD in computer science.&lt;/p&gt;
&lt;p&gt;Key features of the 3DLab approach include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Accessibility:&lt;/strong&gt; ease of installation through detailed step-by-step installation instructions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation:&lt;/strong&gt; scripts that handle the heavy lifting of pre-processing your data and training the 3D models.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organization:&lt;/strong&gt; guided by a single configuration file that organizes your data and parameter settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;impact-from-artifacts-to-algorithms&quot;&gt;Impact: From Artifacts to Algorithms&lt;/h2&gt;
&lt;video controls width=&quot;560&quot; height=&quot;315&quot; style=&quot;display: block; max-width: 100%; height: auto; margin: 0 auto;&quot;&gt;
  &lt;source src=&quot;https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/content/videos/garden.mp4&quot; type=&quot;video/mp4&quot;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;p class=&quot;caption&quot;&gt;Source: https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/&lt;/p&gt;
&lt;p&gt;While the project has applications in medicine and engineering, its potential in the &lt;strong&gt;Social Sciences and Humanities (SH)&lt;/strong&gt; is particularly exciting.&lt;/p&gt;
&lt;p&gt;Consider the field of art history. Capturing and preserving historical sites is a meticulous process. By using the tools developed in 3DLab, researchers can create “digital twins” of heritage sites with unprecedented photo-realism. This preserves the site digitally for remote or future study. It also allows an immersive way to present this history to the public.&lt;/p&gt;
&lt;p&gt;The impact of 3DLab goes beyond just pretty pictures. It aligns with the &lt;strong&gt;FAIR principles&lt;/strong&gt; (Findable, Accessible, Interoperable, Reusable). By providing open-source automation tools, the project ensures that 3D visualizations are not just one-off artistic projects, but reproducible scientific outputs.&lt;/p&gt;
&lt;h2 id=&quot;building-a-community-of-visualizers&quot;&gt;Building a Community of Visualizers&lt;/h2&gt;
&lt;p&gt;3DLab is not developed in a vacuum. It represents a strategic effort to embed 3D expertise into the Dutch research ecosystem. The project aims to leverage the vibrant &lt;strong&gt;NL-RSE (Research Software Engineers in the Netherlands)&lt;/strong&gt; community, sharing knowledge and code to ensure these tools survive beyond the initial funding cycle.&lt;/p&gt;
&lt;p&gt;The project also highlights the collaborative nature of modern science. It sits at the intersection of computer vision, software engineering, and domain-specific research. By making the code open source on GitHub, the eScience Center invites contributions from developers and researchers worldwide, fostering a culture of shared innovation.&lt;/p&gt;
&lt;h2 id=&quot;looking-ahead&quot;&gt;Looking Ahead&lt;/h2&gt;
&lt;p&gt;The work on 3DLab is just the beginning. As techniques like Gaussian Splatting mature, we gaze at the branching possibilities, like integrating these visualizations into virtual reality (VR) and augmented reality (AR) environments. Imagine a medical student walking inside a simulation of a patient’s heart, or a historian walking through a digital reconstruction of 17th-century Amsterdam.&lt;/p&gt;
&lt;p&gt;By lowering the barrier to entry, 3DLab is ensuring that the future of science isn’t just data-driven but it’s immersive, interactive, and accessible to all.&lt;/p&gt;
&lt;h2 id=&quot;get-involved&quot;&gt;Get Involved&lt;/h2&gt;
&lt;p&gt;Are you a researcher struggling to visualize high-dimensional data? Or an RSE interested in the bleeding edge of computer graphics?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Explore the Code:&lt;/strong&gt; Check out the &lt;a href=&quot;https://github.com/NLeSC/3dgs_automation&quot;&gt;3D Gaussian Splatting automation repository on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read the Report:&lt;/strong&gt; Dive deeper into the technical details in the &lt;a href=&quot;https://nlesc-my.sharepoint.com/:w:/g/personal/t_vanlankveld_esciencecenter_nl/IQDcC5wodS0xTYJHQKD2wM1NAZ6h-z-12IevTwMOFfgEUp0?e=3oC24W&quot;&gt;3D Lab project report&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect:&lt;/strong&gt; Reach out to &lt;em&gt;Thijs van Lankveld&lt;/em&gt; or the &lt;em&gt;eScience Center&lt;/em&gt; team to discuss how 3D visualization can transform your research.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_mAnikgybC6AM9aFcDx5Oxg.DR0rUdzV.webp" medium="image"/><author>Thijs van Lankveld</author></item><item><title>Research Software Engineers in the Age of GenAI: Same Value, Changing Practice</title><link>https://blog2.esciencecenter.nl/posts/2026-05-28---research-software-engineers-in-the-age-of-genai-same-value-c</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-05-28---research-software-engineers-in-the-age-of-genai-same-value-c</guid><description>&lt;p&gt;&lt;em&gt;Stephan Druskat, Michelle Barker, Ian Cosden, Cunliang Geng, Robert Haines, Daniel S. Katz, Joseph Shingleton, Ben van Werkhoven&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-e2e2857a.DtjkNNeC_1OdOGE.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;This blog post is being cross-posted by the &lt;em&gt;&lt;a href=&quot;https://www.researchsoft.org/blog/&quot;&gt;&lt;em&gt;Research Software Alliance&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (ReSA), &lt;em&gt;&lt;a href=&quot;https://bssw.io/blog_posts&quot;&gt;&lt;em&gt;Better Scientific Software&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (BSSw), the &lt;em&gt;&lt;a href=&quot;https://everse.software/news/&quot;&gt;&lt;em&gt;European Virtual Institute for Research Software Excellence&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;(EVERSE) and the &lt;em&gt;&lt;a href=&quot;https://www.software.ac.uk/news-and-blogs-hub&quot;&gt;&lt;em&gt;Software Sustainability Institute&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (SSI).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DOI: &lt;a href=&quot;https://zenodo.org/records/20320179&quot;&gt;10.5281/zenodo.20320179&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Research software and its creators have long played a critical role in the advancement of research worldwide. This role is changing in the age of “generative AI” (GenAI), but both the software and the people remain of key importance. Understanding these changes is essential in enabling Research Software Engineers (RSEs) to continue contributing the same high value to the research process and its outputs.&lt;/p&gt;
&lt;p&gt;Before GenAI, the RSE movement had learned to clearly articulate the value proposition of embedding expert software engineering in research to its stakeholders. This blog post highlights how RSEs use GenAI to increase their capacity in both software engineering and research, and visualize this evolution. While GenAI is changing — perhaps considerably — how RSEs work in practice, their value and the value of their work for research remains steady and likely to increase.&lt;/p&gt;
&lt;p&gt;Generative AI, specifically Large Language Models (LLMs) and coding agents, is rapidly changing software engineering. The practice of software engineering is shifting away from writing lines of code to specifying requirements, implementations, designs and verification strategies in higher-level abstractions, including natural language specifications, that are then enacted by an AI coding agent. This lowers the barrier to entry for producing code and reduces the development time for new solutions.&lt;/p&gt;
&lt;p&gt;Generative AI is not only impacting software development in industry, but is understandably also seeing rapid adoption in academia to accelerate software development processes. Its application enables researchers to produce their own research software, including those who would not have done so previously. Software solutions, once beyond the reach of researchers lacking programming and software engineering knowledge, are now accessible with these new GenAI tools. If researchers can write more — and better — code, themselves, it begs the question: where do RSEs fit in this new paradigm?&lt;/p&gt;
&lt;p&gt;In March 2026, 36 members of the research software community came together to discuss this at a workshop entitled “&lt;a href=&quot;https://www.researchsoft.org/events/rse-ai-workshop/&quot;&gt;Research Software Engineering in the Age of Generative AI: Building a Community Vision&lt;/a&gt;”, held in Edinburgh, UK. The Research Software Alliance co-led this event and was supported to undertake this work as part of a Schmidt Sciences grant. Whilst the impact of GenAI on research is being discussed in many forums and publications, this workshop provided an opportunity for a range of early adopters, innovators, and RSE leads to come together to discuss how the ecosystem was changing, and to chart constructive ways to shape and support this change.&lt;/p&gt;
&lt;p&gt;The workshop included multiple rounds of focused working groups, one of which discussed the value of research software engineering in the age of GenAI. This blog post is an outcome of that working group. Its authors brought together their experience as leaders of different types of RSE initiatives across the ecosystem to provide an accessible way to show both how the roles of research software personnel are evolving in line with GenAI, and how these roles remain key to enabling research impact.&lt;/p&gt;
&lt;p&gt;There are costs, concerns and risks associated with the creation and use of AI models generally [1], [2], and in a multitude of more focused areas, including skills [3], [4], [5], [6], community culture and motivation [7], [8], as well as equity and ethics [9], [10], [11]. However, while many of these risks also apply to the use of GenAI in coding tasks, there are also many immediate benefits for coding [12], [13], [14], [15]. AI tools are accelerating routine coding tasks, such as creating working scripts for data analysis, generating boilerplate code, tests and documentation, all from high-level natural language prompts. Coding agents represent a more autonomous evolution of prompt-based coding, enabling systems built around LLMs to access and operate on existing codebases to handle more complex tasks, such as refactoring or porting. They can even be used to build an entire codebase from scratch, given sufficient information such as specifications or implementation plans.&lt;/p&gt;
&lt;p&gt;As software has become one of the primary research tools across all disciplines, a significant majority of scientific results rely on the quality of that software. RSEs emerged as a result: by combining professional software engineering expertise with an intimate understanding of the research discipline, partnerships between RSEs and researchers allowed software to evolve along with research, with RSEs guiding the productive application of methods and technologies and ensuring that software meets the reliability and reproducibility standards that are expected from scientific instruments. This unique position of RSEs bridging software engineering and research was often depicted in diagrams similar to Figure 1, which shows that RSEs vary in their skills and knowledge of both software engineering and research activities. It also shows RSE-adjacent roles (such as software engineer, researcher, and researcher who codes) to provide context, illustrating that RSEs have more software engineering experience than researchers, while also possessing a deeper understanding of research practices than software engineers. Diagrams like these have been very important tools in achieving (pre-GenAI) understanding of the value provided by RSEs, to the extent that RSEs are supported by national initiatives such as those in the UK, the Netherlands and Germany [16], [17], [18].&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;680&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-4c402b8d.DHWN-me0_Z101yE7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: RSEs bring both software engineering and research expertise.With the advent of GenAI, two questions arise: Is this partnership between RSEs and researchers still needed and still valuable? And, how do these roles change? In the age of GenAI, both researchers and RSEs have access to LLMs and coding agents to accelerate their work. Researchers are able to prototype and explore ideas faster and more freely than before. Meanwhile, RSEs are able to use these GenAI tools to greater effect and impact, due to their expertise in software engineering, particularly in requirements engineering and specification, software architecture, testing and verification, validation, performance, and long-term sustainability. This enables them to frame problems more precisely, to evaluate tradeoffs and verify internal correctness and consistency more effectively, and to better address longstanding challenges in research software. Moreover, their continued and frequent practice with these tools compounds their advantages, allowing them to better anticipate failure modes, enforce quality standards, and integrate tooling into complex, evolving research environments.&lt;/p&gt;
&lt;p&gt;RSEs who maintain GenAI literacy and the ability to critically evaluate complex software stacks are especially indispensable in view of the risks associated with the increasing adoption of GenAI in research software development. In particular, when researchers use agentic coding tools without sufficient expertise and experience to write increasingly complex software, over-reliance on these tools risks generating a significant disconnect between the coder and the code. This disconnect can lead to the introduction of unintended errors and inaccuracies, and could pose serious risk to the robustness of related scientific outputs and research results. In this situation, RSEs are well positioned to provide the guidance and oversight that is necessary to ensure the safe adoption of AI in research software engineering.&lt;/p&gt;
&lt;p&gt;Taken together, the value of an RSE remains significant, as the RSE role evolves to integrate expert knowledge in the application of GenAI for software engineering in research contexts. This viewpoint is similarly articulated in the &lt;a href=&quot;https://github.com/Academic-Data-Science-Alliance/rse-ai-position-statement/blob/main/RSE-AI-Final_Statement.md&quot;&gt;Position Statement on Generative AI in the RSE Workplace&lt;/a&gt;[19], which is led by US-RSE and the Alliance for Data Science and AI. The Edinburgh workshop built upon this position statement, and it is also being shared in other conversations[20], [21]. As such, the value of RSEs in relation to researchers and other stakeholders will remain unchanged as their role as a research software professional evolves to also integrate expert knowledge in the application of GenAI in research contexts. This blog post seeks to move one step further in clearly articulating that value in a way that is easy to understand.&lt;/p&gt;
&lt;p&gt;Overall, the value of the RSE role shifts upward as AI enhances it and amplifies its impact. While the practice may change and shift focus to higher levels of abstraction, including specification and verification, the value proposition remains the same**. This is depicted in Figure 2, which shows how the use of GenAI enables the value of RSEs to increase along both the software engineering and research activity axes. It is critical for the research community to understand and acknowledge this increased potential for research impact, and to ensure that going forward, RSE expertise is appropriately supported, funded and integrated into research ecosystems.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-e2e2857a.DtjkNNeC_1OdOGE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: AI can enable RSEs to increase their capacity for both research and software engineering, irrespective of specializations.Figure 3 highlights the unique position of RSEs in the research ecosystem. RSEs and other roles in the research sector (software engineers, researchers who code, and researchers) all evolve in response to leveraging GenAI tools, which affects all groups along the software engineering capacity axis to varying degrees. Researchers who have not previously done any programming can now generate their own code, but for all non-RSE roles these shifts largely reinforce strengths within their established areas of expertise. For RSEs, however, this evolution plays to their dual focus on both software engineering and research, so that the effective value of RSEs and their work is amplified, as GenAI enables them to provide (even) more and better software to support (even) more and better research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;589&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-6f0e3f69.Cs5ozV6X_ZRCakM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: How various roles are evolving in response to GenAI.&lt;strong&gt;Acknowledgements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;MB and DSK were supported to undertake this work as part of Schmidt Sciences grant G-25–69965.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Author biographies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/michelledbarker/&quot;&gt;Michelle Barker&lt;/a&gt; is Director of the Research Software Alliance and has extensive expertise in open science, the research software community, digital skills, and digital research infrastructure. As a sociologist, Michelle is passionate about building collaborative partnerships to achieve system change. She is a former Director of the Australian Research Data Commons, where she led the national research software infrastructure investment program.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/cosden&quot;&gt;Ian Cosden&lt;/a&gt; is the Senior Director of Research Software Engineering at Princeton University. He leads a team of research software engineers who complement multiple traditional academic research groups by offering embedded, long-term software development expertise. He spearheaded the formation of the RSE group in 2016 and has grown the group from an initial size of two FTEs, to a total of 37 FTEs as of May 2026. Ian is the current and founding chair of the steering committee for the United States Research Software Engineer (US-RSE) Association. Additionally, he is the principal investigator for Innovative Training Enabled by a Research Software Engineering Community of Trainers (INTERSECT), an NSF-funded project to develop and deliver RSE-led training events for current researchers interested in careers in research software engineering.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://sdruskat.net&quot;&gt;Stephan Druskat&lt;/a&gt; is a (Research) Software Engineering Researcher based in Berlin. His research focuses on requirements, constraints, policies and practices of software engineering in academic research contexts, such as software publication, citation and sustainability, as well as software metadata and software supply chains. He is a Fellow of the Software Sustainability Institute, co-founder of the Society for Research Software in Germany (de-RSE), and lead of the Citation File Format project.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/hainesr&quot;&gt;Robert Haines&lt;/a&gt; is Director of Research IT and an Honorary Lecturer at the University of Manchester, and a Fellow of the Software Sustainability Institute. He is one of the originators of the term “Research Software Engineer”, served for six years as an elected representative of the UK RSE Association, chaired the First Conference of Research Software Engineers in 2016, and was a founding trustee of the Society of Research Software Engineering. Robert’s research interests include software engineering, software sustainability, software use in open and reproducible research, software citation and credit, and career paths for software engineers and data scientists.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://danielskatz.org/&quot;&gt;Daniel S. Katz&lt;/a&gt; is Chief Scientist at the National Center for Supercomputing Applications, Research Professor in the Siebel School of Computing and Data Science, and Research Professor in the School of Information Sciences at the University of Illinois Urbana-Champaign. He works at the triple point of research software, people, and policy. He is a co-founder and current Associate Editor-in-Chief of the Journal of Open Source Software, co-founder of the US Research Software Engineer Association (US-RSE), and co-founder and steering committee chair of the Research Software Alliance (ReSA).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jshng-glasgow&quot;&gt;Joseph Shingleton&lt;/a&gt; is a Research Software Engineer at the University of Glasgow. His research explores how artificial intelligence can be safely and effectively applied to tasks in geospatial data science and research software engineering. He is the recipient of a UKRI Metascience AI Fellowship, focusing on how generative AI is shaping RSE practice and its consequences for the scientific process. He is also a Software Sustainability Institute Fellow and leads the SSI study group on responsible AI in RSE.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/benvanwerkhoven&quot;&gt;Ben van Werkhoven&lt;/a&gt; is assistant professor at Leiden University, where he heads the Accelerated Computing research group, focusing on making high-performance computing more energy-efficient and sustainable. He holds a PhD from VU Amsterdam on GPU-accelerated scientific computing (2014) and spent nearly a decade at the Netherlands eScience Center before joining Leiden in 2023. With over 15 years of GPU programming and optimization experience, Ben has worked on scientific applications ranging from microscopy and climate modeling to radio astronomy. He is also a co-founder of the Netherlands Research Software Engineers community (NL-RSE), advocating for the recognition of research software engineering as a professional discipline. At Leiden, he teaches High Performance Computing and Multiprocessor Programming, and serves as principal investigator on several research projects. He participates in major European and national consortia, including CORTEX and ESiWACE, advancing large-scale computing infrastructure for science.&lt;/p&gt;
&lt;p&gt;References**&lt;/p&gt;
&lt;p&gt;[1] M. Hosseini, S. P. J. M. Horbach, K. L. Holmes, and T. Ross-Hellauer, ‘Open Science at the Generative AI Turn: An Exploratory Analysis of Challenges and Opportunities’, May 24, 2024, SocArXiv*. doi: 10.31235/osf.io/zns7g.&lt;/p&gt;
&lt;p&gt;[2] G. O’Brien, ‘Threats to scientific software from over-reliance on AI code assistants’, &lt;em&gt;Nat Comput Sci&lt;/em&gt;, vol. 5, no. 9, pp. 701–703, Jul. 2025, doi: 10.1038/s43588–025–00845–2.&lt;/p&gt;
&lt;p&gt;[3] S. Andleeb, B. Kantorski, and J. C. Carver, ‘ChatGPT in Introductory Programming: Counterbalanced Evaluation of Code Quality, Conceptual Learning, and Student Perceptions’, 2025, &lt;em&gt;arXiv&lt;/em&gt;. doi: 10.48550/ARXIV.2510.00946.&lt;/p&gt;
&lt;p&gt;[4] G. O’Brien, A. Parker, N. Eisty, and J. Carver, ‘A survey of generative AI adoption and perceived productivity among scientists who program’, Apr. 09, 2026, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2512.19644. doi: 10.48550/arXiv.2512.19644.&lt;/p&gt;
&lt;p&gt;[5] SAPEA, ‘Successful and timely uptake of artificial intelligence in science in the EU: evidence review report’, SAPEA, Apr. 2024. doi: 10.5281/ZENODO.10977676.&lt;/p&gt;
&lt;p&gt;[6] M.-A. Storey, ‘From Technical Debt to Cognitive and Intent Debt: Rethinking Software Health in the Age of AI’, Apr. 06, 2026, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2603.22106. doi: 10.48550/arXiv.2603.22106.&lt;/p&gt;
&lt;p&gt;[7] R. Choudhuri, D. Liu, I. Steinmacher, M. Gerosa, and A. Sarma, ‘How Far Are We? The Triumphs and Trials of Generative AI in Learning Software Engineering’, in &lt;em&gt;Proceedings of the IEEE/ACM 46th International Conference on Software Engineering&lt;/em&gt;, Lisbon Portugal: ACM, Apr. 2024, pp. 1–13. doi: 10.1145/3597503.3639201.&lt;/p&gt;
&lt;p&gt;[8] M. Koren, G. Békés, J. Hinz, and A. Lohmann, ‘Vibe Coding Kills Open Source’, Jan. 21, 2026, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2601.15494. doi: 10.48550/arXiv.2601.15494.&lt;/p&gt;
&lt;p&gt;[9] S. A. Besser, E. A. Jensen, and D. S. Katz, ‘How generative AI is shaping research software development and maintenance at a research-intensive university’, &lt;em&gt;Open Res Europe&lt;/em&gt;, vol. 6, p. 56, Feb. 2026, doi: 10.12688/openreseurope.22009.1.&lt;/p&gt;
&lt;p&gt;[10] D. R. Newman-Griffis, ‘AI thinking and the enterprise of science’, Jun. 25, 2023, &lt;em&gt;Open Science Framework&lt;/em&gt;. doi: 10.31219/osf.io/wb83e.&lt;/p&gt;
&lt;p&gt;[11] D. Salah, ‘Invisible Risks, Visible Code: A Vision for Understanding Ethical Debt in AI-Based Coding’, in &lt;em&gt;2025 ACM/IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM)&lt;/em&gt;, Honolulu, HI, USA: IEEE, Oct. 2025, pp. 442–446. doi: 10.1109/ESEM64174.2025.00074.&lt;/p&gt;
&lt;p&gt;[12] E. W. Bridgeford &lt;em&gt;et al.&lt;/em&gt;, ‘Ten Simple Rules for AI-Assisted Coding in Science’, Oct. 31, 2025, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2510.22254. doi: 10.48550/arXiv.2510.22254.&lt;/p&gt;
&lt;p&gt;[13] L. C. McInnes &lt;em&gt;et al.&lt;/em&gt;, ‘Report of the 2025 Workshop on Next-Generation Ecosystems for Scientific Computing: Harnessing Community, Software, and AI for Cross-Disciplinary Team Science’, 2025, &lt;em&gt;arXiv&lt;/em&gt;. doi: 10.48550/ARXIV.2510.03413.&lt;/p&gt;
&lt;p&gt;[14] L. Nordling, ‘How ChatGPT is transforming the postdoc experience’, &lt;em&gt;Nature&lt;/em&gt;, vol. 622, no. 7983, pp. 655–657, Oct. 2023, doi: 10.1038/d41586–023–03235–8.&lt;/p&gt;
&lt;p&gt;[15] G. O’Brien, ‘How Scientists Use Large Language Models to Program’, in &lt;em&gt;Proceedings of the 2025 CHI Conference on Human Factors in Computing Systems&lt;/em&gt;, Yokohama Japan: ACM, Apr. 2025, pp. 1–16. doi: 10.1145/3706598.3713668.&lt;/p&gt;
&lt;p&gt;[16] M. Barker &lt;em&gt;et al.&lt;/em&gt;, ‘Software and skills for research computing in the UK’, Zenodo, Jan. 2024. doi: 10.5281/ZENODO.10473186.&lt;/p&gt;
&lt;p&gt;[17] D. Kempf &lt;em&gt;et al.&lt;/em&gt;, ‘Establishing central Research Software Engineering units in German research institutions’, 2025, [Online]. Available: &lt;a href=&quot;https://de-rse.org/2023_paper-RSE-groups/paper.pdf&quot;&gt;https://de-rse.org/2023_paper-RSE-groups/paper.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[18] LCRDM, ‘Professionalizing the role of Research Software Engineers in the Netherlands’, Zenodo, Mar. 2025. doi: 10.5281/ZENODO.15019998.&lt;/p&gt;
&lt;p&gt;[19] ADSA and US-RSE, ‘Position Statement on Generative AI in the RSE Workplace’. Accessed: Apr. 28, 2026. [Online]. Available: &lt;a href=&quot;https://github.com/Academic-Data-Science-Alliance/rse-ai-position-statement/blob/main/RSE-AI-Final_Statement.md&quot;&gt;https://github.com/Academic-Data-Science-Alliance/rse-ai-position-statement/blob/main/RSE-AI-Final_Statement.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[20] S. Gesing, ‘RSEs 2035: Surviving or Thriving in the Age of AI’, in &lt;em&gt;2025 IEEE International Conference on eScience (eScience)&lt;/em&gt;, Chicago, IL, USA: IEEE, Sep. 2025, pp. 381–382. doi: 10.1109/eScience65000.2025.00081.&lt;/p&gt;
&lt;p&gt;[21] P. Leather, D. Silver, and S. Frezza, ‘Software engineering role archetypes’, presented at the IEEE SWEBOK Summit 2026, Apr. 2026. [Online]. Available: &lt;a href=&quot;https://conf.researchr.org/details/icse-2026/swebok-2026/5/Talk-Software-engineering-role-archetypes-mapping-knowledge-skills-and-competenci&quot;&gt;https://conf.researchr.org/details/icse-2026/swebok-2026/5/Talk-Software-engineering-role-archetypes-mapping-knowledge-skills-and-competenci&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Stephan Druskat, Michelle Barker, Ian Cosden, Cunliang Geng, Robert Haines, Daniel S. Katz, Joseph Shingleton, Ben van Werkhoven&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-e2e2857a.DtjkNNeC_1OdOGE.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;This blog post is being cross-posted by the &lt;em&gt;&lt;a href=&quot;https://www.researchsoft.org/blog/&quot;&gt;&lt;em&gt;Research Software Alliance&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (ReSA), &lt;em&gt;&lt;a href=&quot;https://bssw.io/blog_posts&quot;&gt;&lt;em&gt;Better Scientific Software&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (BSSw), the &lt;em&gt;&lt;a href=&quot;https://everse.software/news/&quot;&gt;&lt;em&gt;European Virtual Institute for Research Software Excellence&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;(EVERSE) and the &lt;em&gt;&lt;a href=&quot;https://www.software.ac.uk/news-and-blogs-hub&quot;&gt;&lt;em&gt;Software Sustainability Institute&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (SSI).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;DOI: &lt;a href=&quot;https://zenodo.org/records/20320179&quot;&gt;10.5281/zenodo.20320179&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Research software and its creators have long played a critical role in the advancement of research worldwide. This role is changing in the age of “generative AI” (GenAI), but both the software and the people remain of key importance. Understanding these changes is essential in enabling Research Software Engineers (RSEs) to continue contributing the same high value to the research process and its outputs.&lt;/p&gt;
&lt;p&gt;Before GenAI, the RSE movement had learned to clearly articulate the value proposition of embedding expert software engineering in research to its stakeholders. This blog post highlights how RSEs use GenAI to increase their capacity in both software engineering and research, and visualize this evolution. While GenAI is changing — perhaps considerably — how RSEs work in practice, their value and the value of their work for research remains steady and likely to increase.&lt;/p&gt;
&lt;p&gt;Generative AI, specifically Large Language Models (LLMs) and coding agents, is rapidly changing software engineering. The practice of software engineering is shifting away from writing lines of code to specifying requirements, implementations, designs and verification strategies in higher-level abstractions, including natural language specifications, that are then enacted by an AI coding agent. This lowers the barrier to entry for producing code and reduces the development time for new solutions.&lt;/p&gt;
&lt;p&gt;Generative AI is not only impacting software development in industry, but is understandably also seeing rapid adoption in academia to accelerate software development processes. Its application enables researchers to produce their own research software, including those who would not have done so previously. Software solutions, once beyond the reach of researchers lacking programming and software engineering knowledge, are now accessible with these new GenAI tools. If researchers can write more — and better — code, themselves, it begs the question: where do RSEs fit in this new paradigm?&lt;/p&gt;
&lt;p&gt;In March 2026, 36 members of the research software community came together to discuss this at a workshop entitled “&lt;a href=&quot;https://www.researchsoft.org/events/rse-ai-workshop/&quot;&gt;Research Software Engineering in the Age of Generative AI: Building a Community Vision&lt;/a&gt;”, held in Edinburgh, UK. The Research Software Alliance co-led this event and was supported to undertake this work as part of a Schmidt Sciences grant. Whilst the impact of GenAI on research is being discussed in many forums and publications, this workshop provided an opportunity for a range of early adopters, innovators, and RSE leads to come together to discuss how the ecosystem was changing, and to chart constructive ways to shape and support this change.&lt;/p&gt;
&lt;p&gt;The workshop included multiple rounds of focused working groups, one of which discussed the value of research software engineering in the age of GenAI. This blog post is an outcome of that working group. Its authors brought together their experience as leaders of different types of RSE initiatives across the ecosystem to provide an accessible way to show both how the roles of research software personnel are evolving in line with GenAI, and how these roles remain key to enabling research impact.&lt;/p&gt;
&lt;p&gt;There are costs, concerns and risks associated with the creation and use of AI models generally [1], [2], and in a multitude of more focused areas, including skills [3], [4], [5], [6], community culture and motivation [7], [8], as well as equity and ethics [9], [10], [11]. However, while many of these risks also apply to the use of GenAI in coding tasks, there are also many immediate benefits for coding [12], [13], [14], [15]. AI tools are accelerating routine coding tasks, such as creating working scripts for data analysis, generating boilerplate code, tests and documentation, all from high-level natural language prompts. Coding agents represent a more autonomous evolution of prompt-based coding, enabling systems built around LLMs to access and operate on existing codebases to handle more complex tasks, such as refactoring or porting. They can even be used to build an entire codebase from scratch, given sufficient information such as specifications or implementation plans.&lt;/p&gt;
&lt;p&gt;As software has become one of the primary research tools across all disciplines, a significant majority of scientific results rely on the quality of that software. RSEs emerged as a result: by combining professional software engineering expertise with an intimate understanding of the research discipline, partnerships between RSEs and researchers allowed software to evolve along with research, with RSEs guiding the productive application of methods and technologies and ensuring that software meets the reliability and reproducibility standards that are expected from scientific instruments. This unique position of RSEs bridging software engineering and research was often depicted in diagrams similar to Figure 1, which shows that RSEs vary in their skills and knowledge of both software engineering and research activities. It also shows RSE-adjacent roles (such as software engineer, researcher, and researcher who codes) to provide context, illustrating that RSEs have more software engineering experience than researchers, while also possessing a deeper understanding of research practices than software engineers. Diagrams like these have been very important tools in achieving (pre-GenAI) understanding of the value provided by RSEs, to the extent that RSEs are supported by national initiatives such as those in the UK, the Netherlands and Germany [16], [17], [18].&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;680&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-4c402b8d.DHWN-me0_Z101yE7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: RSEs bring both software engineering and research expertise.With the advent of GenAI, two questions arise: Is this partnership between RSEs and researchers still needed and still valuable? And, how do these roles change? In the age of GenAI, both researchers and RSEs have access to LLMs and coding agents to accelerate their work. Researchers are able to prototype and explore ideas faster and more freely than before. Meanwhile, RSEs are able to use these GenAI tools to greater effect and impact, due to their expertise in software engineering, particularly in requirements engineering and specification, software architecture, testing and verification, validation, performance, and long-term sustainability. This enables them to frame problems more precisely, to evaluate tradeoffs and verify internal correctness and consistency more effectively, and to better address longstanding challenges in research software. Moreover, their continued and frequent practice with these tools compounds their advantages, allowing them to better anticipate failure modes, enforce quality standards, and integrate tooling into complex, evolving research environments.&lt;/p&gt;
&lt;p&gt;RSEs who maintain GenAI literacy and the ability to critically evaluate complex software stacks are especially indispensable in view of the risks associated with the increasing adoption of GenAI in research software development. In particular, when researchers use agentic coding tools without sufficient expertise and experience to write increasingly complex software, over-reliance on these tools risks generating a significant disconnect between the coder and the code. This disconnect can lead to the introduction of unintended errors and inaccuracies, and could pose serious risk to the robustness of related scientific outputs and research results. In this situation, RSEs are well positioned to provide the guidance and oversight that is necessary to ensure the safe adoption of AI in research software engineering.&lt;/p&gt;
&lt;p&gt;Taken together, the value of an RSE remains significant, as the RSE role evolves to integrate expert knowledge in the application of GenAI for software engineering in research contexts. This viewpoint is similarly articulated in the &lt;a href=&quot;https://github.com/Academic-Data-Science-Alliance/rse-ai-position-statement/blob/main/RSE-AI-Final_Statement.md&quot;&gt;Position Statement on Generative AI in the RSE Workplace&lt;/a&gt;[19], which is led by US-RSE and the Alliance for Data Science and AI. The Edinburgh workshop built upon this position statement, and it is also being shared in other conversations[20], [21]. As such, the value of RSEs in relation to researchers and other stakeholders will remain unchanged as their role as a research software professional evolves to also integrate expert knowledge in the application of GenAI in research contexts. This blog post seeks to move one step further in clearly articulating that value in a way that is easy to understand.&lt;/p&gt;
&lt;p&gt;Overall, the value of the RSE role shifts upward as AI enhances it and amplifies its impact. While the practice may change and shift focus to higher levels of abstraction, including specification and verification, the value proposition remains the same**. This is depicted in Figure 2, which shows how the use of GenAI enables the value of RSEs to increase along both the software engineering and research activity axes. It is critical for the research community to understand and acknowledge this increased potential for research impact, and to ensure that going forward, RSE expertise is appropriately supported, funded and integrated into research ecosystems.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-e2e2857a.DtjkNNeC_1OdOGE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: AI can enable RSEs to increase their capacity for both research and software engineering, irrespective of specializations.Figure 3 highlights the unique position of RSEs in the research ecosystem. RSEs and other roles in the research sector (software engineers, researchers who code, and researchers) all evolve in response to leveraging GenAI tools, which affects all groups along the software engineering capacity axis to varying degrees. Researchers who have not previously done any programming can now generate their own code, but for all non-RSE roles these shifts largely reinforce strengths within their established areas of expertise. For RSEs, however, this evolution plays to their dual focus on both software engineering and research, so that the effective value of RSEs and their work is amplified, as GenAI enables them to provide (even) more and better software to support (even) more and better research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research Software Engineers in the Age of GenAI: Same Value, Changing Practice&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;589&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-6f0e3f69.Cs5ozV6X_ZRCakM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: How various roles are evolving in response to GenAI.&lt;strong&gt;Acknowledgements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;MB and DSK were supported to undertake this work as part of Schmidt Sciences grant G-25–69965.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Author biographies&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.linkedin.com/in/michelledbarker/&quot;&gt;Michelle Barker&lt;/a&gt; is Director of the Research Software Alliance and has extensive expertise in open science, the research software community, digital skills, and digital research infrastructure. As a sociologist, Michelle is passionate about building collaborative partnerships to achieve system change. She is a former Director of the Australian Research Data Commons, where she led the national research software infrastructure investment program.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/cosden&quot;&gt;Ian Cosden&lt;/a&gt; is the Senior Director of Research Software Engineering at Princeton University. He leads a team of research software engineers who complement multiple traditional academic research groups by offering embedded, long-term software development expertise. He spearheaded the formation of the RSE group in 2016 and has grown the group from an initial size of two FTEs, to a total of 37 FTEs as of May 2026. Ian is the current and founding chair of the steering committee for the United States Research Software Engineer (US-RSE) Association. Additionally, he is the principal investigator for Innovative Training Enabled by a Research Software Engineering Community of Trainers (INTERSECT), an NSF-funded project to develop and deliver RSE-led training events for current researchers interested in careers in research software engineering.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://sdruskat.net&quot;&gt;Stephan Druskat&lt;/a&gt; is a (Research) Software Engineering Researcher based in Berlin. His research focuses on requirements, constraints, policies and practices of software engineering in academic research contexts, such as software publication, citation and sustainability, as well as software metadata and software supply chains. He is a Fellow of the Software Sustainability Institute, co-founder of the Society for Research Software in Germany (de-RSE), and lead of the Citation File Format project.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/hainesr&quot;&gt;Robert Haines&lt;/a&gt; is Director of Research IT and an Honorary Lecturer at the University of Manchester, and a Fellow of the Software Sustainability Institute. He is one of the originators of the term “Research Software Engineer”, served for six years as an elected representative of the UK RSE Association, chaired the First Conference of Research Software Engineers in 2016, and was a founding trustee of the Society of Research Software Engineering. Robert’s research interests include software engineering, software sustainability, software use in open and reproducible research, software citation and credit, and career paths for software engineers and data scientists.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://danielskatz.org/&quot;&gt;Daniel S. Katz&lt;/a&gt; is Chief Scientist at the National Center for Supercomputing Applications, Research Professor in the Siebel School of Computing and Data Science, and Research Professor in the School of Information Sciences at the University of Illinois Urbana-Champaign. He works at the triple point of research software, people, and policy. He is a co-founder and current Associate Editor-in-Chief of the Journal of Open Source Software, co-founder of the US Research Software Engineer Association (US-RSE), and co-founder and steering committee chair of the Research Software Alliance (ReSA).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jshng-glasgow&quot;&gt;Joseph Shingleton&lt;/a&gt; is a Research Software Engineer at the University of Glasgow. His research explores how artificial intelligence can be safely and effectively applied to tasks in geospatial data science and research software engineering. He is the recipient of a UKRI Metascience AI Fellowship, focusing on how generative AI is shaping RSE practice and its consequences for the scientific process. He is also a Software Sustainability Institute Fellow and leads the SSI study group on responsible AI in RSE.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/benvanwerkhoven&quot;&gt;Ben van Werkhoven&lt;/a&gt; is assistant professor at Leiden University, where he heads the Accelerated Computing research group, focusing on making high-performance computing more energy-efficient and sustainable. He holds a PhD from VU Amsterdam on GPU-accelerated scientific computing (2014) and spent nearly a decade at the Netherlands eScience Center before joining Leiden in 2023. With over 15 years of GPU programming and optimization experience, Ben has worked on scientific applications ranging from microscopy and climate modeling to radio astronomy. He is also a co-founder of the Netherlands Research Software Engineers community (NL-RSE), advocating for the recognition of research software engineering as a professional discipline. At Leiden, he teaches High Performance Computing and Multiprocessor Programming, and serves as principal investigator on several research projects. He participates in major European and national consortia, including CORTEX and ESiWACE, advancing large-scale computing infrastructure for science.&lt;/p&gt;
&lt;p&gt;References**&lt;/p&gt;
&lt;p&gt;[1] M. Hosseini, S. P. J. M. Horbach, K. L. Holmes, and T. Ross-Hellauer, ‘Open Science at the Generative AI Turn: An Exploratory Analysis of Challenges and Opportunities’, May 24, 2024, SocArXiv*. doi: 10.31235/osf.io/zns7g.&lt;/p&gt;
&lt;p&gt;[2] G. O’Brien, ‘Threats to scientific software from over-reliance on AI code assistants’, &lt;em&gt;Nat Comput Sci&lt;/em&gt;, vol. 5, no. 9, pp. 701–703, Jul. 2025, doi: 10.1038/s43588–025–00845–2.&lt;/p&gt;
&lt;p&gt;[3] S. Andleeb, B. Kantorski, and J. C. Carver, ‘ChatGPT in Introductory Programming: Counterbalanced Evaluation of Code Quality, Conceptual Learning, and Student Perceptions’, 2025, &lt;em&gt;arXiv&lt;/em&gt;. doi: 10.48550/ARXIV.2510.00946.&lt;/p&gt;
&lt;p&gt;[4] G. O’Brien, A. Parker, N. Eisty, and J. Carver, ‘A survey of generative AI adoption and perceived productivity among scientists who program’, Apr. 09, 2026, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2512.19644. doi: 10.48550/arXiv.2512.19644.&lt;/p&gt;
&lt;p&gt;[5] SAPEA, ‘Successful and timely uptake of artificial intelligence in science in the EU: evidence review report’, SAPEA, Apr. 2024. doi: 10.5281/ZENODO.10977676.&lt;/p&gt;
&lt;p&gt;[6] M.-A. Storey, ‘From Technical Debt to Cognitive and Intent Debt: Rethinking Software Health in the Age of AI’, Apr. 06, 2026, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2603.22106. doi: 10.48550/arXiv.2603.22106.&lt;/p&gt;
&lt;p&gt;[7] R. Choudhuri, D. Liu, I. Steinmacher, M. Gerosa, and A. Sarma, ‘How Far Are We? The Triumphs and Trials of Generative AI in Learning Software Engineering’, in &lt;em&gt;Proceedings of the IEEE/ACM 46th International Conference on Software Engineering&lt;/em&gt;, Lisbon Portugal: ACM, Apr. 2024, pp. 1–13. doi: 10.1145/3597503.3639201.&lt;/p&gt;
&lt;p&gt;[8] M. Koren, G. Békés, J. Hinz, and A. Lohmann, ‘Vibe Coding Kills Open Source’, Jan. 21, 2026, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2601.15494. doi: 10.48550/arXiv.2601.15494.&lt;/p&gt;
&lt;p&gt;[9] S. A. Besser, E. A. Jensen, and D. S. Katz, ‘How generative AI is shaping research software development and maintenance at a research-intensive university’, &lt;em&gt;Open Res Europe&lt;/em&gt;, vol. 6, p. 56, Feb. 2026, doi: 10.12688/openreseurope.22009.1.&lt;/p&gt;
&lt;p&gt;[10] D. R. Newman-Griffis, ‘AI thinking and the enterprise of science’, Jun. 25, 2023, &lt;em&gt;Open Science Framework&lt;/em&gt;. doi: 10.31219/osf.io/wb83e.&lt;/p&gt;
&lt;p&gt;[11] D. Salah, ‘Invisible Risks, Visible Code: A Vision for Understanding Ethical Debt in AI-Based Coding’, in &lt;em&gt;2025 ACM/IEEE International Symposium on Empirical Software Engineering and Measurement (ESEM)&lt;/em&gt;, Honolulu, HI, USA: IEEE, Oct. 2025, pp. 442–446. doi: 10.1109/ESEM64174.2025.00074.&lt;/p&gt;
&lt;p&gt;[12] E. W. Bridgeford &lt;em&gt;et al.&lt;/em&gt;, ‘Ten Simple Rules for AI-Assisted Coding in Science’, Oct. 31, 2025, &lt;em&gt;arXiv&lt;/em&gt;: arXiv:2510.22254. doi: 10.48550/arXiv.2510.22254.&lt;/p&gt;
&lt;p&gt;[13] L. C. McInnes &lt;em&gt;et al.&lt;/em&gt;, ‘Report of the 2025 Workshop on Next-Generation Ecosystems for Scientific Computing: Harnessing Community, Software, and AI for Cross-Disciplinary Team Science’, 2025, &lt;em&gt;arXiv&lt;/em&gt;. doi: 10.48550/ARXIV.2510.03413.&lt;/p&gt;
&lt;p&gt;[14] L. Nordling, ‘How ChatGPT is transforming the postdoc experience’, &lt;em&gt;Nature&lt;/em&gt;, vol. 622, no. 7983, pp. 655–657, Oct. 2023, doi: 10.1038/d41586–023–03235–8.&lt;/p&gt;
&lt;p&gt;[15] G. O’Brien, ‘How Scientists Use Large Language Models to Program’, in &lt;em&gt;Proceedings of the 2025 CHI Conference on Human Factors in Computing Systems&lt;/em&gt;, Yokohama Japan: ACM, Apr. 2025, pp. 1–16. doi: 10.1145/3706598.3713668.&lt;/p&gt;
&lt;p&gt;[16] M. Barker &lt;em&gt;et al.&lt;/em&gt;, ‘Software and skills for research computing in the UK’, Zenodo, Jan. 2024. doi: 10.5281/ZENODO.10473186.&lt;/p&gt;
&lt;p&gt;[17] D. Kempf &lt;em&gt;et al.&lt;/em&gt;, ‘Establishing central Research Software Engineering units in German research institutions’, 2025, [Online]. Available: &lt;a href=&quot;https://de-rse.org/2023_paper-RSE-groups/paper.pdf&quot;&gt;https://de-rse.org/2023_paper-RSE-groups/paper.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[18] LCRDM, ‘Professionalizing the role of Research Software Engineers in the Netherlands’, Zenodo, Mar. 2025. doi: 10.5281/ZENODO.15019998.&lt;/p&gt;
&lt;p&gt;[19] ADSA and US-RSE, ‘Position Statement on Generative AI in the RSE Workplace’. Accessed: Apr. 28, 2026. [Online]. Available: &lt;a href=&quot;https://github.com/Academic-Data-Science-Alliance/rse-ai-position-statement/blob/main/RSE-AI-Final_Statement.md&quot;&gt;https://github.com/Academic-Data-Science-Alliance/rse-ai-position-statement/blob/main/RSE-AI-Final_Statement.md&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[20] S. Gesing, ‘RSEs 2035: Surviving or Thriving in the Age of AI’, in &lt;em&gt;2025 IEEE International Conference on eScience (eScience)&lt;/em&gt;, Chicago, IL, USA: IEEE, Sep. 2025, pp. 381–382. doi: 10.1109/eScience65000.2025.00081.&lt;/p&gt;
&lt;p&gt;[21] P. Leather, D. Silver, and S. Frezza, ‘Software engineering role archetypes’, presented at the IEEE SWEBOK Summit 2026, Apr. 2026. [Online]. Available: &lt;a href=&quot;https://conf.researchr.org/details/icse-2026/swebok-2026/5/Talk-Software-engineering-role-archetypes-mapping-knowledge-skills-and-competenci&quot;&gt;https://conf.researchr.org/details/icse-2026/swebok-2026/5/Talk-Software-engineering-role-archetypes-mapping-knowledge-skills-and-competenci&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/research-software-engineers-in-the-age-o-4c402b8d.DHWN-me0.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing</title><link>https://blog2.esciencecenter.nl/posts/2026-05-15---co-designing-a-roadmap-for-training-on-research-software-tem</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-05-15---co-designing-a-roadmap-for-training-on-research-software-tem</guid><description>&lt;p&gt;Training materials are most effective when they are created hand-in-hand with the communities who will actually use them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-789c85ed.Ci1stTDr_ZSnt3j.webp&quot; srcset=&quot;&quot;&gt;
Photo of the eventBy &lt;a href=&quot;https://www.tudelft.nl/en/staff/m.g.garciaalvarez/&quot;&gt;Manuel G. Garcia&lt;/a&gt; and &lt;a href=&quot;https://people.utwente.nl/s.girgin&quot;&gt;Serkan Gigin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Training materials are most effective when they are created with the communities who will actually use them. Co-design brings together lived experience, local knowledge, and technical expertise, ensuring that learning resources are relevant, accessible, and grounded in real needs. During the Research Software Training Day 2026, we engaged with research software trainers from across the Netherlands to explore how training materials for &lt;a href=&quot;https://ss-nes.github.io/meta-template/&quot;&gt;Meta-Template&lt;/a&gt; and &lt;a href=&quot;https://github.com/SS-NES/code-auditor&quot;&gt;Code Auditor&lt;/a&gt; should be developed and delivered.&lt;/p&gt;
&lt;p&gt;This the story of our experience and the lessons we learned along the way:&lt;/p&gt;
&lt;p&gt;Meta-Template** is a tool for aligning software best practices across teams, groups, and organisations through software templates. These templates provide structure and boilerplate code for software projects, offering several key advantages for research software development: they reduce the time and barriers involved in setting up a new project, encourage the adoption of best practices such as the FAIR principles for software, and promote standardisation and consistency across projects within a research team, group, or organisation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-11fafa6b.TwqUPDLO_Z2uxTPU.webp&quot; srcset=&quot;&quot;&gt;
&lt;strong&gt;Code Auditor&lt;/strong&gt; is a conformity checking tool that provides insights into the structure and content of a research software project. When applied to a code base, such as a code repository, Code Auditor can identify missing or conflicting best practices, suggest solutions to the issues it detects, and generate conformity reports in both machine- and human-friendly formats. It can also be used to verify compliance with software management plans and, when integrated with software templating tools, enables automated corrections.&lt;/p&gt;
&lt;p&gt;These two tools complement each other. Meta-Template facilitates the adoption of software best practices from the very inception of a research software project, while Code Auditor helps monitor compliance with those practices at key points throughout the software lifecycle.&lt;/p&gt;
&lt;p&gt;To promote the adoption of these tools, we need training materials, such as tutorials, that introduce them to potential users, demonstrate their value, and attract collaborators to the open-source projects that maintain them. With this goal in mind, we consulted the Research Software Training community about which directions and approaches to follow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fact Sheet&lt;/strong&gt;** Participants: 16
Experience as trainners: beginners (1 year) to proficient (&gt; 5 years)
Location: Utrecht
Duration: 1.5 hours&lt;/p&gt;
&lt;h2 id=&quot;directions-for-training-tutorials&quot;&gt;Directions for Training Tutorials&lt;/h2&gt;
&lt;p&gt;Training tutorials can be developed in several directions. During our engagement with software trainers, we focused on understanding their preferences and opinions regarding two key questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How independent should training materials be from other training materials and initiatives?** Independent materials might be easier to develop and maintain, but risk being too niche to reach a broad pool of potential users. On the other hand, integrating materials with existing training programmes could provide good leverage to reach a wider audience, though it requires more coordination and effort.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Should training materials focus on the tools themselves, or on the research software development topics they relate to?&lt;/strong&gt; Tool-focused materials would have a narrower scope but highlight the capabilities of the tools in detail, while topic-focused materials would cover broader software topics, such as publishing research software, and introduce the tools as mechanisms to ease the workload.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;independence-vs-integration&quot;&gt;Independence vs Integration&lt;/h2&gt;
&lt;p&gt;Most trainers agreed that training materials for &lt;strong&gt;Meta-Template&lt;/strong&gt; and &lt;strong&gt;Code Auditor&lt;/strong&gt; should be developed as part of existing training programmes, taking advantage of established initiatives and institutional structures. However, some arguments in favour of &lt;em&gt;independent&lt;/em&gt; training highlighted that standalone materials could be shorter and use-case oriented, requiring less time investment from potential users. A few others acknowledged these arguments but felt that choosing a single direction might not be necessary, since both approaches offer advantages and drawbacks.&lt;/p&gt;
&lt;p&gt;Despite the differences in opinion, the discussion concluded with trainers agreeing that a good starting point would be to explore integrating materials into existing and related training initiatives.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;381&quot; height=&quot;690&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-a675afcf.D6VzIWth_1DSoT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;tool-focus-vs-topic-focus&quot;&gt;Tool Focus vs Topic Focus&lt;/h2&gt;
&lt;p&gt;A large majority of trainers agreed that training materials should be topic-focused. The strongest argument in favour was that topic-focused materials would emphasise the value of the tools within a particular use case or research domain, demonstrating how useful they can be in a specific context and therefore serving as a better strategy to attract users. The argument for tool-focused materials, on the other hand, emphasised that such materials could be shorter and concentrate on demonstrating the how-to of each tool. Those who favoured neither direction raised arguments similar to those in the discussion about independence vs integration.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;381&quot; height=&quot;690&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-b6184d88.CyNJMPeB_Z1quADR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;audiences-formats-and-collaborations&quot;&gt;Audiences, Formats, and Collaborations&lt;/h2&gt;
&lt;p&gt;In the final part of the workshop, trainers proposed ideas on three topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which audiences should the training materials target?&lt;/li&gt;
&lt;li&gt;Which formats would be most suitable?&lt;/li&gt;
&lt;li&gt;How can we attract collaborators to help develop materials?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most favoured ideas pointed towards targeting PhD candidates, MSc students, data support staff, and data repository managers, through on-site training sessions such as workshops. However, a wide range of ideas were proposed for each aspect — see Table 1.&lt;/p&gt;
&lt;p&gt;Regarding collaboration, the preferred approach was to organise on-site events, such as content-a-thons, where trainers work together on developing materials.&lt;/p&gt;
&lt;p&gt;Table 1. Ideas for addressing topics related to audiences, formats and collaborations for developing training materials for &lt;em&gt;&lt;a href=&quot;https://ss-nes.github.io/meta-template/&quot;&gt;&lt;em&gt;Meta-Template&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://github.com/SS-NES/code-auditor&quot;&gt;&lt;em&gt;Code Auditor&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1114&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-487b1948.BsSiTcH3_uDqG9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;The main takeaways from the workshop were as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work towards integrating training materials for the tools into existing initiatives, such as data and software training programmes, to leverage the opportunities they offer for reaching a wider audience.&lt;/li&gt;
&lt;li&gt;Topic-focused materials offer a strategic advantage in demonstrating the value of new tools such as Meta-Template and Code Auditor, which in turn helps attract new users.&lt;/li&gt;
&lt;li&gt;Prioritise PhD candidates, MSc students, and data/software support staff as target audiences, delivering training through on-site formats such as hands-on workshops.&lt;/li&gt;
&lt;li&gt;Trainers prefer collective efforts during on-site events, such as content-a-thons, for contributing to the development of training materials.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;contact&quot;&gt;Contact&lt;/h2&gt;
&lt;p&gt;If you would like to learn more about Meta-Template** and &lt;strong&gt;Code Auditor&lt;/strong&gt;, or explore how to use them in your own training activities, we would love to hear from you. We also warmly invite contributions from the community — whether by improving the existing materials, sharing feedback, or helping co-develop new training resources together.&lt;/p&gt;
&lt;p&gt;Dr. Manuel Garcia Alvarez
Research Software Engineer
TU Delft DCC
&lt;a href=&quot;mailto:m.g.garciaalvarez@tudelft.nl&quot;&gt;m.g.garciaalvarez@tudelft.nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dr. Serkan Girgin
Associate Professor
University of Twente, Faculty ITC
&lt;a href=&quot;mailto:s.girgin@utwente.nl&quot;&gt;s.girgin@utwente.nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The project “Best Practices for Sustainable Software” with file number ICT.TDCC.002.001 of the research programme NWO Implementation Plan for ICT Infrastructure for TDCC Bottleneck Projects is financed by the Dutch Research Council (NWO).&lt;/em&gt;&lt;/p&gt;</description><pubDate>Fri, 15 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Training materials are most effective when they are created hand-in-hand with the communities who will actually use them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-789c85ed.Ci1stTDr_ZSnt3j.webp&quot; srcset=&quot;&quot;&gt;
Photo of the eventBy &lt;a href=&quot;https://www.tudelft.nl/en/staff/m.g.garciaalvarez/&quot;&gt;Manuel G. Garcia&lt;/a&gt; and &lt;a href=&quot;https://people.utwente.nl/s.girgin&quot;&gt;Serkan Gigin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Training materials are most effective when they are created with the communities who will actually use them. Co-design brings together lived experience, local knowledge, and technical expertise, ensuring that learning resources are relevant, accessible, and grounded in real needs. During the Research Software Training Day 2026, we engaged with research software trainers from across the Netherlands to explore how training materials for &lt;a href=&quot;https://ss-nes.github.io/meta-template/&quot;&gt;Meta-Template&lt;/a&gt; and &lt;a href=&quot;https://github.com/SS-NES/code-auditor&quot;&gt;Code Auditor&lt;/a&gt; should be developed and delivered.&lt;/p&gt;
&lt;p&gt;This the story of our experience and the lessons we learned along the way:&lt;/p&gt;
&lt;p&gt;Meta-Template** is a tool for aligning software best practices across teams, groups, and organisations through software templates. These templates provide structure and boilerplate code for software projects, offering several key advantages for research software development: they reduce the time and barriers involved in setting up a new project, encourage the adoption of best practices such as the FAIR principles for software, and promote standardisation and consistency across projects within a research team, group, or organisation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-11fafa6b.TwqUPDLO_Z2uxTPU.webp&quot; srcset=&quot;&quot;&gt;
&lt;strong&gt;Code Auditor&lt;/strong&gt; is a conformity checking tool that provides insights into the structure and content of a research software project. When applied to a code base, such as a code repository, Code Auditor can identify missing or conflicting best practices, suggest solutions to the issues it detects, and generate conformity reports in both machine- and human-friendly formats. It can also be used to verify compliance with software management plans and, when integrated with software templating tools, enables automated corrections.&lt;/p&gt;
&lt;p&gt;These two tools complement each other. Meta-Template facilitates the adoption of software best practices from the very inception of a research software project, while Code Auditor helps monitor compliance with those practices at key points throughout the software lifecycle.&lt;/p&gt;
&lt;p&gt;To promote the adoption of these tools, we need training materials, such as tutorials, that introduce them to potential users, demonstrate their value, and attract collaborators to the open-source projects that maintain them. With this goal in mind, we consulted the Research Software Training community about which directions and approaches to follow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fact Sheet&lt;/strong&gt;** Participants: 16
Experience as trainners: beginners (1 year) to proficient (&gt; 5 years)
Location: Utrecht
Duration: 1.5 hours&lt;/p&gt;
&lt;h2 id=&quot;directions-for-training-tutorials&quot;&gt;Directions for Training Tutorials&lt;/h2&gt;
&lt;p&gt;Training tutorials can be developed in several directions. During our engagement with software trainers, we focused on understanding their preferences and opinions regarding two key questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How independent should training materials be from other training materials and initiatives?** Independent materials might be easier to develop and maintain, but risk being too niche to reach a broad pool of potential users. On the other hand, integrating materials with existing training programmes could provide good leverage to reach a wider audience, though it requires more coordination and effort.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Should training materials focus on the tools themselves, or on the research software development topics they relate to?&lt;/strong&gt; Tool-focused materials would have a narrower scope but highlight the capabilities of the tools in detail, while topic-focused materials would cover broader software topics, such as publishing research software, and introduce the tools as mechanisms to ease the workload.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;independence-vs-integration&quot;&gt;Independence vs Integration&lt;/h2&gt;
&lt;p&gt;Most trainers agreed that training materials for &lt;strong&gt;Meta-Template&lt;/strong&gt; and &lt;strong&gt;Code Auditor&lt;/strong&gt; should be developed as part of existing training programmes, taking advantage of established initiatives and institutional structures. However, some arguments in favour of &lt;em&gt;independent&lt;/em&gt; training highlighted that standalone materials could be shorter and use-case oriented, requiring less time investment from potential users. A few others acknowledged these arguments but felt that choosing a single direction might not be necessary, since both approaches offer advantages and drawbacks.&lt;/p&gt;
&lt;p&gt;Despite the differences in opinion, the discussion concluded with trainers agreeing that a good starting point would be to explore integrating materials into existing and related training initiatives.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;381&quot; height=&quot;690&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-a675afcf.D6VzIWth_1DSoT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;tool-focus-vs-topic-focus&quot;&gt;Tool Focus vs Topic Focus&lt;/h2&gt;
&lt;p&gt;A large majority of trainers agreed that training materials should be topic-focused. The strongest argument in favour was that topic-focused materials would emphasise the value of the tools within a particular use case or research domain, demonstrating how useful they can be in a specific context and therefore serving as a better strategy to attract users. The argument for tool-focused materials, on the other hand, emphasised that such materials could be shorter and concentrate on demonstrating the how-to of each tool. Those who favoured neither direction raised arguments similar to those in the discussion about independence vs integration.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;381&quot; height=&quot;690&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-b6184d88.CyNJMPeB_Z1quADR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;audiences-formats-and-collaborations&quot;&gt;Audiences, Formats, and Collaborations&lt;/h2&gt;
&lt;p&gt;In the final part of the workshop, trainers proposed ideas on three topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which audiences should the training materials target?&lt;/li&gt;
&lt;li&gt;Which formats would be most suitable?&lt;/li&gt;
&lt;li&gt;How can we attract collaborators to help develop materials?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most favoured ideas pointed towards targeting PhD candidates, MSc students, data support staff, and data repository managers, through on-site training sessions such as workshops. However, a wide range of ideas were proposed for each aspect — see Table 1.&lt;/p&gt;
&lt;p&gt;Regarding collaboration, the preferred approach was to organise on-site events, such as content-a-thons, where trainers work together on developing materials.&lt;/p&gt;
&lt;p&gt;Table 1. Ideas for addressing topics related to audiences, formats and collaborations for developing training materials for &lt;em&gt;&lt;a href=&quot;https://ss-nes.github.io/meta-template/&quot;&gt;&lt;em&gt;Meta-Template&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://github.com/SS-NES/code-auditor&quot;&gt;&lt;em&gt;Code Auditor&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Co-Designing a Roadmap for Training on Research Software Templates and Code Auditing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1114&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-487b1948.BsSiTcH3_uDqG9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;/h2&gt;
&lt;p&gt;The main takeaways from the workshop were as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work towards integrating training materials for the tools into existing initiatives, such as data and software training programmes, to leverage the opportunities they offer for reaching a wider audience.&lt;/li&gt;
&lt;li&gt;Topic-focused materials offer a strategic advantage in demonstrating the value of new tools such as Meta-Template and Code Auditor, which in turn helps attract new users.&lt;/li&gt;
&lt;li&gt;Prioritise PhD candidates, MSc students, and data/software support staff as target audiences, delivering training through on-site formats such as hands-on workshops.&lt;/li&gt;
&lt;li&gt;Trainers prefer collective efforts during on-site events, such as content-a-thons, for contributing to the development of training materials.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;contact&quot;&gt;Contact&lt;/h2&gt;
&lt;p&gt;If you would like to learn more about Meta-Template** and &lt;strong&gt;Code Auditor&lt;/strong&gt;, or explore how to use them in your own training activities, we would love to hear from you. We also warmly invite contributions from the community — whether by improving the existing materials, sharing feedback, or helping co-develop new training resources together.&lt;/p&gt;
&lt;p&gt;Dr. Manuel Garcia Alvarez
Research Software Engineer
TU Delft DCC
&lt;a href=&quot;mailto:m.g.garciaalvarez@tudelft.nl&quot;&gt;m.g.garciaalvarez@tudelft.nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dr. Serkan Girgin
Associate Professor
University of Twente, Faculty ITC
&lt;a href=&quot;mailto:s.girgin@utwente.nl&quot;&gt;s.girgin@utwente.nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The project “Best Practices for Sustainable Software” with file number ICT.TDCC.002.001 of the research programme NWO Implementation Plan for ICT Infrastructure for TDCC Bottleneck Projects is financed by the Dutch Research Council (NWO).&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/co-designing-a-roadmap-for-training-on-r-11fafa6b.TwqUPDLO.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Provenance in the age of AI: Why we need AI Declarations for more transparency</title><link>https://blog2.esciencecenter.nl/posts/2026-04-23---provenance-in-the-age-of-ai-why-we-need-ai-declarations-for-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-04-23---provenance-in-the-age-of-ai-why-we-need-ai-declarations-for-</guid><description>&lt;p&gt;&lt;em&gt;In research, if our methodology is not transparent, our results are not verifiable. Using AI to help generate code or synthesize data is dramatically affecting transparency, sustainability and maintenance. But how can we make the AI involvement more transparent and traceable?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Provenance in the age of AI: Why we need AI Declarations for more transparency&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;382&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/provenance-in-the-age-of-ai-why-we-need--4b349da1.BX8llyxo_Z1yry4i.webp&quot; srcset=&quot;&quot;&gt;
This image was generated using Google Gemini 3.1. See the declaration file at the end of this blog post for more details.Before I started as a Research Software Engineer, I worked in a physical lab where the culture of provenance was absolute. You documented everything: the materials, the hardware, the exact version of the software you used to process the data, and so forth. Without that trail, the results were meaningless. You could not trust them, and you certainly could not reproduce them.&lt;/p&gt;
&lt;p&gt;Today, my “lab” is entirely digital, but the need for that same precision remains.&lt;/p&gt;
&lt;p&gt;Over the last two years, a new variable has entered our work. We are using Generative AI to suggest code refactors, autonomous agents to synthesize datasets, and generative models to draft technical reports. AI is no longer a separate tool we are experimenting with; it is already becoming a standard part of our daily routine.&lt;/p&gt;
&lt;p&gt;Today, when I download a dataset or review a colleague’s pull request, I have no way to know where the human logic ends and the model’s output begins. This ambiguity is a problem for scientific reliability. If we cannot trace the logic of an algorithm or the origin of a dataset, we lose reproducibility. If we cannot identify which parts of a codebase were generated by a model, we are building up a “maintenance debt” that will eventually come due. And if we ignore the compute cost of these models, we are ignoring the sustainability of our field.&lt;/p&gt;
&lt;p&gt;We built the &lt;a href=&quot;https://ai-declaration.org/&quot;&gt;AI Declaration Format**&lt;/a&gt;** (&lt;strong&gt;&lt;a href=&quot;https://ai-declaration.org/&quot;&gt;https://ai-declaration.org&lt;/a&gt;&lt;/strong&gt;)** to address this. Our goal is to make structured documentation of AI usage a standard, routine part of professional work.&lt;/p&gt;
&lt;h2 id=&quot;the-foundation-a-machine-readable-file-format&quot;&gt;The foundation: A machine-readable file format&lt;/h2&gt;
&lt;p&gt;The AI Declaration Format is the foundation: a machine-readable, general-purpose file format designed to describe AI involvement in any digital artifact. It does not matter if you are publishing software, a research paper, a dataset, or media; you can use the same structured approach to say how AI was involved.&lt;/p&gt;
&lt;p&gt;We designed the schema to be modular, so you can focus on the parts that matter for your project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Maintainability and Security:&lt;/strong&gt; You can track which modules were AI-assisted and document security reviews. Knowing which blocks of code were generated helps future maintainers understand the intent behind them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environmental Impact:&lt;/strong&gt; You can record compute hours and estimated carbon footprints. This turns “sustainability” into a measurable metric.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explainability and Governance:&lt;/strong&gt; For systems that interact with users, you can document technical decision logic or interpretability methods. You can also name responsible officers and link to internal ethics reviews.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Regulations (not just the EU Act):&lt;/strong&gt; With the EU AI Act, the US Executive Order, and other global frameworks, transparency is becoming a legal requirement. The AI Declaration Format lets you map your project to risk categories and link to the technical documentation these laws demand.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-another-format&quot;&gt;Why another format?&lt;/h2&gt;
&lt;p&gt;A common question is why we need a new format when standards like &lt;a href=&quot;https://spdx.github.io/spdx-spec/v3.0.1/model/AI/AI/&quot;&gt;SPDX 3.0 (AI Profile)&lt;/a&gt; and &lt;a href=&quot;https://cyclonedx.org/capabilities/mlbom&quot;&gt;CycloneDX (ML-BOM)&lt;/a&gt; already exist. The answer lies in the scope and the audience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SPDX and CycloneDX are “Bill of Materials” (SBoM) standards. They are designed for legal teams and security auditors to track every sub-component and vulnerability in a supply chain. They are powerful but often complex for an individual researcher or a small dev team.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codemeta.github.io/&quot;&gt;CodeMeta&lt;/a&gt; and &lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;CITATION.cff&lt;/a&gt; are useful for general project metadata and academic citations. However, they lack the specialized fields needed for AI transparency — such as risk classification, model versions, and human oversight.&lt;/li&gt;
&lt;li&gt;The AI Declaration Format is a declaration format, not a full inventory. It is designed to be human-writable and project-focused. It answers the specific question of &lt;em&gt;“How did the humans on this project use AI?”.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AI Declaration Format sits alongside these standards: it is the missing piece of the metadata puzzle that captures the usage and methodology of Generative AI.&lt;/p&gt;
&lt;h2 id=&quot;how-do-i-get-started&quot;&gt;How do I get started?&lt;/h2&gt;
&lt;p&gt;A standard is only useful if it is easy to adopt. We have built an ecosystem of tools and automation around the AI Declaration Format to ensure it fits into your existing workflow. We are also working on improving and extending this tooling, including GitHub/GitLab Actions and workflows to automate validation and updating as part of your CI/CD pipelines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://app.ai-declaration.org&quot;&gt;The Web App**&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; If you want a guided interface, we built a web app specifically to create these declaration files. It runs entirely in your browser, so your project data never hits our servers. You can generate an &lt;code&gt;aidecl.yaml&lt;/code&gt;, validate it, or look at examples from other fields.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ai-declaration/cli&quot;&gt;&lt;strong&gt;The CLI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; For those of us who live in the terminal, the &lt;code&gt;aidecl&lt;/code&gt; tool lets you initialize and validate declarations as part of your git workflow. It runs semantic checks to make sure your claims actually make sense—like flagging if you claim no AI was used but then list three models in your inventory.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;scientific-and-technical-standards&quot;&gt;Scientific and Technical Standards&lt;/h2&gt;
&lt;p&gt;In research, we document our hardware and our data sources because that is how we maintain the standard of our work. This is the bedrock of Open Science: if our methodology is not transparent, our results are not verifiable. Using AI to help generate code or synthesize data is simply another part of that methodology. It belongs in the formal record.&lt;/p&gt;
&lt;p&gt;Adding an &lt;code&gt;aidecl.yaml&lt;/code&gt; to your repository shows a commitment to open science principles. It is a way to make sure that the things we are building today will be MORE understandable, maintainable, and reproducible in future.&lt;/p&gt;
&lt;h2 id=&quot;join-the-effort&quot;&gt;Join the effort&lt;/h2&gt;
&lt;p&gt;We are in the early stages of this, and we need a community to make it a standard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Adopt:&lt;/strong&gt; Add an &lt;code&gt;aidecl.yaml&lt;/code&gt; to your next project. It takes about five minutes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Endorse:&lt;/strong&gt; If your lab or organization values AI transparency, we need early adopters to help build credibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contribute:&lt;/strong&gt; The schema and tools are open-source. Help us improve the validation rules or the web interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feedback:&lt;/strong&gt; We need to know how this works (or does not) for your specific field — whether that is genomics, legal tech, or creative media.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are all figuring this out as we go. As the technology changes and we get more feedback, the file format and the tools will evolve to keep up.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project page:&lt;/strong&gt; &lt;a href=&quot;https://ai-declaration.org&quot;&gt;ai-declaration.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub organization:&lt;/strong&gt; &lt;a href=&quot;https://github.com/ai-declaration&quot;&gt;github.com/ai-declaration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ai-declaration-aideclyaml-for-this-post&quot;&gt;AI Declaration (aidecl.yaml) for this post&lt;/h2&gt;
&lt;p&gt;schema_version: “1.0.0”
project:
name: “Provenance in the age of LLMs: Why we need AI Declarations”
version: “1.0.0”
content_type: “document”
license: “CC BY 4.0”
ai_usage:
used: true
summary: “Structured and refined by Gemini (LLM) based on human-provided themes, constraints, and source documentation.”
level: “moderate”
activities:
- content_drafting
- content_editing
tools:
- name: “Gemini”
vendor: “Google”
type: “assistant”
model: “gemini-3.1”
purpose:
- content_refining
- structural_organization
- image_generation
ai_proportion:
qualitative: mostly_human
method: self_reported
governance:
responsible_officer: “Faruk Diblen”
ethics_review_status: “not_applicable”
environmental:
compute_hours: 0.05
estimation_method: self_estimated
security:
review_performed: true
review_type:
- human_in_the_loop
declaration:
date: “2026-04-07”
declared_by: “Faruk Diblen”
organization: “Resoft Labs”&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;Thanks to [Flavio Hafner], [Carlos Martinez-Ortiz] and [Elena Ranguelova] for their feedback on the text and [Pablo Rodríguez-Sánchez] and [Alexander Hadjiivanov] for their editorial support.&lt;/p&gt;</description><pubDate>Thu, 23 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;In research, if our methodology is not transparent, our results are not verifiable. Using AI to help generate code or synthesize data is dramatically affecting transparency, sustainability and maintenance. But how can we make the AI involvement more transparent and traceable?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Provenance in the age of AI: Why we need AI Declarations for more transparency&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;382&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/provenance-in-the-age-of-ai-why-we-need--4b349da1.BX8llyxo_Z1yry4i.webp&quot; srcset=&quot;&quot;&gt;
This image was generated using Google Gemini 3.1. See the declaration file at the end of this blog post for more details.Before I started as a Research Software Engineer, I worked in a physical lab where the culture of provenance was absolute. You documented everything: the materials, the hardware, the exact version of the software you used to process the data, and so forth. Without that trail, the results were meaningless. You could not trust them, and you certainly could not reproduce them.&lt;/p&gt;
&lt;p&gt;Today, my “lab” is entirely digital, but the need for that same precision remains.&lt;/p&gt;
&lt;p&gt;Over the last two years, a new variable has entered our work. We are using Generative AI to suggest code refactors, autonomous agents to synthesize datasets, and generative models to draft technical reports. AI is no longer a separate tool we are experimenting with; it is already becoming a standard part of our daily routine.&lt;/p&gt;
&lt;p&gt;Today, when I download a dataset or review a colleague’s pull request, I have no way to know where the human logic ends and the model’s output begins. This ambiguity is a problem for scientific reliability. If we cannot trace the logic of an algorithm or the origin of a dataset, we lose reproducibility. If we cannot identify which parts of a codebase were generated by a model, we are building up a “maintenance debt” that will eventually come due. And if we ignore the compute cost of these models, we are ignoring the sustainability of our field.&lt;/p&gt;
&lt;p&gt;We built the &lt;a href=&quot;https://ai-declaration.org/&quot;&gt;AI Declaration Format**&lt;/a&gt;** (&lt;strong&gt;&lt;a href=&quot;https://ai-declaration.org/&quot;&gt;https://ai-declaration.org&lt;/a&gt;&lt;/strong&gt;)** to address this. Our goal is to make structured documentation of AI usage a standard, routine part of professional work.&lt;/p&gt;
&lt;h2 id=&quot;the-foundation-a-machine-readable-file-format&quot;&gt;The foundation: A machine-readable file format&lt;/h2&gt;
&lt;p&gt;The AI Declaration Format is the foundation: a machine-readable, general-purpose file format designed to describe AI involvement in any digital artifact. It does not matter if you are publishing software, a research paper, a dataset, or media; you can use the same structured approach to say how AI was involved.&lt;/p&gt;
&lt;p&gt;We designed the schema to be modular, so you can focus on the parts that matter for your project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Maintainability and Security:&lt;/strong&gt; You can track which modules were AI-assisted and document security reviews. Knowing which blocks of code were generated helps future maintainers understand the intent behind them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environmental Impact:&lt;/strong&gt; You can record compute hours and estimated carbon footprints. This turns “sustainability” into a measurable metric.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explainability and Governance:&lt;/strong&gt; For systems that interact with users, you can document technical decision logic or interpretability methods. You can also name responsible officers and link to internal ethics reviews.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Regulations (not just the EU Act):&lt;/strong&gt; With the EU AI Act, the US Executive Order, and other global frameworks, transparency is becoming a legal requirement. The AI Declaration Format lets you map your project to risk categories and link to the technical documentation these laws demand.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-another-format&quot;&gt;Why another format?&lt;/h2&gt;
&lt;p&gt;A common question is why we need a new format when standards like &lt;a href=&quot;https://spdx.github.io/spdx-spec/v3.0.1/model/AI/AI/&quot;&gt;SPDX 3.0 (AI Profile)&lt;/a&gt; and &lt;a href=&quot;https://cyclonedx.org/capabilities/mlbom&quot;&gt;CycloneDX (ML-BOM)&lt;/a&gt; already exist. The answer lies in the scope and the audience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SPDX and CycloneDX are “Bill of Materials” (SBoM) standards. They are designed for legal teams and security auditors to track every sub-component and vulnerability in a supply chain. They are powerful but often complex for an individual researcher or a small dev team.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://codemeta.github.io/&quot;&gt;CodeMeta&lt;/a&gt; and &lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;CITATION.cff&lt;/a&gt; are useful for general project metadata and academic citations. However, they lack the specialized fields needed for AI transparency — such as risk classification, model versions, and human oversight.&lt;/li&gt;
&lt;li&gt;The AI Declaration Format is a declaration format, not a full inventory. It is designed to be human-writable and project-focused. It answers the specific question of &lt;em&gt;“How did the humans on this project use AI?”.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AI Declaration Format sits alongside these standards: it is the missing piece of the metadata puzzle that captures the usage and methodology of Generative AI.&lt;/p&gt;
&lt;h2 id=&quot;how-do-i-get-started&quot;&gt;How do I get started?&lt;/h2&gt;
&lt;p&gt;A standard is only useful if it is easy to adopt. We have built an ecosystem of tools and automation around the AI Declaration Format to ensure it fits into your existing workflow. We are also working on improving and extending this tooling, including GitHub/GitLab Actions and workflows to automate validation and updating as part of your CI/CD pipelines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://app.ai-declaration.org&quot;&gt;The Web App**&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; If you want a guided interface, we built a web app specifically to create these declaration files. It runs entirely in your browser, so your project data never hits our servers. You can generate an &lt;code&gt;aidecl.yaml&lt;/code&gt;, validate it, or look at examples from other fields.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ai-declaration/cli&quot;&gt;&lt;strong&gt;The CLI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; For those of us who live in the terminal, the &lt;code&gt;aidecl&lt;/code&gt; tool lets you initialize and validate declarations as part of your git workflow. It runs semantic checks to make sure your claims actually make sense—like flagging if you claim no AI was used but then list three models in your inventory.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;scientific-and-technical-standards&quot;&gt;Scientific and Technical Standards&lt;/h2&gt;
&lt;p&gt;In research, we document our hardware and our data sources because that is how we maintain the standard of our work. This is the bedrock of Open Science: if our methodology is not transparent, our results are not verifiable. Using AI to help generate code or synthesize data is simply another part of that methodology. It belongs in the formal record.&lt;/p&gt;
&lt;p&gt;Adding an &lt;code&gt;aidecl.yaml&lt;/code&gt; to your repository shows a commitment to open science principles. It is a way to make sure that the things we are building today will be MORE understandable, maintainable, and reproducible in future.&lt;/p&gt;
&lt;h2 id=&quot;join-the-effort&quot;&gt;Join the effort&lt;/h2&gt;
&lt;p&gt;We are in the early stages of this, and we need a community to make it a standard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Adopt:&lt;/strong&gt; Add an &lt;code&gt;aidecl.yaml&lt;/code&gt; to your next project. It takes about five minutes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Endorse:&lt;/strong&gt; If your lab or organization values AI transparency, we need early adopters to help build credibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contribute:&lt;/strong&gt; The schema and tools are open-source. Help us improve the validation rules or the web interface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feedback:&lt;/strong&gt; We need to know how this works (or does not) for your specific field — whether that is genomics, legal tech, or creative media.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are all figuring this out as we go. As the technology changes and we get more feedback, the file format and the tools will evolve to keep up.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project page:&lt;/strong&gt; &lt;a href=&quot;https://ai-declaration.org&quot;&gt;ai-declaration.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub organization:&lt;/strong&gt; &lt;a href=&quot;https://github.com/ai-declaration&quot;&gt;github.com/ai-declaration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ai-declaration-aideclyaml-for-this-post&quot;&gt;AI Declaration (aidecl.yaml) for this post&lt;/h2&gt;
&lt;p&gt;schema_version: “1.0.0”
project:
name: “Provenance in the age of LLMs: Why we need AI Declarations”
version: “1.0.0”
content_type: “document”
license: “CC BY 4.0”
ai_usage:
used: true
summary: “Structured and refined by Gemini (LLM) based on human-provided themes, constraints, and source documentation.”
level: “moderate”
activities:
- content_drafting
- content_editing
tools:
- name: “Gemini”
vendor: “Google”
type: “assistant”
model: “gemini-3.1”
purpose:
- content_refining
- structural_organization
- image_generation
ai_proportion:
qualitative: mostly_human
method: self_reported
governance:
responsible_officer: “Faruk Diblen”
ethics_review_status: “not_applicable”
environmental:
compute_hours: 0.05
estimation_method: self_estimated
security:
review_performed: true
review_type:
- human_in_the_loop
declaration:
date: “2026-04-07”
declared_by: “Faruk Diblen”
organization: “Resoft Labs”&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;Thanks to [Flavio Hafner], [Carlos Martinez-Ortiz] and [Elena Ranguelova] for their feedback on the text and [Pablo Rodríguez-Sánchez] and [Alexander Hadjiivanov] for their editorial support.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/provenance-in-the-age-of-ai-why-we-need--4b349da1.BX8llyxo.png" medium="image"/><author>Faruk Diblen</author></item><item><title>FOSDEM 2026: Observations and key takeaways</title><link>https://blog2.esciencecenter.nl/posts/2026-04-09---fosdem-2026-observations-and-key-takeaways</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-04-09---fosdem-2026-observations-and-key-takeaways</guid><description>&lt;p&gt;&lt;img alt=&quot;FOSDEM 2026: Observations and key takeaways&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/fosdem-2026-observations-and-key-takeawa-55dcce06.l9YVToEZ_ZsYfBF.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;If you missed FOSDEM 2026 — the largest conference dedicated to open-source software — you can still absorb some of the experience as shared by NLeSC RSEs &lt;strong&gt;Flavio Hafner&lt;/strong&gt;&lt;/em&gt;*, &lt;strong&gt;&lt;strong&gt;Ole Mussmann&lt;/strong&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;strong&gt;Faruk Diblen&lt;/strong&gt;&lt;/strong&gt;.*&lt;/p&gt;
&lt;h2 id=&quot;flavio-hafner-on-fosdem-2026-security-llms-and-software-performance&quot;&gt;Flavio Hafner on FOSDEM 2026: Security, LLMs, and Software Performance&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is a version of the &lt;em&gt;&lt;a href=&quot;https://f-hafner.github.io/fosdem-2026/&quot;&gt;&lt;em&gt;original post by Flavio&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; adapted for Medium.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My highlights from this year’s FOSDEM are in the areas of LLM/security/open source, in machine learning/software performance, and in databases/search.&lt;/p&gt;
&lt;h2 id=&quot;upcoming-features-in-git&quot;&gt;Upcoming features in git&lt;/h2&gt;
&lt;p&gt;Patrick Steinhardt from GitLab, and git contributor, &lt;a href=&quot;https://fosdem.org/2026/schedule/event/HTJK33-evolving_git_for_the_next_decade/&quot;&gt;presented&lt;/a&gt; about some upcoming changes, planned for the major 3.0 release towards mid-2026.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Under the hood, git changes the hashing algorithm from SHA-1 to SHA-256&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is because SHA-1 is not secure — a paper from around 2017 showed that it does not create unique hashes.&lt;/li&gt;
&lt;li&gt;While git itself does not rely on uniqueness of hashes, the ecosystem implicitly does — for instance, by pinning software dependencies to git hashes.&lt;/li&gt;
&lt;li&gt;At the same time, large parts of the ecosystem (GitHub for instance) currently do not support SHA-256 hashes.&lt;/li&gt;
&lt;li&gt;By moving the default in git, the contributors want to solve the chicken-and-egg problem of “no-one wanting to use the feature because no-one supports it” and vice versa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;New command: git history for easier rewriting of history&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In git, rewriting history through an interactive rebase is cumbersome and takes several steps.&lt;/li&gt;
&lt;li&gt;Another limitation is that it leads to orphaned branches because other branches depending on the changed commits are not updated. For instance, this makes is tedious to use workflows with stacked branches.&lt;/li&gt;
&lt;li&gt;The new &lt;code&gt;git history&lt;/code&gt; command, inspired by other version control systems such as Jujutsu and Mercurial, provides some functionality that makes such workflows easier. For instance, &lt;code&gt;git history reword &amp;#x26;lt;commit&amp;#x26;gt;&lt;/code&gt; allows to amend the commit message of a specific commit; &lt;code&gt;git history split &amp;#x26;lt;commit&amp;#x26;gt;&lt;/code&gt; allows to split a specific commit.&lt;/li&gt;
&lt;li&gt;The new commands &lt;em&gt;also&lt;/em&gt; rebase other branches that depend on respective commits.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;open-source-llms-and-security&quot;&gt;Open Source, LLMs, and security&lt;/h3&gt;
&lt;p&gt;This was a major topic in this year’s conference and featured in two keynotes: Michael Leenaars &lt;a href=&quot;https://fosdem.org/2026/schedule/event/FE7ULY-foss-in-times-of-war-scarcity-and-ai/&quot;&gt;(talk)&lt;/a&gt; from NLnet, and Daniel Stenberg, founder and lead developer of cURL &lt;a href=&quot;https://fosdem.org/2026/schedule/event/B7YKQ7-oss-in-spite-of-ai/&quot;&gt;(talk)&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both speakers highlighted that LLMs can help malicious actors find and exploit vulnerabilities in open-source code, and thus open-source will become more vulnerable to supply-chain attacks.&lt;/li&gt;
&lt;li&gt;Stenberg further detailed how LLMs bring out the worst and best at the same time. On one hand, the cURL project is bombarded by AI-generated security reports. This has led cURL to stop their bug bounty program. On the other hand, they use LLMs selectively to find security issues and review code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Several talks in the security devroom addressed the same problem.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Updated governance model for open-weight LLMs&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;a href=&quot;https://fosdem.org/2026/schedule/event/VGMUYA-the-open-weight-dilemma/&quot;&gt;talk&lt;/a&gt; about LLMs and cyber risks argued for an updated governance model for open-source (and maybe open-weight) LLMs.&lt;/li&gt;
&lt;li&gt;While closed LLMs are easily controllable, safeguards in open models can easily be fine-tuned away.&lt;/li&gt;
&lt;li&gt;Therefore, open LLMs cannot be regulated like an API, and closed LLMs may even have an advantage because they are easier to regulate — a “mitigation gap”.&lt;/li&gt;
&lt;li&gt;The proposed solution is to define fine-tuned models as “substantial modification”, and shift the liability burden from the issuer of the original model to the fine-tuner.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Auditing and securing supply chains&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Open Source Technology Improvement Fund (OSTIF) presented their work on providing security audits to open-source software &lt;a href=&quot;https://fosdem.org/2026/schedule/event/Z7D3MW-security_audits_and_security/&quot;&gt;(talk)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aboutcode.org/&quot;&gt;AboutCode&lt;/a&gt; presented their tool for detecting LLM-generated code &lt;a href=&quot;https://fosdem.org/2026/schedule/event/XGLP7J-ai-generated-code/&quot;&gt;(talk)&lt;/a&gt;. If I understood correctly, the tool finds parts of a codebase that have been regurgitated from another source, and can pinpoint to the source. One challenge was that LLMs often create similar control flow, but different variable names from the original. In their &lt;code&gt;scancode.io&lt;/code&gt; &lt;a href=&quot;https://github.com/aboutcode-org/scancode.io/&quot;&gt;tool&lt;/a&gt;, they solve this problem with code stemming, a method also used by &lt;code&gt;treesitter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-search-and-llms&quot;&gt;Data, Search and LLMs&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Vector search&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In a RAG pipeline, the hard part is data engineering: one has to understand the data and the context &lt;a href=&quot;https://fosdem.org/2026/schedule/event/DHTAXQ-prevent-ai-garbage/&quot;&gt;(talk)&lt;/a&gt;. For instance, the chunking strategy is crucial for the retrieved the results.&lt;/li&gt;
&lt;li&gt;Weaviate &lt;a href=&quot;https://fosdem.org/2026/schedule/event/3AWMQZ-multi-vector-embeddings-revolution-or-evolution/&quot;&gt;presented and demonstrated&lt;/a&gt; multi-vector retrieval. This is particularly useful for search on PDFs that include images. Their &lt;a href=&quot;https://github.com/weaviate/weaviate&quot;&gt;tool&lt;/a&gt; implements the MUVERA algorithm &lt;a href=&quot;https://arxiv.org/abs/2405.19504&quot;&gt;(paper)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Speeding up LLM inference&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The vLLM project &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/eldar_kurtic/&quot;&gt;explained&lt;/a&gt; how they speed up LLM inference with quantization and speculative decoding.&lt;/li&gt;
&lt;li&gt;Quantization compresses the network weights into buckets. This leads to a smaller footprint in memory and to faster transfer of the weights from the GPU’s high-bandwidth memory to the SRAM and Tensor cores that do the matrix multiplications.&lt;/li&gt;
&lt;li&gt;Their benchmarks show that the ideal strategy (4-bit integer quantization vs. 8-bit integer quantization vs. no quantization) depends on the number of queries per second.&lt;/li&gt;
&lt;li&gt;For speculative decoding, one trains a light-weight “speculator” model that generates tokens at inference time, and the main model approves or rejects the generated tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;machine-learning-performance-and-observability&quot;&gt;Machine learning, performance, and observability&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Performance engineering&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two talks discussed best practices for performance engineering: to reliably capture performance regressions, benchmarks should be repeatable and representative, and setting them up for this requires some thought. Challenges include isolating the benchmark environments and avoiding too many false positives.&lt;/li&gt;
&lt;li&gt;The first talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/8AS3XD-how-to-reliably-measure-software-performance/&quot;&gt;outlined&lt;/a&gt; a statistical testing approach based on increasing the signal-to-noise ratio and deciding when to reject the null hypothesis of no performance regression. Further, running benchmarks in the cloud poses challenges, and they recommend avoiding virtualized environments. The slides of the talk are &lt;a href=&quot;https://github.com/igoragoli/fosdem-2026-software-performance&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The second talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/YNB7KR-continuous-perf-engineering/&quot;&gt;focused&lt;/a&gt; on change point detection. I also liked the idea of using canaries to track the performance of the benchmark infrastructure itself — you want to know when the problem is with the infrastructure and when it is with your software.&lt;/li&gt;
&lt;li&gt;Both talks argued for continuous performance monitoring and presented some tools for this.&lt;code&gt;nyrkio&lt;/code&gt;provides CI runners for change point detection; the runners are not free but according to the provider, they are of better quality than other runners (such as &lt;code&gt;github-action-benchmark&lt;/code&gt;). &lt;a href=&quot;https://github.com/sharkdp/hyperfine&quot;&gt;hyperfine&lt;/a&gt; is a command-line benchmarking tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Performance monitoring of deep learning workloads on HPC&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Two talks addressed performance monitoring for deep learning workloads on HPC systems.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/&quot;&gt;highlighted&lt;/a&gt; the shortcomings of &lt;code&gt;nvidia-smi&lt;/code&gt; compared to &lt;code&gt;dcgmi&lt;/code&gt;. In short, the former only tells us &lt;em&gt;whether&lt;/em&gt; the GPUs are busy, but not &lt;em&gt;how efficiently&lt;/em&gt; they are being used (tensor cores, streaming multiprocessors, DRAM). One example was that using 32-bit and 16-bit precision on a H100 shows the same utilization on &lt;code&gt;nvidia-smi&lt;/code&gt;, even though FP32 is less efficient because H100s do not support tensor core computations with this precision.&lt;/li&gt;
&lt;li&gt;The same talk also suggested that running &lt;code&gt;dcgmi&lt;/code&gt; incurs no overhead because it is reading data that is already being tracked. I found useful docs from SURF &lt;a href=&quot;https://servicedesk.surf.nl/wiki/spaces/WIKI/pages/92668151/dcgmi+dmon&quot;&gt;here&lt;/a&gt;, and they are more cautious, mentioning that &lt;code&gt;dcgmi&lt;/code&gt; may slightly slow down your code. I guess one has to test and see it for themselves. The NVIDIA docs for &lt;code&gt;dcgmi&lt;/code&gt; are &lt;a href=&quot;https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/feature-overview.html#profiling-metrics&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The second talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/FYLDFE-observability_for_ai_workloads_on_hpc_beyond_gpu_utilization_metrics/&quot;&gt;presented&lt;/a&gt; an open-source observability dashboard for deep learning on HPC. It covers hardware, workload, and model health (such as gradient tracking). The &lt;a href=&quot;https://github.com/erythix4/HPCOBS&quot;&gt;tool&lt;/a&gt; was just released during the conference. I’m curious to see how it evolves and how it compares to other tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ole-mussmann-on-fosdem-2026-nix-international-oss-accessibility-and-collaboration&quot;&gt;Ole Mussmann on FOSDEM 2026: Nix, International OSS, Accessibility and Collaboration&lt;/h2&gt;
&lt;h3 id=&quot;opening&quot;&gt;Opening&lt;/h3&gt;
&lt;p&gt;A quote that hit hard:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If we lose our democracies, Open Source is irrelevant and goes away.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nothing to add here.&lt;/p&gt;
&lt;h3 id=&quot;nix-and-nixos&quot;&gt;Nix and NixOS&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;nix&lt;/code&gt; &lt;em&gt;&lt;strong&gt;for Determinism&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/bruce_gain/&quot;&gt;Bruce Gain&lt;/a&gt; discussed using &lt;code&gt;nix&lt;/code&gt; for “deterministic distributed-system benchmarking”. Without special care, library versions and kernel versions will drift over time. The low-hanging fruit &lt;code&gt;docker&lt;/code&gt; is not helping here. It solves packaging, not reproducibility, for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker&lt;/code&gt; uses the host’s kernel, and&lt;/li&gt;
&lt;li&gt;it is &lt;em&gt;really&lt;/em&gt; hard to make a container deterministic. &lt;code&gt;apt-get update&lt;/code&gt; is not reproducible, any unpinned library will drift over time. You could distribute the &lt;em&gt;images&lt;/em&gt; instead of &lt;code&gt;Dockerfile&lt;/code&gt;s, but those are huge and not meant to be changed (only appended).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;nix&lt;/code&gt; solves those issues by treating hashing and pinning every input of a project. Infrastructure is treated as a pure function. For identical inputs, the output &lt;em&gt;must&lt;/em&gt; be identical as well.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Software Bill of Materials (SBOM) Tools for &lt;code&gt;nix&lt;/code&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What’s inside your software package? Which dependencies do you use, and what’s &lt;em&gt;their&lt;/em&gt; dependencies? This surprisingly hard question is relevant for license compliance (did you obey the licenses of all libraries that you used?) as well as cybersecurity. If there’s a vulnerable package somewhere in the stack, you’d like to know, right? There’s a few tools that can help you out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nikstur/bombon&quot;&gt;https://github.com/nikstur/bombon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tiiuae/sbomnix&quot;&gt;https://github.com/tiiuae/sbomnix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/anchore/syft&quot;&gt;https://github.com/anchore/syft&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/determinatesystems&quot;&gt;Determinate Systems&lt;/a&gt; seem to have their own tool as well, but it does not seem to be public (yet?).&lt;/p&gt;
&lt;p&gt;Thanks for the heads up from &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/thecomputerguy&quot;&gt;Tristan “TheComputerGuy” Ross&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Sphinx&lt;/code&gt; &lt;em&gt;&lt;strong&gt;Documentation for &lt;code&gt;nix&lt;/code&gt; Code&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Sphinx&lt;/code&gt; was originally created as a documentation tool for &lt;code&gt;Python&lt;/code&gt; code, but it has since become a generic tool targeting all sorts of projects. &lt;a href=&quot;#7b6c&quot;&gt;[1]&lt;/a&gt; With &lt;a href=&quot;https://github.com/minijackson&quot;&gt;Rémi “minijackson”&lt;/a&gt; project &lt;code&gt;[sphinxcontrib-nixdomain](https://github.com/minijackson/sphinxcontrib-nixdomain)&lt;/code&gt; (rolls right off the tongue, doesn’t it?), one can document &lt;code&gt;nix&lt;/code&gt; options, modules, functions, package sets…&lt;/p&gt;
&lt;p&gt;This is the first time I see a structured approach to documenting a &lt;code&gt;nix&lt;/code&gt; project. Well done!&lt;/p&gt;
&lt;h3 id=&quot;international-open-source&quot;&gt;International Open Source&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Open Source in China&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Open Source looks different in China, says &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/richard_lin/&quot;&gt;Richard Lin&lt;/a&gt;. There are several factors at play:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FLOSS is seen as a market capture tool in three easy steps:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Turn standards into de facto rules,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rules into monopoly, and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Monopoly into profits.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Going global is not expansion, it’s survival.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The market in China is dry, so branching out is a necessity.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;FLOSS is a declaration, not procurement. The goal is to nurture industries that will enlarge future tax revenue, not buying a working product. The process for companies is:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Self-declare a directional FLOSS project,&lt;/li&gt;
&lt;li&gt;Build it,&lt;/li&gt;
&lt;li&gt;Pass inspection, and&lt;/li&gt;
&lt;li&gt;Receive cash.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Software development, even FLOSS, is a cathedral, not a bazaar.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Development is top-down.&lt;/li&gt;
&lt;li&gt;Pressure from the FLOSS community is slowly changing that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You might notice a lack of FLOSS culture. Instead of “software wants to be free”, this looks very market-driven. And yet, even through this lens, this flavor of open source looks better to me than closed source. It will be interesting to watch how FLOSS develops in China, and how the different viewpoints will evolve.&lt;/p&gt;
&lt;h3 id=&quot;accessibility&quot;&gt;Accessibility&lt;/h3&gt;
&lt;p&gt;I arrived late to &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/mike_gifford/&quot;&gt;Mike Gifford&lt;/a&gt;’s talk “Accessible Sovereignty: Why the Four Freedoms Depend on Inclusion”, so I can’t say much about the actual content. What &lt;em&gt;did&lt;/em&gt; impress me was that he had a live-transcription of his voice underneath the slides. That is not only terrific for the hard-of-hearing, but also a very comforting addition for everyone else.&lt;/p&gt;
&lt;p&gt;Lessons at the eScience Center often use web slides made with &lt;code&gt;[reveal.js](https://revealjs.com/)&lt;/code&gt;. Modern browsers have a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API&quot;&gt;Web Speech API&lt;/a&gt; which can be used for &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition&quot;&gt;speech recognition&lt;/a&gt;. Do you see where this is going…? Would it not be great to have a plugin for &lt;code&gt;reveal.js&lt;/code&gt; presentations that display speech-to-text below the slides? Any volunteers to build this? Anyone?&lt;/p&gt;
&lt;p&gt;Ok, fine. I’ll do it myself.&lt;/p&gt;
&lt;p&gt;P.S.: Here it is: &lt;a href=&quot;https://github.com/OleMussmann/RevealSubtitles&quot;&gt;https://github.com/OleMussmann/RevealSubtitles&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;collaboration&quot;&gt;Collaboration&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/tdpauw&quot;&gt;Thierry de Pauw&lt;/a&gt; makes an argument that pull requests are useful for open-source work, but are more of a hindrance in the corporate world. They were coaching a novice team of developers and, to make things simple, they introduced trunk-based development with Non-Blocking Continuous Code Reviews. This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Everything happens on the &lt;code&gt;main&lt;/code&gt; branch, there are no other branches.&lt;/li&gt;
&lt;li&gt;Changes are (automatically) tested before deployment.&lt;/li&gt;
&lt;li&gt;Every morning, developers review some commits.&lt;/li&gt;
&lt;li&gt;In the end, every commit will be reviewed, after* being deployed(!).&lt;/li&gt;
&lt;li&gt;Fixes are applied, if needed, though this is rare.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Woah.&lt;/p&gt;
&lt;p&gt;I can see this working for a very specific developer situation while having absolutely rock-solid tests. Distributed development? Difficult. Working on features, while keeping the &lt;code&gt;main&lt;/code&gt; branch stable? Impossible. Troubleshooting bugs, bisecting a commit history? Tough.&lt;/p&gt;
&lt;p&gt;This is probably not a good fit for research-software-engineering. But I have to say, kudos for trying something weird &lt;em&gt;and making it work&lt;/em&gt;. And as a side effect, I realize that I have to be more flexible with my assumptions about how to develop software. That alone is already worthwhile.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://documentation.help/Sphinx/index.html&quot;&gt;https://documentation.help/Sphinx/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;faruk-diblen-on-fosdem-2026-sovereignty-burnout-and-the-ai-reality-check&quot;&gt;Faruk Diblen on FOSDEM 2026: Sovereignty, Burnout, and the AI Reality Check&lt;/h2&gt;
&lt;p&gt;I hope that by providing this short summary, I can convince you to participate in the next FOSDEM. It remains the biggest and most awesome open-source conference in Europe — and it is still free. It is so large that it reminds me of certain free open-source software projects: it is full of a specific kind of chaos. This is not due to the organization, but rather the scale of the conference and the range of topics and talks happening simultaneously. I must give kudos to the organizers for doing an amazing job.&lt;/p&gt;
&lt;h3 id=&quot;reflections-on-ai-and-the-community&quot;&gt;Reflections on AI and the Community&lt;/h3&gt;
&lt;p&gt;As I do every year, I was expecting amazing talks from people who are very passionate about open source and “geeky” topics. However, this time I also expected to hear more about how AI is supporting software development. Instead, most talks focused on how AI is dangerous and toxic for open source.&lt;/p&gt;
&lt;p&gt;I think I partly agree with that sentiment, but it may still be useful for certain tasks as a supporting tool. There were many interesting talks and discussions regarding the cultural, ethical, legal, and technological effects of recent developments in AI.&lt;/p&gt;
&lt;p&gt;The infamous &lt;a href=&quot;https://xkcd.com/2347/&quot;&gt;xkcd comic about infrastructure&lt;/a&gt; was also compulsory for all speakers to show. Perhaps the organizers were checking presentations beforehand, and if you did not have this comic, they were not allowing you to present. Jokes aside, I also agree now that this comic represents the current reality; it is perhaps even too modest.&lt;/p&gt;
&lt;h3 id=&quot;networking-and-the-research-track&quot;&gt;Networking and the Research Track&lt;/h3&gt;
&lt;p&gt;One of the other fun parts of FOSDEM is the chance to meet and have conversations with great minds, contributors, and initiators of very impactful open-source projects. Like previous years, I gathered new ideas and identified new potential collaboration opportunities. I should not skip the “fun stands”; you can talk to the amazing groups of people who made your favorite Linux distribution or who are working on drone development.&lt;/p&gt;
&lt;p&gt;As a researcher, I also had a chance to follow some of the &lt;a href=&quot;https://fosdem.org/2026/schedule/track/open-research/&quot;&gt;Open Research&lt;/a&gt; track. Although the research community was under-represented, it had a great variety of interesting topics, some of which are relevant to my own work. My positive experience has made me think about submitting a proposal for next year. For the other talks I followed or found interesting but could not attend in person, please see the &lt;a href=&quot;#72d3&quot;&gt;Highlights**&lt;/a&gt; section below.&lt;/p&gt;
&lt;p&gt;After leaving the conference, I had three things in my mind: sovereignty now, sovereignty in the near future, and sovereignty in the far future. I also deeply felt the messages of “AI is killing Open Source,” “Even if AI gets better, we, the developers, will be needed,” and “Everything will collapse if we do not support open source.” These messages were sometimes subliminal and sometimes mentioned openly.&lt;/p&gt;
&lt;h3 id=&quot;keynotes&quot;&gt;Keynotes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeynote-foss-in-times-of-war%2F&quot;&gt;&lt;strong&gt;FOSDEM 2026 — FOSS in times of war, scarcity and (adversarial) AI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Given by Michiel Leenaards, our neighbor next door. I was expecting him to talk about how NLnet supports open-source software, but he focused on the threats caused by geopolitics. Given the recent political changes in many countries, I think it was a wisely chosen topic that forces us to think about upcoming challenges.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeynote-free-as-in-burned-out%2F&quot;&gt;&lt;strong&gt;FOSDEM 2026 — Free as in Burned Out: Who Really Pays for Open Source?&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Marga Manterola, a long-time Debian developer, talked about why the “donations and sponsorships” model is failing maintainers. She listed common funding sources including a sort of “Open Source tax.” This talk may help us find solutions for software maintenance and sustainability funds.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeynote-security-in-spite-of-ai%2F&quot;&gt;&lt;strong&gt;Open Source Security in spite of AI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; This was the most fun keynote, given by Daniel Stenberg. He told the story of the cURL project and his fight with issues and pull requests created by LLMs. Eventually, they decided to stop their Bug Bounty program. You can download the talk by using the &lt;code&gt;curl&lt;/code&gt; command below:** &lt;code&gt;curl https://ftp.belnet.be/mirror/FOSDEM/video/2026/janson/B7YKQ7-oss-in-spite-of-ai.av1.webm --output curl_keynote.webm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;highlights&quot;&gt;Highlights&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(The talks I liked the most)&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Frrp-reproducible-research-platform%2F&quot;&gt;RRP: Reproducible Research Platform for FAIR Open Research**&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Andreas Cuny showcased the RRP: a heavyweight solution combining openBIS (RDMS), Git, Docker, and Kubernetes. It allows users to mount datasets into Jupyter/VS Code environments instantly. It is a bit complex to set up, but powerful for institutions. I had a very pleasant conversation with Andreas regarding potential collaborations, such as adding actual FAIR software checks (via &lt;code&gt;howfairis&lt;/code&gt;) to their platform.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fwho-funds-the-egg%2F&quot;&gt;&lt;strong&gt;Who Funds the Egg? Cracking the FOSS Funding Paradox&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Deborah Udoh highlighted the “chicken and egg” problem: you need impact to get funding, but you need funding to create impact. The “Pre-seeds” concept — non-monetary investments like visibility and mentorship — seems like a viable bridge for early-stage projects.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fmultimodal-support-in-llamacpp%2F&quot;&gt;&lt;strong&gt;Multimodal support in llama.cpp — Achievements and Future Directions&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Huge updates for local AI. &lt;code&gt;libmtmd&lt;/code&gt; finally standardizes multimodal support. They showed &lt;code&gt;llama-mtmd-cli&lt;/code&gt; doing low-latency OCR and experimental audio input with Ultravox.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fits-time-to-audit-open-source%2F&quot;&gt;&lt;strong&gt;It’s Time to Audit Open Source: Success Stories with OSTIF&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; OSTIF has now facilitated over 100 security audits for projects like git, cURL, and Kubernetes. The data shows that independent code review works.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fsupply-chain-security-meets-ai%2F&quot;&gt;&lt;strong&gt;Supply chain security meets AI: Detecting AI-generated code&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Philippe Ombredanne introduced a new tool for “fuzzy matching” code snippets to detect AI-generated content. With bots writing billions of lines of code, exact hashing does not work any more.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fthe-ai-shockwave%2F&quot;&gt;&lt;strong&gt;The AI Shockwave in Open Source Communities: How AI Is Reshaping the Foundations of Open Source Communities&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A worrying trend where newbie questions are dropping because people ask ChatGPT instead. This breaks the “contributor pipeline.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fburnout-in-open-source%2F&quot;&gt;&lt;strong&gt;Burnout in Open Source: A Structural Problem We Can Fix Together&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Miranda Heath identified “hyper-responsibility” and “toxic entitlement” as key burnout drivers. We need structural changes in how we value maintenance work.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fintroducing-jupyter-book-2%2F&quot;&gt;&lt;strong&gt;Introducing Jupyter Book 2: Next-generation Tools for Creating Computational Narratives&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A complete rewrite based on the MyST (Markedly Structured Text) engine. It produces semantic, machine-readable content that is much easier to cross-reference.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fparticleos-from-fedora-to-feast%2F&quot;&gt;&lt;strong&gt;ParticleOS, from Fedora to Feast: Stirring Traditional Distros into Immutable Delights&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Luca Boccassi showed how &lt;code&gt;systemd&lt;/code&gt; and &lt;code&gt;mkosi&lt;/code&gt; are changing OS building, creating a fully immutable, signed, and verifiable image.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fwhat-do-we-mean-sovereign-ai%2F&quot;&gt;&lt;strong&gt;What do we mean when we say Sovereign AI?&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Katharine Jarmul explained that true “Sovereign AI” is not just about where the model is hosted, but having the full training data and code available to inspect.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;other-notable-tracks-and-talks&quot;&gt;Other Notable Tracks and Talks&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Research &amp;#x26; Science&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Frse-movement-uiuc%2F&quot;&gt;Research software engineering: a movement and its instantiation at the University of Illinois Urbana-Champaign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fresearch-software-funding-models%2F&quot;&gt;Research software grant funding models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fbuilding-open-research-infrastructure%2F&quot;&gt;Building Open Research Infrastructure: Connecting the Lab Bench to Computational Analysis with RSpace &amp;#x26; Galaxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fharnessing-nix-for-bioinformatics%2F&quot;&gt;Building Everything with Nothing — Harnessing Nix for Bioinformatics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fgems-high-level-language%2F&quot;&gt;From Code to Models-as-Data: GEMS, a High-Level Language for Energy System Modelling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fopen-reproducible-ai-lmics%2F&quot;&gt;Building Open and Reproducible AI Practices for LMICs (and Beyond)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fcern-adaptyst%2F&quot;&gt;Towards unified full-stack performance analysis and automated computer system design at CERN with Adaptyst&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Foqtopus-quantum-toolchain%2F&quot;&gt;OQTOPUS: Open Quantum Toolchain for OPerators and USers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fskills-floss-developer%2F&quot;&gt;The Skills of a FLOSS Developer and Why They Are Important in Open Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Ftrusted-by-design%2F&quot;&gt;Trusted by design: set up your research software for community adoption&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Main Track &amp;#x26; Community&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fefficient-git-workflow%2F&quot;&gt;An Efficient Git Workflow For High-Stakes Projects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeep-open-source-open%2F&quot;&gt;How to keep Open Source open without leaving our communities open to threats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fstrategy-trusting-employer%2F&quot;&gt;Strategy for Trusting your Employer in Open Source: a Historical Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fwho-pays-your-bills%2F&quot;&gt;Who Pays Your Bills? Sustainability, Community and Business: The Open Source Triangle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fnext-gen-postgres-contributors%2F&quot;&gt;Building the next generation of open source contributors — Lessons from 30 years of Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Ffunding-europe-digital-infra%2F&quot;&gt;Funding Europe’s Open Digital Infrastructure: A Detailed Case for an EU Sovereign Tech Fund&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2F32-years-debian%2F&quot;&gt;32 years of Debian: how a do-ocracy keeps evolving&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;AI &amp;#x26; Machine Learning&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Flow-code-ai-agents%2F&quot;&gt;Drag, Drop, and Deploy: Low-Code AI Agents for Network Ops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fself-hosted-llms%2F&quot;&gt;From Infrastructure to Production: A Year of Self-Hosted LLMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fai-security-monitoring%2F&quot;&gt;AI Security Monitoring: Detecting Threats Against Production ML Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fprevent-ai-garbage%2F&quot;&gt;How to Prevent Your AI from Returning Garbage: It Starts and Ends with Data Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fdeep-learning-snap%2F&quot;&gt;Deep Learning Demystified — Having Fun with Neural Networks in Snap!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Security, Databases &amp;#x26; Infrastructure&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fpost-quantum-cryptography%2F&quot;&gt;Demystifying Post-Quantum Cryptography: The Hybrid Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Flook-ma-no-secrets%2F&quot;&gt;Look ma, no secrets! — bootstrapping cryptographic trust in my homelab using NixOS, UKIs, TPMs and SPIFFE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Freal-time-ai-rondb%2F&quot;&gt;Real-Time AI Powered by RonDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fduckdb-bike-share%2F&quot;&gt;Exploring time series bike share data with duckdb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fopensearch-v3%2F&quot;&gt;OpenSearch v3: A New Era of Search Innovation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fsurf-research-cloud-oss%2F&quot;&gt;SURF Research Cloud is going OSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fguix-container-images%2F&quot;&gt;Guix Container Images — and what you can do with them&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;booths-and-extra-notes&quot;&gt;Booths and Extra Notes&lt;/h3&gt;
&lt;p&gt;After hearing about sovereignty everywhere, I had lengthy chats with the folks from &lt;strong&gt;GitLab, NextCloud, LibreOffice, Forgejo&lt;/strong&gt;, and &lt;strong&gt;Codeberg&lt;/strong&gt; to learn about open-source office solutions and infrastructure. I also talked to someone from Germany who explained the government migration to Linux (see: &lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Fwww.zdnet.com%2Farticle%2Fanother-european-government-is-ditching-microsoft-for-linux%2F&quot;&gt;Yet another European government is ditching Microsoft for Linux&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I visited the &lt;strong&gt;Tor&lt;/strong&gt; stand, where you could get fancy stickers if you donated to help them fight censorship. The &lt;strong&gt;Free Software Foundation Europe (FSFE)&lt;/strong&gt; is also worth following closely as their goals are related to our own. Finally, I learned about &lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffundingjs.org%2F&quot;&gt;&lt;strong&gt;funding.json&lt;/strong&gt;&lt;/a&gt;, a format to declare financial needs of projects in a machine-readable format.&lt;/p&gt;</description><pubDate>Thu, 09 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;FOSDEM 2026: Observations and key takeaways&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/fosdem-2026-observations-and-key-takeawa-55dcce06.l9YVToEZ_ZsYfBF.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;If you missed FOSDEM 2026 — the largest conference dedicated to open-source software — you can still absorb some of the experience as shared by NLeSC RSEs &lt;strong&gt;Flavio Hafner&lt;/strong&gt;&lt;/em&gt;*, &lt;strong&gt;&lt;strong&gt;Ole Mussmann&lt;/strong&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;strong&gt;Faruk Diblen&lt;/strong&gt;&lt;/strong&gt;.*&lt;/p&gt;
&lt;h2 id=&quot;flavio-hafner-on-fosdem-2026-security-llms-and-software-performance&quot;&gt;Flavio Hafner on FOSDEM 2026: Security, LLMs, and Software Performance&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is a version of the &lt;em&gt;&lt;a href=&quot;https://f-hafner.github.io/fosdem-2026/&quot;&gt;&lt;em&gt;original post by Flavio&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; adapted for Medium.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My highlights from this year’s FOSDEM are in the areas of LLM/security/open source, in machine learning/software performance, and in databases/search.&lt;/p&gt;
&lt;h2 id=&quot;upcoming-features-in-git&quot;&gt;Upcoming features in git&lt;/h2&gt;
&lt;p&gt;Patrick Steinhardt from GitLab, and git contributor, &lt;a href=&quot;https://fosdem.org/2026/schedule/event/HTJK33-evolving_git_for_the_next_decade/&quot;&gt;presented&lt;/a&gt; about some upcoming changes, planned for the major 3.0 release towards mid-2026.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Under the hood, git changes the hashing algorithm from SHA-1 to SHA-256&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is because SHA-1 is not secure — a paper from around 2017 showed that it does not create unique hashes.&lt;/li&gt;
&lt;li&gt;While git itself does not rely on uniqueness of hashes, the ecosystem implicitly does — for instance, by pinning software dependencies to git hashes.&lt;/li&gt;
&lt;li&gt;At the same time, large parts of the ecosystem (GitHub for instance) currently do not support SHA-256 hashes.&lt;/li&gt;
&lt;li&gt;By moving the default in git, the contributors want to solve the chicken-and-egg problem of “no-one wanting to use the feature because no-one supports it” and vice versa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;New command: git history for easier rewriting of history&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In git, rewriting history through an interactive rebase is cumbersome and takes several steps.&lt;/li&gt;
&lt;li&gt;Another limitation is that it leads to orphaned branches because other branches depending on the changed commits are not updated. For instance, this makes is tedious to use workflows with stacked branches.&lt;/li&gt;
&lt;li&gt;The new &lt;code&gt;git history&lt;/code&gt; command, inspired by other version control systems such as Jujutsu and Mercurial, provides some functionality that makes such workflows easier. For instance, &lt;code&gt;git history reword &amp;#x26;lt;commit&amp;#x26;gt;&lt;/code&gt; allows to amend the commit message of a specific commit; &lt;code&gt;git history split &amp;#x26;lt;commit&amp;#x26;gt;&lt;/code&gt; allows to split a specific commit.&lt;/li&gt;
&lt;li&gt;The new commands &lt;em&gt;also&lt;/em&gt; rebase other branches that depend on respective commits.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;open-source-llms-and-security&quot;&gt;Open Source, LLMs, and security&lt;/h3&gt;
&lt;p&gt;This was a major topic in this year’s conference and featured in two keynotes: Michael Leenaars &lt;a href=&quot;https://fosdem.org/2026/schedule/event/FE7ULY-foss-in-times-of-war-scarcity-and-ai/&quot;&gt;(talk)&lt;/a&gt; from NLnet, and Daniel Stenberg, founder and lead developer of cURL &lt;a href=&quot;https://fosdem.org/2026/schedule/event/B7YKQ7-oss-in-spite-of-ai/&quot;&gt;(talk)&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both speakers highlighted that LLMs can help malicious actors find and exploit vulnerabilities in open-source code, and thus open-source will become more vulnerable to supply-chain attacks.&lt;/li&gt;
&lt;li&gt;Stenberg further detailed how LLMs bring out the worst and best at the same time. On one hand, the cURL project is bombarded by AI-generated security reports. This has led cURL to stop their bug bounty program. On the other hand, they use LLMs selectively to find security issues and review code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Several talks in the security devroom addressed the same problem.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Updated governance model for open-weight LLMs&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;a href=&quot;https://fosdem.org/2026/schedule/event/VGMUYA-the-open-weight-dilemma/&quot;&gt;talk&lt;/a&gt; about LLMs and cyber risks argued for an updated governance model for open-source (and maybe open-weight) LLMs.&lt;/li&gt;
&lt;li&gt;While closed LLMs are easily controllable, safeguards in open models can easily be fine-tuned away.&lt;/li&gt;
&lt;li&gt;Therefore, open LLMs cannot be regulated like an API, and closed LLMs may even have an advantage because they are easier to regulate — a “mitigation gap”.&lt;/li&gt;
&lt;li&gt;The proposed solution is to define fine-tuned models as “substantial modification”, and shift the liability burden from the issuer of the original model to the fine-tuner.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Auditing and securing supply chains&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Open Source Technology Improvement Fund (OSTIF) presented their work on providing security audits to open-source software &lt;a href=&quot;https://fosdem.org/2026/schedule/event/Z7D3MW-security_audits_and_security/&quot;&gt;(talk)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aboutcode.org/&quot;&gt;AboutCode&lt;/a&gt; presented their tool for detecting LLM-generated code &lt;a href=&quot;https://fosdem.org/2026/schedule/event/XGLP7J-ai-generated-code/&quot;&gt;(talk)&lt;/a&gt;. If I understood correctly, the tool finds parts of a codebase that have been regurgitated from another source, and can pinpoint to the source. One challenge was that LLMs often create similar control flow, but different variable names from the original. In their &lt;code&gt;scancode.io&lt;/code&gt; &lt;a href=&quot;https://github.com/aboutcode-org/scancode.io/&quot;&gt;tool&lt;/a&gt;, they solve this problem with code stemming, a method also used by &lt;code&gt;treesitter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-search-and-llms&quot;&gt;Data, Search and LLMs&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Vector search&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In a RAG pipeline, the hard part is data engineering: one has to understand the data and the context &lt;a href=&quot;https://fosdem.org/2026/schedule/event/DHTAXQ-prevent-ai-garbage/&quot;&gt;(talk)&lt;/a&gt;. For instance, the chunking strategy is crucial for the retrieved the results.&lt;/li&gt;
&lt;li&gt;Weaviate &lt;a href=&quot;https://fosdem.org/2026/schedule/event/3AWMQZ-multi-vector-embeddings-revolution-or-evolution/&quot;&gt;presented and demonstrated&lt;/a&gt; multi-vector retrieval. This is particularly useful for search on PDFs that include images. Their &lt;a href=&quot;https://github.com/weaviate/weaviate&quot;&gt;tool&lt;/a&gt; implements the MUVERA algorithm &lt;a href=&quot;https://arxiv.org/abs/2405.19504&quot;&gt;(paper)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Speeding up LLM inference&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The vLLM project &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/eldar_kurtic/&quot;&gt;explained&lt;/a&gt; how they speed up LLM inference with quantization and speculative decoding.&lt;/li&gt;
&lt;li&gt;Quantization compresses the network weights into buckets. This leads to a smaller footprint in memory and to faster transfer of the weights from the GPU’s high-bandwidth memory to the SRAM and Tensor cores that do the matrix multiplications.&lt;/li&gt;
&lt;li&gt;Their benchmarks show that the ideal strategy (4-bit integer quantization vs. 8-bit integer quantization vs. no quantization) depends on the number of queries per second.&lt;/li&gt;
&lt;li&gt;For speculative decoding, one trains a light-weight “speculator” model that generates tokens at inference time, and the main model approves or rejects the generated tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;machine-learning-performance-and-observability&quot;&gt;Machine learning, performance, and observability&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Performance engineering&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Two talks discussed best practices for performance engineering: to reliably capture performance regressions, benchmarks should be repeatable and representative, and setting them up for this requires some thought. Challenges include isolating the benchmark environments and avoiding too many false positives.&lt;/li&gt;
&lt;li&gt;The first talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/8AS3XD-how-to-reliably-measure-software-performance/&quot;&gt;outlined&lt;/a&gt; a statistical testing approach based on increasing the signal-to-noise ratio and deciding when to reject the null hypothesis of no performance regression. Further, running benchmarks in the cloud poses challenges, and they recommend avoiding virtualized environments. The slides of the talk are &lt;a href=&quot;https://github.com/igoragoli/fosdem-2026-software-performance&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The second talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/YNB7KR-continuous-perf-engineering/&quot;&gt;focused&lt;/a&gt; on change point detection. I also liked the idea of using canaries to track the performance of the benchmark infrastructure itself — you want to know when the problem is with the infrastructure and when it is with your software.&lt;/li&gt;
&lt;li&gt;Both talks argued for continuous performance monitoring and presented some tools for this.&lt;code&gt;nyrkio&lt;/code&gt;provides CI runners for change point detection; the runners are not free but according to the provider, they are of better quality than other runners (such as &lt;code&gt;github-action-benchmark&lt;/code&gt;). &lt;a href=&quot;https://github.com/sharkdp/hyperfine&quot;&gt;hyperfine&lt;/a&gt; is a command-line benchmarking tool.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Performance monitoring of deep learning workloads on HPC&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Two talks addressed performance monitoring for deep learning workloads on HPC systems.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/BBYZLU-gpu-performance-monitoring/&quot;&gt;highlighted&lt;/a&gt; the shortcomings of &lt;code&gt;nvidia-smi&lt;/code&gt; compared to &lt;code&gt;dcgmi&lt;/code&gt;. In short, the former only tells us &lt;em&gt;whether&lt;/em&gt; the GPUs are busy, but not &lt;em&gt;how efficiently&lt;/em&gt; they are being used (tensor cores, streaming multiprocessors, DRAM). One example was that using 32-bit and 16-bit precision on a H100 shows the same utilization on &lt;code&gt;nvidia-smi&lt;/code&gt;, even though FP32 is less efficient because H100s do not support tensor core computations with this precision.&lt;/li&gt;
&lt;li&gt;The same talk also suggested that running &lt;code&gt;dcgmi&lt;/code&gt; incurs no overhead because it is reading data that is already being tracked. I found useful docs from SURF &lt;a href=&quot;https://servicedesk.surf.nl/wiki/spaces/WIKI/pages/92668151/dcgmi+dmon&quot;&gt;here&lt;/a&gt;, and they are more cautious, mentioning that &lt;code&gt;dcgmi&lt;/code&gt; may slightly slow down your code. I guess one has to test and see it for themselves. The NVIDIA docs for &lt;code&gt;dcgmi&lt;/code&gt; are &lt;a href=&quot;https://docs.nvidia.com/datacenter/dcgm/latest/user-guide/feature-overview.html#profiling-metrics&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The second talk &lt;a href=&quot;https://fosdem.org/2026/schedule/event/FYLDFE-observability_for_ai_workloads_on_hpc_beyond_gpu_utilization_metrics/&quot;&gt;presented&lt;/a&gt; an open-source observability dashboard for deep learning on HPC. It covers hardware, workload, and model health (such as gradient tracking). The &lt;a href=&quot;https://github.com/erythix4/HPCOBS&quot;&gt;tool&lt;/a&gt; was just released during the conference. I’m curious to see how it evolves and how it compares to other tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ole-mussmann-on-fosdem-2026-nix-international-oss-accessibility-and-collaboration&quot;&gt;Ole Mussmann on FOSDEM 2026: Nix, International OSS, Accessibility and Collaboration&lt;/h2&gt;
&lt;h3 id=&quot;opening&quot;&gt;Opening&lt;/h3&gt;
&lt;p&gt;A quote that hit hard:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If we lose our democracies, Open Source is irrelevant and goes away.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nothing to add here.&lt;/p&gt;
&lt;h3 id=&quot;nix-and-nixos&quot;&gt;Nix and NixOS&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;nix&lt;/code&gt; &lt;em&gt;&lt;strong&gt;for Determinism&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/bruce_gain/&quot;&gt;Bruce Gain&lt;/a&gt; discussed using &lt;code&gt;nix&lt;/code&gt; for “deterministic distributed-system benchmarking”. Without special care, library versions and kernel versions will drift over time. The low-hanging fruit &lt;code&gt;docker&lt;/code&gt; is not helping here. It solves packaging, not reproducibility, for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker&lt;/code&gt; uses the host’s kernel, and&lt;/li&gt;
&lt;li&gt;it is &lt;em&gt;really&lt;/em&gt; hard to make a container deterministic. &lt;code&gt;apt-get update&lt;/code&gt; is not reproducible, any unpinned library will drift over time. You could distribute the &lt;em&gt;images&lt;/em&gt; instead of &lt;code&gt;Dockerfile&lt;/code&gt;s, but those are huge and not meant to be changed (only appended).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;nix&lt;/code&gt; solves those issues by treating hashing and pinning every input of a project. Infrastructure is treated as a pure function. For identical inputs, the output &lt;em&gt;must&lt;/em&gt; be identical as well.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Software Bill of Materials (SBOM) Tools for &lt;code&gt;nix&lt;/code&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What’s inside your software package? Which dependencies do you use, and what’s &lt;em&gt;their&lt;/em&gt; dependencies? This surprisingly hard question is relevant for license compliance (did you obey the licenses of all libraries that you used?) as well as cybersecurity. If there’s a vulnerable package somewhere in the stack, you’d like to know, right? There’s a few tools that can help you out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nikstur/bombon&quot;&gt;https://github.com/nikstur/bombon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tiiuae/sbomnix&quot;&gt;https://github.com/tiiuae/sbomnix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/anchore/syft&quot;&gt;https://github.com/anchore/syft&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/determinatesystems&quot;&gt;Determinate Systems&lt;/a&gt; seem to have their own tool as well, but it does not seem to be public (yet?).&lt;/p&gt;
&lt;p&gt;Thanks for the heads up from &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/thecomputerguy&quot;&gt;Tristan “TheComputerGuy” Ross&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Sphinx&lt;/code&gt; &lt;em&gt;&lt;strong&gt;Documentation for &lt;code&gt;nix&lt;/code&gt; Code&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Sphinx&lt;/code&gt; was originally created as a documentation tool for &lt;code&gt;Python&lt;/code&gt; code, but it has since become a generic tool targeting all sorts of projects. &lt;a href=&quot;#7b6c&quot;&gt;[1]&lt;/a&gt; With &lt;a href=&quot;https://github.com/minijackson&quot;&gt;Rémi “minijackson”&lt;/a&gt; project &lt;code&gt;[sphinxcontrib-nixdomain](https://github.com/minijackson/sphinxcontrib-nixdomain)&lt;/code&gt; (rolls right off the tongue, doesn’t it?), one can document &lt;code&gt;nix&lt;/code&gt; options, modules, functions, package sets…&lt;/p&gt;
&lt;p&gt;This is the first time I see a structured approach to documenting a &lt;code&gt;nix&lt;/code&gt; project. Well done!&lt;/p&gt;
&lt;h3 id=&quot;international-open-source&quot;&gt;International Open Source&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Open Source in China&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Open Source looks different in China, says &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/richard_lin/&quot;&gt;Richard Lin&lt;/a&gt;. There are several factors at play:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;FLOSS is seen as a market capture tool in three easy steps:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Turn standards into de facto rules,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Rules into monopoly, and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Monopoly into profits.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Going global is not expansion, it’s survival.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;The market in China is dry, so branching out is a necessity.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;FLOSS is a declaration, not procurement. The goal is to nurture industries that will enlarge future tax revenue, not buying a working product. The process for companies is:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Self-declare a directional FLOSS project,&lt;/li&gt;
&lt;li&gt;Build it,&lt;/li&gt;
&lt;li&gt;Pass inspection, and&lt;/li&gt;
&lt;li&gt;Receive cash.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Software development, even FLOSS, is a cathedral, not a bazaar.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Development is top-down.&lt;/li&gt;
&lt;li&gt;Pressure from the FLOSS community is slowly changing that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You might notice a lack of FLOSS culture. Instead of “software wants to be free”, this looks very market-driven. And yet, even through this lens, this flavor of open source looks better to me than closed source. It will be interesting to watch how FLOSS develops in China, and how the different viewpoints will evolve.&lt;/p&gt;
&lt;h3 id=&quot;accessibility&quot;&gt;Accessibility&lt;/h3&gt;
&lt;p&gt;I arrived late to &lt;a href=&quot;https://fosdem.org/2026/schedule/speaker/mike_gifford/&quot;&gt;Mike Gifford&lt;/a&gt;’s talk “Accessible Sovereignty: Why the Four Freedoms Depend on Inclusion”, so I can’t say much about the actual content. What &lt;em&gt;did&lt;/em&gt; impress me was that he had a live-transcription of his voice underneath the slides. That is not only terrific for the hard-of-hearing, but also a very comforting addition for everyone else.&lt;/p&gt;
&lt;p&gt;Lessons at the eScience Center often use web slides made with &lt;code&gt;[reveal.js](https://revealjs.com/)&lt;/code&gt;. Modern browsers have a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API/Using_the_Web_Speech_API&quot;&gt;Web Speech API&lt;/a&gt; which can be used for &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition&quot;&gt;speech recognition&lt;/a&gt;. Do you see where this is going…? Would it not be great to have a plugin for &lt;code&gt;reveal.js&lt;/code&gt; presentations that display speech-to-text below the slides? Any volunteers to build this? Anyone?&lt;/p&gt;
&lt;p&gt;Ok, fine. I’ll do it myself.&lt;/p&gt;
&lt;p&gt;P.S.: Here it is: &lt;a href=&quot;https://github.com/OleMussmann/RevealSubtitles&quot;&gt;https://github.com/OleMussmann/RevealSubtitles&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;collaboration&quot;&gt;Collaboration&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/tdpauw&quot;&gt;Thierry de Pauw&lt;/a&gt; makes an argument that pull requests are useful for open-source work, but are more of a hindrance in the corporate world. They were coaching a novice team of developers and, to make things simple, they introduced trunk-based development with Non-Blocking Continuous Code Reviews. This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Everything happens on the &lt;code&gt;main&lt;/code&gt; branch, there are no other branches.&lt;/li&gt;
&lt;li&gt;Changes are (automatically) tested before deployment.&lt;/li&gt;
&lt;li&gt;Every morning, developers review some commits.&lt;/li&gt;
&lt;li&gt;In the end, every commit will be reviewed, after* being deployed(!).&lt;/li&gt;
&lt;li&gt;Fixes are applied, if needed, though this is rare.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Woah.&lt;/p&gt;
&lt;p&gt;I can see this working for a very specific developer situation while having absolutely rock-solid tests. Distributed development? Difficult. Working on features, while keeping the &lt;code&gt;main&lt;/code&gt; branch stable? Impossible. Troubleshooting bugs, bisecting a commit history? Tough.&lt;/p&gt;
&lt;p&gt;This is probably not a good fit for research-software-engineering. But I have to say, kudos for trying something weird &lt;em&gt;and making it work&lt;/em&gt;. And as a side effect, I realize that I have to be more flexible with my assumptions about how to develop software. That alone is already worthwhile.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://documentation.help/Sphinx/index.html&quot;&gt;https://documentation.help/Sphinx/index.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;faruk-diblen-on-fosdem-2026-sovereignty-burnout-and-the-ai-reality-check&quot;&gt;Faruk Diblen on FOSDEM 2026: Sovereignty, Burnout, and the AI Reality Check&lt;/h2&gt;
&lt;p&gt;I hope that by providing this short summary, I can convince you to participate in the next FOSDEM. It remains the biggest and most awesome open-source conference in Europe — and it is still free. It is so large that it reminds me of certain free open-source software projects: it is full of a specific kind of chaos. This is not due to the organization, but rather the scale of the conference and the range of topics and talks happening simultaneously. I must give kudos to the organizers for doing an amazing job.&lt;/p&gt;
&lt;h3 id=&quot;reflections-on-ai-and-the-community&quot;&gt;Reflections on AI and the Community&lt;/h3&gt;
&lt;p&gt;As I do every year, I was expecting amazing talks from people who are very passionate about open source and “geeky” topics. However, this time I also expected to hear more about how AI is supporting software development. Instead, most talks focused on how AI is dangerous and toxic for open source.&lt;/p&gt;
&lt;p&gt;I think I partly agree with that sentiment, but it may still be useful for certain tasks as a supporting tool. There were many interesting talks and discussions regarding the cultural, ethical, legal, and technological effects of recent developments in AI.&lt;/p&gt;
&lt;p&gt;The infamous &lt;a href=&quot;https://xkcd.com/2347/&quot;&gt;xkcd comic about infrastructure&lt;/a&gt; was also compulsory for all speakers to show. Perhaps the organizers were checking presentations beforehand, and if you did not have this comic, they were not allowing you to present. Jokes aside, I also agree now that this comic represents the current reality; it is perhaps even too modest.&lt;/p&gt;
&lt;h3 id=&quot;networking-and-the-research-track&quot;&gt;Networking and the Research Track&lt;/h3&gt;
&lt;p&gt;One of the other fun parts of FOSDEM is the chance to meet and have conversations with great minds, contributors, and initiators of very impactful open-source projects. Like previous years, I gathered new ideas and identified new potential collaboration opportunities. I should not skip the “fun stands”; you can talk to the amazing groups of people who made your favorite Linux distribution or who are working on drone development.&lt;/p&gt;
&lt;p&gt;As a researcher, I also had a chance to follow some of the &lt;a href=&quot;https://fosdem.org/2026/schedule/track/open-research/&quot;&gt;Open Research&lt;/a&gt; track. Although the research community was under-represented, it had a great variety of interesting topics, some of which are relevant to my own work. My positive experience has made me think about submitting a proposal for next year. For the other talks I followed or found interesting but could not attend in person, please see the &lt;a href=&quot;#72d3&quot;&gt;Highlights**&lt;/a&gt; section below.&lt;/p&gt;
&lt;p&gt;After leaving the conference, I had three things in my mind: sovereignty now, sovereignty in the near future, and sovereignty in the far future. I also deeply felt the messages of “AI is killing Open Source,” “Even if AI gets better, we, the developers, will be needed,” and “Everything will collapse if we do not support open source.” These messages were sometimes subliminal and sometimes mentioned openly.&lt;/p&gt;
&lt;h3 id=&quot;keynotes&quot;&gt;Keynotes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeynote-foss-in-times-of-war%2F&quot;&gt;&lt;strong&gt;FOSDEM 2026 — FOSS in times of war, scarcity and (adversarial) AI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Given by Michiel Leenaards, our neighbor next door. I was expecting him to talk about how NLnet supports open-source software, but he focused on the threats caused by geopolitics. Given the recent political changes in many countries, I think it was a wisely chosen topic that forces us to think about upcoming challenges.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeynote-free-as-in-burned-out%2F&quot;&gt;&lt;strong&gt;FOSDEM 2026 — Free as in Burned Out: Who Really Pays for Open Source?&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Marga Manterola, a long-time Debian developer, talked about why the “donations and sponsorships” model is failing maintainers. She listed common funding sources including a sort of “Open Source tax.” This talk may help us find solutions for software maintenance and sustainability funds.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeynote-security-in-spite-of-ai%2F&quot;&gt;&lt;strong&gt;Open Source Security in spite of AI&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; This was the most fun keynote, given by Daniel Stenberg. He told the story of the cURL project and his fight with issues and pull requests created by LLMs. Eventually, they decided to stop their Bug Bounty program. You can download the talk by using the &lt;code&gt;curl&lt;/code&gt; command below:** &lt;code&gt;curl https://ftp.belnet.be/mirror/FOSDEM/video/2026/janson/B7YKQ7-oss-in-spite-of-ai.av1.webm --output curl_keynote.webm&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;highlights&quot;&gt;Highlights&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(The talks I liked the most)&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Frrp-reproducible-research-platform%2F&quot;&gt;RRP: Reproducible Research Platform for FAIR Open Research**&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Andreas Cuny showcased the RRP: a heavyweight solution combining openBIS (RDMS), Git, Docker, and Kubernetes. It allows users to mount datasets into Jupyter/VS Code environments instantly. It is a bit complex to set up, but powerful for institutions. I had a very pleasant conversation with Andreas regarding potential collaborations, such as adding actual FAIR software checks (via &lt;code&gt;howfairis&lt;/code&gt;) to their platform.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fwho-funds-the-egg%2F&quot;&gt;&lt;strong&gt;Who Funds the Egg? Cracking the FOSS Funding Paradox&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Deborah Udoh highlighted the “chicken and egg” problem: you need impact to get funding, but you need funding to create impact. The “Pre-seeds” concept — non-monetary investments like visibility and mentorship — seems like a viable bridge for early-stage projects.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fmultimodal-support-in-llamacpp%2F&quot;&gt;&lt;strong&gt;Multimodal support in llama.cpp — Achievements and Future Directions&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Huge updates for local AI. &lt;code&gt;libmtmd&lt;/code&gt; finally standardizes multimodal support. They showed &lt;code&gt;llama-mtmd-cli&lt;/code&gt; doing low-latency OCR and experimental audio input with Ultravox.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fits-time-to-audit-open-source%2F&quot;&gt;&lt;strong&gt;It’s Time to Audit Open Source: Success Stories with OSTIF&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; OSTIF has now facilitated over 100 security audits for projects like git, cURL, and Kubernetes. The data shows that independent code review works.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fsupply-chain-security-meets-ai%2F&quot;&gt;&lt;strong&gt;Supply chain security meets AI: Detecting AI-generated code&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Philippe Ombredanne introduced a new tool for “fuzzy matching” code snippets to detect AI-generated content. With bots writing billions of lines of code, exact hashing does not work any more.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fthe-ai-shockwave%2F&quot;&gt;&lt;strong&gt;The AI Shockwave in Open Source Communities: How AI Is Reshaping the Foundations of Open Source Communities&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A worrying trend where newbie questions are dropping because people ask ChatGPT instead. This breaks the “contributor pipeline.”&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fburnout-in-open-source%2F&quot;&gt;&lt;strong&gt;Burnout in Open Source: A Structural Problem We Can Fix Together&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Miranda Heath identified “hyper-responsibility” and “toxic entitlement” as key burnout drivers. We need structural changes in how we value maintenance work.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fintroducing-jupyter-book-2%2F&quot;&gt;&lt;strong&gt;Introducing Jupyter Book 2: Next-generation Tools for Creating Computational Narratives&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; A complete rewrite based on the MyST (Markedly Structured Text) engine. It produces semantic, machine-readable content that is much easier to cross-reference.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fparticleos-from-fedora-to-feast%2F&quot;&gt;&lt;strong&gt;ParticleOS, from Fedora to Feast: Stirring Traditional Distros into Immutable Delights&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Luca Boccassi showed how &lt;code&gt;systemd&lt;/code&gt; and &lt;code&gt;mkosi&lt;/code&gt; are changing OS building, creating a fully immutable, signed, and verifiable image.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fwhat-do-we-mean-sovereign-ai%2F&quot;&gt;&lt;strong&gt;What do we mean when we say Sovereign AI?&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt; Katharine Jarmul explained that true “Sovereign AI” is not just about where the model is hosted, but having the full training data and code available to inspect.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;other-notable-tracks-and-talks&quot;&gt;Other Notable Tracks and Talks&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Research &amp;#x26; Science&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Frse-movement-uiuc%2F&quot;&gt;Research software engineering: a movement and its instantiation at the University of Illinois Urbana-Champaign&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fresearch-software-funding-models%2F&quot;&gt;Research software grant funding models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fbuilding-open-research-infrastructure%2F&quot;&gt;Building Open Research Infrastructure: Connecting the Lab Bench to Computational Analysis with RSpace &amp;#x26; Galaxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fharnessing-nix-for-bioinformatics%2F&quot;&gt;Building Everything with Nothing — Harnessing Nix for Bioinformatics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fgems-high-level-language%2F&quot;&gt;From Code to Models-as-Data: GEMS, a High-Level Language for Energy System Modelling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fopen-reproducible-ai-lmics%2F&quot;&gt;Building Open and Reproducible AI Practices for LMICs (and Beyond)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fcern-adaptyst%2F&quot;&gt;Towards unified full-stack performance analysis and automated computer system design at CERN with Adaptyst&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Foqtopus-quantum-toolchain%2F&quot;&gt;OQTOPUS: Open Quantum Toolchain for OPerators and USers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fskills-floss-developer%2F&quot;&gt;The Skills of a FLOSS Developer and Why They Are Important in Open Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Ftrusted-by-design%2F&quot;&gt;Trusted by design: set up your research software for community adoption&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Main Track &amp;#x26; Community&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fefficient-git-workflow%2F&quot;&gt;An Efficient Git Workflow For High-Stakes Projects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fkeep-open-source-open%2F&quot;&gt;How to keep Open Source open without leaving our communities open to threats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fstrategy-trusting-employer%2F&quot;&gt;Strategy for Trusting your Employer in Open Source: a Historical Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fwho-pays-your-bills%2F&quot;&gt;Who Pays Your Bills? Sustainability, Community and Business: The Open Source Triangle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fnext-gen-postgres-contributors%2F&quot;&gt;Building the next generation of open source contributors — Lessons from 30 years of Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Ffunding-europe-digital-infra%2F&quot;&gt;Funding Europe’s Open Digital Infrastructure: A Detailed Case for an EU Sovereign Tech Fund&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2F32-years-debian%2F&quot;&gt;32 years of Debian: how a do-ocracy keeps evolving&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;AI &amp;#x26; Machine Learning&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Flow-code-ai-agents%2F&quot;&gt;Drag, Drop, and Deploy: Low-Code AI Agents for Network Ops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fself-hosted-llms%2F&quot;&gt;From Infrastructure to Production: A Year of Self-Hosted LLMs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fai-security-monitoring%2F&quot;&gt;AI Security Monitoring: Detecting Threats Against Production ML Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fprevent-ai-garbage%2F&quot;&gt;How to Prevent Your AI from Returning Garbage: It Starts and Ends with Data Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fdeep-learning-snap%2F&quot;&gt;Deep Learning Demystified — Having Fun with Neural Networks in Snap!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Security, Databases &amp;#x26; Infrastructure&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fpost-quantum-cryptography%2F&quot;&gt;Demystifying Post-Quantum Cryptography: The Hybrid Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Flook-ma-no-secrets%2F&quot;&gt;Look ma, no secrets! — bootstrapping cryptographic trust in my homelab using NixOS, UKIs, TPMs and SPIFFE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Freal-time-ai-rondb%2F&quot;&gt;Real-Time AI Powered by RonDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fduckdb-bike-share%2F&quot;&gt;Exploring time series bike share data with duckdb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fopensearch-v3%2F&quot;&gt;OpenSearch v3: A New Era of Search Innovation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fsurf-research-cloud-oss%2F&quot;&gt;SURF Research Cloud is going OSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffosdem.org%2F2026%2Fschedule%2Fevent%2Fguix-container-images%2F&quot;&gt;Guix Container Images — and what you can do with them&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;booths-and-extra-notes&quot;&gt;Booths and Extra Notes&lt;/h3&gt;
&lt;p&gt;After hearing about sovereignty everywhere, I had lengthy chats with the folks from &lt;strong&gt;GitLab, NextCloud, LibreOffice, Forgejo&lt;/strong&gt;, and &lt;strong&gt;Codeberg&lt;/strong&gt; to learn about open-source office solutions and infrastructure. I also talked to someone from Germany who explained the government migration to Linux (see: &lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Fwww.zdnet.com%2Farticle%2Fanother-european-government-is-ditching-microsoft-for-linux%2F&quot;&gt;Yet another European government is ditching Microsoft for Linux&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;I visited the &lt;strong&gt;Tor&lt;/strong&gt; stand, where you could get fancy stickers if you donated to help them fight censorship. The &lt;strong&gt;Free Software Foundation Europe (FSFE)&lt;/strong&gt; is also worth following closely as their goals are related to our own. Finally, I learned about &lt;a href=&quot;https://www.google.com/search?q=https%3A%2F%2Ffundingjs.org%2F&quot;&gt;&lt;strong&gt;funding.json&lt;/strong&gt;&lt;/a&gt;, a format to declare financial needs of projects in a machine-readable format.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/fosdem-2026-observations-and-key-takeawa-55dcce06.l9YVToEZ.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Bring Your Own Backend</title><link>https://blog2.esciencecenter.nl/posts/2026-03-26---bring-your-own-backend</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-03-26---bring-your-own-backend</guid><description>&lt;p&gt;&lt;em&gt;A pattern for sustainable research software collaboration&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;298&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-58215f84.C2jqj6wm_Z1sjKop.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image source &lt;a href=&quot;https://www.pnnl.gov/news-media/new-nationwide-modeling-points-widespread-racial-disparities-urban-heat-stress&quot;&gt;https://www.pnnl.gov/news-media/new-nationwide-modeling-points-widespread-racial-disparities-urban-heat-stress&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a research software engineer (RSE) working at the Netherlands eScience Center, I work on projects together with domain scientists at universities and research institutes.&lt;/p&gt;
&lt;p&gt;For example, currently I am working on the &lt;a href=&quot;https://research-software-directory.org/projects/urban-m4&quot;&gt;Urban-M4 project,&lt;/a&gt; where we are trying to improve a weather model by telling it the properties of buildings in a city. As part of this project, I built a web-based application called &lt;a href=&quot;https://github.com/Urban-M4/Urban-M5&quot;&gt;streetscapes-explorer&lt;/a&gt; to create, review and edit segmented street view images. My engineering colleagues and project partners worked on the machine learning models and data processing pipelines that powered the backend of the web application.&lt;/p&gt;
&lt;p&gt;But as the project neared its end, a familiar worry crept in: &lt;em&gt;what happens after I leave?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-sustainability-problem&quot;&gt;The sustainability problem&lt;/h2&gt;
&lt;p&gt;The project partners are first and foremost domain scientists. They have the expertise and time to maintain a Python backend — updating dependencies, fixing bugs, evolving their data processing pipelines. But maintaining a highly interactive frontend written in TypeScript, with its constantly shifting JavaScript ecosystem, build tools, and UI frameworks, is a different story. That’s not where their expertise or time should go.&lt;/p&gt;
&lt;p&gt;A traditional monolithic application — with frontend and backend tightly coupled and deployed together — would force them to maintain both. They’d need to keep the server running, dependencies updated, security patches applied, and yes, understand that frontend code when something inevitably breaks. Given their constraints, this is a recipe for software rot and eventual abandonment.&lt;/p&gt;
&lt;p&gt;I needed a different approach. One where the frontend could essentially “freeze” after I left, requiring zero maintenance, while my partners could continue evolving their backend independently.&lt;/p&gt;
&lt;h2 id=&quot;the-solution-bring-your-own-backend&quot;&gt;The solution: Bring Your Own Backend&lt;/h2&gt;
&lt;p&gt;The key insight was simple: decouple where the frontend is hosted from where the backend runs**.&lt;/p&gt;
&lt;p&gt;Instead of deploying the frontend and backend together on some server that my partners would need to maintain, I separated them completely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: As a single page web application using &lt;a href=&quot;https://react.dev/&quot;&gt;React framework&lt;/a&gt;. Hosted as static files on &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; — zero maintenance, free hosting, always available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Runs on my Users or partners’ own machines, under their full control&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The magic that connects them? A URL query parameter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;607&quot; height=&quot;717&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-f8659c4d.BLuW3jQh_2eE4Yn.webp&quot; srcset=&quot;&quot;&gt;
The main idea, in a nutshell&lt;/p&gt;
&lt;h2 id=&quot;the-magic-url-based-backend-configuration&quot;&gt;The Magic: URL-based backend configuration&lt;/h2&gt;
&lt;p&gt;Here’s the core pattern. The frontend reads the backend URL from the query string:&lt;/p&gt;
&lt;p&gt;export function App() {**  const backend = new URLSearchParams(location.search).get(‘backend’);
if (!backend) {
return &amp;#x3C;BackendForm /&gt;;
}
return &amp;#x3C;StreetscapesExplorer backend={backend} /&gt;;
}When someone visits the frontend without specifying a backend, they see a helpful form with instructions:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;324&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-eb41ae53.2lRmfhfe_zxNKF.webp&quot; srcset=&quot;&quot;&gt;
When the frontend is unable to connect to the specified backend, it shows an error message with troubleshooting tips:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;547&quot; height=&quot;113&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-cdf89285.BWF2Lzc__Z1qVv8L.webp&quot; srcset=&quot;&quot;&gt;
The workflow becomes simply:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A user starts their backend locally&lt;/li&gt;
&lt;li&gt;A user visits the frontend URL with &lt;code&gt;?backend=http://localhost:5000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The frontend connects to their local backend&lt;/li&gt;
&lt;li&gt;All data stays on their machine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No rebuilds. No redeployments. No complex configuration. Just a URL parameter.&lt;/p&gt;
&lt;h2 id=&quot;keeping-it-simple-for-project-partners&quot;&gt;Keeping it simple for project partners&lt;/h2&gt;
&lt;p&gt;For this pattern to work after I leave, the backend needs to be dead simple to run.&lt;/p&gt;
&lt;p&gt;from dataclasses import dataclass, field
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware&lt;/p&gt;
&lt;p&gt;app = FastAPI()Web browsers do not like the frontend and backend to be at different URLs. For this in the backend we need to enable &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS&quot;&gt;CORS&lt;/a&gt; like so:&lt;/p&gt;
&lt;p&gt;app.add_middleware(
CORSMiddleware,
allow_origins=[&quot;&lt;em&gt;&quot;],
allow_methods=[&quot;&lt;/em&gt;&quot;],
)Then anyone can simply write a decorated and type annotated Python function to define an API endpoint:&lt;/p&gt;
&lt;p&gt;@dataclass
class FilterParams(Bbox):
ratings: list[int] = Field(default=[])&lt;/p&gt;
&lt;p&gt;@dataclass
class Image:
id: str
url: str
lat: float
lon: float
@app.get(“/images”)
async def fetch_images(filter: Annotated[FilterParams, Query()]) -&gt; list[Image]
# … implementationAnd to make it even more user-friendly, the backend prints a clickable link to the frontend on startup:&lt;/p&gt;
&lt;p&gt;def main() -&gt; None:
url = “&lt;a href=&quot;https://urban-m4.github.io/Urban-M5/?backend=http://localhost:8000&quot;&gt;https://urban-m4.github.io/Urban-M5/?backend=http://localhost:8000&lt;/a&gt;”
print(f”Waiting for the streetscapes-explorer to start…”)
print(f”Goto {url}”)
print(“(Press CTRL+C to quit)”)
uvicorn.run(app, host=“0.0.0.0”, port=8000)&lt;/p&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == “&lt;strong&gt;main&lt;/strong&gt;”:
main()If you’re feeling more helpful you can use &lt;a href=&quot;https://docs.python.org/3/library/webbrowser.html#webbrowser.open&quot;&gt;webbrowser.open(url)&lt;/a&gt; to open the URL automatically in the user’s default browser.&lt;/p&gt;
&lt;h2 id=&quot;the-contract-openapi-as-the-bridge&quot;&gt;The contract: OpenAPI as the bridge&lt;/h2&gt;
&lt;p&gt;The frontend and backend need to agree on an API contract. Rather than maintaining documentation that inevitably drifts from reality, I used &lt;a href=&quot;https://www.openapis.org/&quot;&gt;OpenAPI&lt;/a&gt; as the single source of truth.&lt;/p&gt;
&lt;p&gt;FastAPI automatically generates an OpenAPI specification from the Python code. I then use &lt;a href=&quot;https://openapi-ts.dev/introduction&quot;&gt;OpenAPI TypeScript&lt;/a&gt; to generate TypeScript types:&lt;/p&gt;
&lt;p&gt;openapi-typescript &lt;a href=&quot;http://localhost:5000/openapi.json&quot;&gt;http://localhost:5000/openapi.json&lt;/a&gt; -o ./src/lib/streetscapes-api.tsThe frontend then makes type-safe API calls:&lt;/p&gt;
&lt;p&gt;import createClient from ‘openapi-fetch’;
import type { paths } from ’./lib/streetscapes-api’;&lt;/p&gt;
&lt;p&gt;function StreetscapesExplorer({backend}: { backend: string }) {
const client = createClient&amp;#x3C;paths&gt;({ baseUrl: backend });
const { data = [], error } = await client.GET(‘/images’, {
params: { query: { rating: [4, 5] } }
});
return (
&amp;#x3C;div&gt;
{error &amp;#x26;&amp;#x26; &amp;#x3C;div&gt;Error: {error.message}&amp;#x3C;/div&gt;}
{data.map(image =&gt; (
&amp;#x3C;img key={image.id} src={image.url} alt={&lt;code&gt;Image ${image.id}&lt;/code&gt;} /&gt;
))}
{/* … rest of the app like map view */}
&amp;#x3C;/div&gt;
);
};This gives us compile-time safety: if my partners change the API contract, the TypeScript compiler will catch any mismatches when regenerating the types.&lt;/p&gt;
&lt;h2 id=&quot;try-it-out-yourself&quot;&gt;Try it out yourself&lt;/h2&gt;
&lt;p&gt;I made a minimal example of this pattern with a &lt;a href=&quot;https://sverhoeven.github.io/byob-todo-frontend/&quot;&gt;simple TODO application&lt;/a&gt;. To use follow the instructions to run the backend locally.&lt;/p&gt;
&lt;p&gt;The source code is available at &lt;a href=&quot;https://github.com/sverhoeven/byob-todo-frontend&quot;&gt;byob-todo-frontend&lt;/a&gt; and &lt;a href=&quot;https://github.com/sverhoeven/byob-todo-backend&quot;&gt;byob-todo-backend&lt;/a&gt;. In the frontend I used SolidJS and bun to keep the frontend light. In the backend I used uv and inline dependencies to keep the backend easy to run.&lt;/p&gt;
&lt;h2 id=&quot;when-to-use-byob&quot;&gt;When to use BYOB&lt;/h2&gt;
&lt;p&gt;This pattern isn’t for every project, but it shines when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Different expertise levels**: Frontend specialists work with domain experts who prefer other languages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data sensitivity&lt;/strong&gt;: Users need to keep data on their own machines&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limited resources&lt;/strong&gt;: No budget for ongoing server maintenance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaborative research&lt;/strong&gt;: Multiple groups might want to run their own backends&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The “Bring Your Own Backend” pattern turned what could have been abandoned software into a sustainable tool that my partners can use and evolve long after our collaboration ended. Sometimes the best code you write is the code others don’t have to maintain.&lt;/p&gt;
&lt;p&gt;This post was originally published at &lt;a href=&quot;https://github.com/sverhoeven/byob-todo-frontend/tree/main/blog&quot;&gt;the author’s GitHub account&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;A pattern for sustainable research software collaboration&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;298&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-58215f84.C2jqj6wm_Z1sjKop.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image source &lt;a href=&quot;https://www.pnnl.gov/news-media/new-nationwide-modeling-points-widespread-racial-disparities-urban-heat-stress&quot;&gt;https://www.pnnl.gov/news-media/new-nationwide-modeling-points-widespread-racial-disparities-urban-heat-stress&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a research software engineer (RSE) working at the Netherlands eScience Center, I work on projects together with domain scientists at universities and research institutes.&lt;/p&gt;
&lt;p&gt;For example, currently I am working on the &lt;a href=&quot;https://research-software-directory.org/projects/urban-m4&quot;&gt;Urban-M4 project,&lt;/a&gt; where we are trying to improve a weather model by telling it the properties of buildings in a city. As part of this project, I built a web-based application called &lt;a href=&quot;https://github.com/Urban-M4/Urban-M5&quot;&gt;streetscapes-explorer&lt;/a&gt; to create, review and edit segmented street view images. My engineering colleagues and project partners worked on the machine learning models and data processing pipelines that powered the backend of the web application.&lt;/p&gt;
&lt;p&gt;But as the project neared its end, a familiar worry crept in: &lt;em&gt;what happens after I leave?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-sustainability-problem&quot;&gt;The sustainability problem&lt;/h2&gt;
&lt;p&gt;The project partners are first and foremost domain scientists. They have the expertise and time to maintain a Python backend — updating dependencies, fixing bugs, evolving their data processing pipelines. But maintaining a highly interactive frontend written in TypeScript, with its constantly shifting JavaScript ecosystem, build tools, and UI frameworks, is a different story. That’s not where their expertise or time should go.&lt;/p&gt;
&lt;p&gt;A traditional monolithic application — with frontend and backend tightly coupled and deployed together — would force them to maintain both. They’d need to keep the server running, dependencies updated, security patches applied, and yes, understand that frontend code when something inevitably breaks. Given their constraints, this is a recipe for software rot and eventual abandonment.&lt;/p&gt;
&lt;p&gt;I needed a different approach. One where the frontend could essentially “freeze” after I left, requiring zero maintenance, while my partners could continue evolving their backend independently.&lt;/p&gt;
&lt;h2 id=&quot;the-solution-bring-your-own-backend&quot;&gt;The solution: Bring Your Own Backend&lt;/h2&gt;
&lt;p&gt;The key insight was simple: decouple where the frontend is hosted from where the backend runs**.&lt;/p&gt;
&lt;p&gt;Instead of deploying the frontend and backend together on some server that my partners would need to maintain, I separated them completely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: As a single page web application using &lt;a href=&quot;https://react.dev/&quot;&gt;React framework&lt;/a&gt;. Hosted as static files on &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; — zero maintenance, free hosting, always available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Runs on my Users or partners’ own machines, under their full control&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The magic that connects them? A URL query parameter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;607&quot; height=&quot;717&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-f8659c4d.BLuW3jQh_2eE4Yn.webp&quot; srcset=&quot;&quot;&gt;
The main idea, in a nutshell&lt;/p&gt;
&lt;h2 id=&quot;the-magic-url-based-backend-configuration&quot;&gt;The Magic: URL-based backend configuration&lt;/h2&gt;
&lt;p&gt;Here’s the core pattern. The frontend reads the backend URL from the query string:&lt;/p&gt;
&lt;p&gt;export function App() {**  const backend = new URLSearchParams(location.search).get(‘backend’);
if (!backend) {
return &amp;#x3C;BackendForm /&gt;;
}
return &amp;#x3C;StreetscapesExplorer backend={backend} /&gt;;
}When someone visits the frontend without specifying a backend, they see a helpful form with instructions:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;324&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-eb41ae53.2lRmfhfe_zxNKF.webp&quot; srcset=&quot;&quot;&gt;
When the frontend is unable to connect to the specified backend, it shows an error message with troubleshooting tips:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Bring Your Own Backend&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;547&quot; height=&quot;113&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-cdf89285.BWF2Lzc__Z1qVv8L.webp&quot; srcset=&quot;&quot;&gt;
The workflow becomes simply:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A user starts their backend locally&lt;/li&gt;
&lt;li&gt;A user visits the frontend URL with &lt;code&gt;?backend=http://localhost:5000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The frontend connects to their local backend&lt;/li&gt;
&lt;li&gt;All data stays on their machine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No rebuilds. No redeployments. No complex configuration. Just a URL parameter.&lt;/p&gt;
&lt;h2 id=&quot;keeping-it-simple-for-project-partners&quot;&gt;Keeping it simple for project partners&lt;/h2&gt;
&lt;p&gt;For this pattern to work after I leave, the backend needs to be dead simple to run.&lt;/p&gt;
&lt;p&gt;from dataclasses import dataclass, field
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware&lt;/p&gt;
&lt;p&gt;app = FastAPI()Web browsers do not like the frontend and backend to be at different URLs. For this in the backend we need to enable &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS&quot;&gt;CORS&lt;/a&gt; like so:&lt;/p&gt;
&lt;p&gt;app.add_middleware(
CORSMiddleware,
allow_origins=[&quot;&lt;em&gt;&quot;],
allow_methods=[&quot;&lt;/em&gt;&quot;],
)Then anyone can simply write a decorated and type annotated Python function to define an API endpoint:&lt;/p&gt;
&lt;p&gt;@dataclass
class FilterParams(Bbox):
ratings: list[int] = Field(default=[])&lt;/p&gt;
&lt;p&gt;@dataclass
class Image:
id: str
url: str
lat: float
lon: float
@app.get(“/images”)
async def fetch_images(filter: Annotated[FilterParams, Query()]) -&gt; list[Image]
# … implementationAnd to make it even more user-friendly, the backend prints a clickable link to the frontend on startup:&lt;/p&gt;
&lt;p&gt;def main() -&gt; None:
url = “&lt;a href=&quot;https://urban-m4.github.io/Urban-M5/?backend=http://localhost:8000&quot;&gt;https://urban-m4.github.io/Urban-M5/?backend=http://localhost:8000&lt;/a&gt;”
print(f”Waiting for the streetscapes-explorer to start…”)
print(f”Goto {url}”)
print(“(Press CTRL+C to quit)”)
uvicorn.run(app, host=“0.0.0.0”, port=8000)&lt;/p&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == “&lt;strong&gt;main&lt;/strong&gt;”:
main()If you’re feeling more helpful you can use &lt;a href=&quot;https://docs.python.org/3/library/webbrowser.html#webbrowser.open&quot;&gt;webbrowser.open(url)&lt;/a&gt; to open the URL automatically in the user’s default browser.&lt;/p&gt;
&lt;h2 id=&quot;the-contract-openapi-as-the-bridge&quot;&gt;The contract: OpenAPI as the bridge&lt;/h2&gt;
&lt;p&gt;The frontend and backend need to agree on an API contract. Rather than maintaining documentation that inevitably drifts from reality, I used &lt;a href=&quot;https://www.openapis.org/&quot;&gt;OpenAPI&lt;/a&gt; as the single source of truth.&lt;/p&gt;
&lt;p&gt;FastAPI automatically generates an OpenAPI specification from the Python code. I then use &lt;a href=&quot;https://openapi-ts.dev/introduction&quot;&gt;OpenAPI TypeScript&lt;/a&gt; to generate TypeScript types:&lt;/p&gt;
&lt;p&gt;openapi-typescript &lt;a href=&quot;http://localhost:5000/openapi.json&quot;&gt;http://localhost:5000/openapi.json&lt;/a&gt; -o ./src/lib/streetscapes-api.tsThe frontend then makes type-safe API calls:&lt;/p&gt;
&lt;p&gt;import createClient from ‘openapi-fetch’;
import type { paths } from ’./lib/streetscapes-api’;&lt;/p&gt;
&lt;p&gt;function StreetscapesExplorer({backend}: { backend: string }) {
const client = createClient&amp;#x3C;paths&gt;({ baseUrl: backend });
const { data = [], error } = await client.GET(‘/images’, {
params: { query: { rating: [4, 5] } }
});
return (
&amp;#x3C;div&gt;
{error &amp;#x26;&amp;#x26; &amp;#x3C;div&gt;Error: {error.message}&amp;#x3C;/div&gt;}
{data.map(image =&gt; (
&amp;#x3C;img key={image.id} src={image.url} alt={&lt;code&gt;Image ${image.id}&lt;/code&gt;} /&gt;
))}
{/* … rest of the app like map view */}
&amp;#x3C;/div&gt;
);
};This gives us compile-time safety: if my partners change the API contract, the TypeScript compiler will catch any mismatches when regenerating the types.&lt;/p&gt;
&lt;h2 id=&quot;try-it-out-yourself&quot;&gt;Try it out yourself&lt;/h2&gt;
&lt;p&gt;I made a minimal example of this pattern with a &lt;a href=&quot;https://sverhoeven.github.io/byob-todo-frontend/&quot;&gt;simple TODO application&lt;/a&gt;. To use follow the instructions to run the backend locally.&lt;/p&gt;
&lt;p&gt;The source code is available at &lt;a href=&quot;https://github.com/sverhoeven/byob-todo-frontend&quot;&gt;byob-todo-frontend&lt;/a&gt; and &lt;a href=&quot;https://github.com/sverhoeven/byob-todo-backend&quot;&gt;byob-todo-backend&lt;/a&gt;. In the frontend I used SolidJS and bun to keep the frontend light. In the backend I used uv and inline dependencies to keep the backend easy to run.&lt;/p&gt;
&lt;h2 id=&quot;when-to-use-byob&quot;&gt;When to use BYOB&lt;/h2&gt;
&lt;p&gt;This pattern isn’t for every project, but it shines when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Different expertise levels**: Frontend specialists work with domain experts who prefer other languages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data sensitivity&lt;/strong&gt;: Users need to keep data on their own machines&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limited resources&lt;/strong&gt;: No budget for ongoing server maintenance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaborative research&lt;/strong&gt;: Multiple groups might want to run their own backends&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The “Bring Your Own Backend” pattern turned what could have been abandoned software into a sustainable tool that my partners can use and evolve long after our collaboration ended. Sometimes the best code you write is the code others don’t have to maintain.&lt;/p&gt;
&lt;p&gt;This post was originally published at &lt;a href=&quot;https://github.com/sverhoeven/byob-todo-frontend/tree/main/blog&quot;&gt;the author’s GitHub account&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/bring-your-own-backend-f8659c4d.BLuW3jQh.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Give Me Data, Yesterday</title><link>https://blog2.esciencecenter.nl/posts/2026-03-18---give-me-data-yesterday</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-03-18---give-me-data-yesterday</guid><description>&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-bd7575b9.DXvMDkzN_Z1TbF5C.webp&quot; srcset=&quot;&quot;&gt;
I want this data, and I want it yesterday!&lt;em&gt;This post is adapted, with the &lt;em&gt;&lt;a href=&quot;https://ole-mn.medium.com/&quot;&gt;&lt;em&gt;author&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;’s permission and collaboration, from &lt;em&gt;&lt;a href=&quot;https://ole.mn/posts/2026-02-data-cache/&quot;&gt;&lt;em&gt;this post&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; in his personal blog.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is a quest. A quest for the right tool for the right job, for usability, and performance. We will torture databases, run tens of thousands of benchmarks and conjure charts, numbers, and tables. Because science. 🧑‍🔬&lt;/p&gt;
&lt;p&gt;But first, some background.&lt;/p&gt;
&lt;p&gt;The patient is the package search program &lt;code&gt;[nps](https://github.com/OleMussmann/nps/)&lt;/code&gt;, which provides information about all packages the &lt;code&gt;[nix](https://nixos.org/)&lt;/code&gt; package manager has to offer. What’s the patient’s complaint? &lt;code&gt;nps&lt;/code&gt; needs a better database and a better way to update its data.&lt;/p&gt;
&lt;p&gt;Erm, &lt;code&gt;nix&lt;/code&gt;? Never heard of it? It’s kinda special. Unlike &lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;pacman&lt;/code&gt;, or their siblings, it is declarative, reproducible and reliable. To top it off, it has a &lt;a href=&quot;https://repology.org/repositories/graphs&quot;&gt;gigantic library&lt;/a&gt;. If you don’t know what that means, no worries! Here’s a primer.&lt;/p&gt;
&lt;h2 id=&quot;nix-whats-that&quot;&gt;&lt;code&gt;nix&lt;/code&gt;? What’s That?&lt;/h2&gt;
&lt;p&gt;How do you set up your operating system? You install, for example, Ubuntu. Then you install a bunch of packages. You configure them. Then you set the wallpaper, the color scheme, the fonts, and make yourself at home. And if you set up a new system, you start again from square one. This whole process is &lt;em&gt;procedural&lt;/em&gt;, you follow one step after another. If you re-do all your steps again, you get the same result; and any changes to the recipe will result in a different outcome.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;nix&lt;/code&gt;, you describe the end state you want to have, and &lt;code&gt;nix&lt;/code&gt; will build and set up the system like you describe. Reliably. Reproducibly. &lt;code&gt;nix&lt;/code&gt; is &lt;em&gt;declarative&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Worry not, you can still apply tweaks and modifications. The desired end state including all customizations can be described in a single configuration file (keep it simple), or a set of files (make it modular). Let’s call this configuration file a “flake”. ❄️ Throw &lt;code&gt;git&lt;/code&gt; at this flake file and now you can jump between different versions on demand.&lt;/p&gt;
&lt;p&gt;If you share your flake with someone else, they can re-create the exact environment on their system. This is great for collaborative development! Runs on your computer? Runs everywhere. You can run other people’s software &lt;em&gt;without installing&lt;/em&gt;, and others can run yours. For even more portability, you can create Docker containers, virtual machines, or even a bootable ISO from your project.&lt;/p&gt;
&lt;p&gt;Sounds like magic? It comes close.&lt;/p&gt;
&lt;p&gt;Current gotchas include a lack of broad adoption, a steep learning curve for the &lt;code&gt;nix&lt;/code&gt; language, as well as not great (but improving) documentation. And, well, a distinct lack of a native, fast, offline program for searching packages.&lt;/p&gt;
&lt;h2 id=&quot;paper-cuts&quot;&gt;Paper Cuts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;nix&lt;/code&gt;’s usability has, let’s say, still room for improvement. Prime example: how to find out which packages one can install. What do these packages do exactly, and what version do I get? The &lt;a href=&quot;https://wiki.nixos.org/wiki/Searching_packages&quot;&gt;recommended way&lt;/a&gt; is – drumroll – a website: &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;search.nixos.org/packages&lt;/a&gt;. It’s fast, comprehensive, and detailed. It works well.&lt;/p&gt;
&lt;p&gt;But it’s a website.&lt;/p&gt;
&lt;p&gt;When I’m pondering about installing packages, I’m not staring at a browser. I’m in the terminal. I want to have the equivalent of &lt;code&gt;apt search&lt;/code&gt; or &lt;code&gt;pacman -Ss&lt;/code&gt;¹.&lt;/p&gt;
&lt;p&gt;There are some wonderful CLI search programs out there², but they hook into the ElasticSearch database powering the backend of &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;search.nixos.org/packages&lt;/a&gt;. This means that you need to be online to get any package information, and (minor quibble, I know) it takes a bit for the information to appear on your screen.&lt;/p&gt;
&lt;h2 id=&quot;nps&quot;&gt;&lt;code&gt;nps&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I built the &lt;a href=&quot;https://github.com/OleMussmann/nps/&quot;&gt;Nix Package Search &lt;/a&gt;&lt;code&gt;[nps](https://github.com/OleMussmann/nps/)&lt;/code&gt; program to do my part to make &lt;code&gt;nix&lt;/code&gt; more user-friendly. &lt;code&gt;nps&lt;/code&gt; stores the package information locally, searches this cache, and presents the result – color-coded and sanely sorted. It works offline. It’s fast. It’s beautiful. Yeah, yeah, I know, I’m biased. Try it for yourself, though! Remember, you can run it without installing.&lt;/p&gt;
&lt;p&gt;Lately, &lt;a href=&quot;https://github.com/kevb1973&quot;&gt;kevb1973&lt;/a&gt; asked me to &lt;a href=&quot;https://github.com/OleMussmann/nps/issues/25&quot;&gt;provide more package information&lt;/a&gt; in the (dense) output that &lt;code&gt;nps&lt;/code&gt; provides. It’s a great idea and would increase the utility that &lt;code&gt;nps&lt;/code&gt; provides! Unfortunately, this is not something I can just bolt on to the existing program. Let’s have a look at the moving parts of &lt;code&gt;nps&lt;/code&gt; to understand why.&lt;/p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;
&lt;p&gt;Ok, architecture is a big word. Let me run by you how &lt;code&gt;nps&lt;/code&gt; currently works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;nix search nixpkgs ^&lt;/code&gt; – get all information for “all” packages.&lt;/li&gt;
&lt;li&gt;Create a text file with package names, versions, and descriptions and store them locally.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;/code&gt; through the text file (yes, it’s that low-tech) to find matches.&lt;/li&gt;
&lt;li&gt;Sort matches nicely into exact hits (searching for “avahi” matches package &lt;code&gt;avahi&lt;/code&gt;), direct hits (finds packages starting with “avahi”, e.g. &lt;code&gt;avahi-compat&lt;/code&gt;) and indirect hits (“avahi” appears anywhere in the package name or description).&lt;/li&gt;
&lt;li&gt;Create columns for better readability.&lt;/li&gt;
&lt;li&gt;Add a lick of paint to color-code the different types of matches.&lt;/li&gt;
&lt;li&gt;Print the result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The issue: the data is stored as one row per package. Adding more information to each package row will make it harder for &lt;code&gt;grep&lt;/code&gt; to find the packages you’re looking for. This looks like a job for a “proper” database now. But which one? There’s plenty of cool tech out there, but which would be the “best” one for this use case?&lt;/p&gt;
&lt;h2 id=&quot;database-candidate-boundary-conditions&quot;&gt;Database Candidate Boundary Conditions&lt;/h2&gt;
&lt;p&gt;Alright, before we dive in, let’s define a few corner stones.&lt;/p&gt;
&lt;h3 id=&quot;data-source&quot;&gt;Data Source&lt;/h3&gt;
&lt;p&gt;Remember the &lt;code&gt;nix search&lt;/code&gt; command from above? It does not actually find “all” packages, &lt;a href=&quot;https://search.nixos.org&quot;&gt;https://search.nixos.org&lt;/a&gt; finds significantly more³. Why? No idea. Also, &lt;code&gt;nix search&lt;/code&gt; supplies only the package name, version, and description. No other information. Not great. Another aspect that’s missing is that packages might provide a differently named executable: you install the package &lt;code&gt;neovim&lt;/code&gt; and use the executable &lt;code&gt;nvim&lt;/code&gt;; some packages even provide multiple different executables. &lt;code&gt;nix search&lt;/code&gt; can’t find those.&lt;/p&gt;
&lt;p&gt;The data needs to come from a better source.&lt;/p&gt;
&lt;p&gt;The ElasticSearch backend is a good choice, but it’s meant to be queried, not downloaded. This means we have to scrape it in its entirety first.&lt;/p&gt;
&lt;p&gt;Setting up a project that does the scraping and regularly builds a cache that is usable by (a future version of) &lt;code&gt;nps&lt;/code&gt; is a task that goes beyond the scope of this post. Let’s assume for now that we have the data available, and we can squish (very scientific term here) it into any shape or form that we need for querying.&lt;/p&gt;
&lt;h3 id=&quot;substring-matching&quot;&gt;Substring Matching&lt;/h3&gt;
&lt;p&gt;Subwhat? A substring is a part of a string: “crow” is a substring of “miCROWave”. It can be anywhere in a string, beginning, middle, or end. When searching for “nvim” I want to find &lt;code&gt;nvim&lt;/code&gt; (duh!), as well as &lt;code&gt;nvimpager&lt;/code&gt; “use neovim as pager”, and &lt;code&gt;gnvim&lt;/code&gt; “GUI for neovim, without any web bloat”. As most databases are specialized in retrieving “exact” matches, substring matching might take some convincing.&lt;/p&gt;
&lt;h3 id=&quot;query-time&quot;&gt;Query Time&lt;/h3&gt;
&lt;p&gt;I want future &lt;code&gt;nps&lt;/code&gt; to stay fast. I’m happy with the responsiveness of the current implementation. To get a feeling for this, using &lt;code&gt;nps&lt;/code&gt; to search for the package &lt;code&gt;nps&lt;/code&gt; takes about 6ms on my desktop – so let’s take that as a baseline. If the pure data retrieval of the database candidates takes longer than current-&lt;code&gt;nps&lt;/code&gt;, then that’s a red flag, since sorting, coloring, etc. will take some extra time on top of that.&lt;/p&gt;
&lt;p&gt;Quick Cold Start**&lt;/p&gt;
&lt;p&gt;Related to “Query Time”: many “serious” databases are designed to run as a service; that makes querying fast, but you need something running in the background all the time. We don’t want that. Instead, we have a single program that starts up, queries a database, prints stuff, and then quits. This excludes many of the usual suspects like MySQL and its colleagues.&lt;/p&gt;
&lt;h3 id=&quot;data-amount&quot;&gt;Data Amount&lt;/h3&gt;
&lt;p&gt;The current data amount is about 8.5 Mb of package information and metadata for one &lt;code&gt;nixpkgs&lt;/code&gt; channel. The future, more detailed one (also including a long description, project URL and location within the &lt;code&gt;nixpkgs&lt;/code&gt; repo) would be 26 Mb of plain text. For three NixOS channels (“unstable”, “current stable”, “previous stable”), this would be about 80 Mb. While compression can bring this down a bit, some databases need to index their database to be able to search quickly; this will increase the data amount again. How much? That depends on the database used.&lt;/p&gt;
&lt;p&gt;The increased data amount is defensible when taking into account that one could regularly download the &lt;em&gt;incremental changes&lt;/em&gt; instead of the whole database for refreshing the cache.&lt;/p&gt;
&lt;p&gt;Yes, this is pretty hand-wavy for now. We’ll get more concrete about this later.&lt;/p&gt;
&lt;h3 id=&quot;memory-usage&quot;&gt;Memory Usage&lt;/h3&gt;
&lt;p&gt;A bit less crucial than the above, I’d like to use as little RAM as possible during the search. &lt;code&gt;nps&lt;/code&gt; is a guest on your machine and it should use only as much of your resources as needed.&lt;/p&gt;
&lt;p&gt;Many databases (as well as the good ol’ &lt;code&gt;grep&lt;/code&gt;) don’t load the whole data into memory before searching, they “crawl” through the data and drop the parts they have already used. I’d set that as a “nice to have”.&lt;/p&gt;
&lt;h2 id=&quot;database-candidates&quot;&gt;Database Candidates&lt;/h2&gt;
&lt;p&gt;First, let’s discuss the candidates and their structural strengths and weaknesses. We get to the hard numbers below, in the chapter &lt;a href=&quot;#37a0&quot;&gt;&lt;strong&gt;“Gimme Numbers!”&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;grep-a-text-file-&quot;&gt;&lt;code&gt;grep&lt;/code&gt; a Text File 🦖&lt;/h3&gt;
&lt;p&gt;Why change a working system? The old dinosaur &lt;code&gt;grep&lt;/code&gt; is fast. Really fast. We have the &lt;a href=&quot;https://www.gnu.org/software/grep/&quot;&gt;“GNU” flavor&lt;/a&gt; that runs on the command line, then there’s a &lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;Rust implementation called &lt;/a&gt;&lt;code&gt;[ripgrep](https://github.com/BurntSushi/ripgrep)&lt;/code&gt;, and lastly the &lt;a href=&quot;https://docs.rs/grep/latest/grep/&quot;&gt;Rust crate called &lt;/a&gt;&lt;code&gt;[grep](https://docs.rs/grep/latest/grep/)&lt;/code&gt;, which is – despite the name – closer to &lt;code&gt;ripgrep&lt;/code&gt; than to &lt;code&gt;grep&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s dial it up a notch. I’d like to see how just calling &lt;code&gt;grep&lt;/code&gt; or its cousin &lt;code&gt;ripgrep&lt;/code&gt; from the command line (equivalent to step 3. from &lt;a href=&quot;#architecture&quot;&gt;“Architecture”&lt;/a&gt;; we will label all those tests with the “CLI” suffix) compares to calling it from Rust and splitting the results (necessity for the “new” architecture). &lt;code&gt;ripgrep&lt;/code&gt; likes to work with streaming data, but we can’t do that if we want to form columns later. So what’s the overhead of the extra data mangling?&lt;/p&gt;
&lt;p&gt;That brings us to the following list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GNU &lt;code&gt;grep&lt;/code&gt; (called from CLI, results &lt;em&gt;not&lt;/em&gt; split)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ripgrep&lt;/code&gt; (called from CLI, results &lt;em&gt;not&lt;/em&gt; split)&lt;/li&gt;
&lt;li&gt;GNU &lt;code&gt;grep&lt;/code&gt; (called from Rust)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ripgrep&lt;/code&gt; (called from Rust)&lt;/li&gt;
&lt;li&gt;Rust crate &lt;code&gt;grep&lt;/code&gt; (called from Rust)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Simple&lt;/li&gt;
&lt;li&gt;Single file “database”&lt;/li&gt;
&lt;li&gt;Easy and good compression&lt;/li&gt;
&lt;li&gt;Trivial substring matching&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Extra finagling to only search certain parts of a line, yet still returning the whole row of data; in practice this means extra lines of code plus possibly a few extra gray hairs&lt;/li&gt;
&lt;li&gt;Incremental data updates are difficult&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;sqlite-&quot;&gt;SQLite 🪶&lt;/h3&gt;
&lt;p&gt;The gold standard for “simple” databases. Scales less well for serious applications than MySQL (or MariaDB or whatever), but should be “good enough” for a few hundred thousand packages.&lt;/p&gt;
&lt;p&gt;We use trigram (N-gram with N=3)⁴search to achieve fast substring matching. This makes it, well, fast. But it also inflates the database size and ignores any search terms shorter than 3 characters. One &lt;em&gt;could&lt;/em&gt; check for search string length and use a different matching algorithm for shorter terms, but is that worth the effort?&lt;/p&gt;
&lt;h3 id=&quot;benefits-1&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Single file database&lt;/li&gt;
&lt;li&gt;Battle-tested and stable&lt;/li&gt;
&lt;li&gt;“Proper” database queries, the results are well-structured&lt;/li&gt;
&lt;li&gt;Incremental updates are trivial&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trade-offs&quot;&gt;Trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;How compressible is an already compressed database?&lt;/li&gt;
&lt;li&gt;Needs indexing for fast substring matches, balancing database size vs performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks-1&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compression per row, not on the whole file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;tantivy-&quot;&gt;Tantivy 🐎&lt;/h3&gt;
&lt;p&gt;I sparred with ChatGPT about which database to use, and it was very enthusiastic about Tantivy — we will see later if that was a good idea or not. It is designed for a quick cold-start and fast data retrieval, sounds like a match to me! Tantivy stores data in several files and has a &lt;code&gt;meta.json&lt;/code&gt; file to figure out what’s what.&lt;/p&gt;
&lt;p&gt;A quirk: technically, you can’t delete already stored data. Instead, you add a “delete” file that ignores entries and you can delete storage files that eventually become obsolete. Still, incremental updates should not be too hard this way. Every once in a while one would need to re-download the whole thing once the local index grew too large with all those “delete” files.&lt;/p&gt;
&lt;p&gt;Same as with &lt;code&gt;SQLite&lt;/code&gt;, we use trigram matching for speed, with the same benefits and drawbacks.&lt;/p&gt;
&lt;h3 id=&quot;benefits-2&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pretty much designed for this purpose&lt;/li&gt;
&lt;li&gt;Incremental updates are easy&lt;/li&gt;
&lt;li&gt;“Proper” database queries, the results are well-structured&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trade-offs-1&quot;&gt;Trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The database is a folder with multiple files&lt;/li&gt;
&lt;li&gt;Needs indexing for fast substring matches, balancing database size vs performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks-2&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Incremental updates do need a strategy, with an occasional fresh download of the whole database&lt;/li&gt;
&lt;li&gt;The many files might take some time to read, benchmarks will tell if that’s an issue&lt;/li&gt;
&lt;li&gt;Compression per row, not on the whole file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;duckdb-&quot;&gt;DuckDB 🦆&lt;/h3&gt;
&lt;p&gt;Completing our zoo is the new duckling on the block. DuckDB sports rad analytics which might be handy for retrieving already correctly sorted search results.&lt;/p&gt;
&lt;p&gt;However, DuckDB can’t do N-grams. &lt;a href=&quot;https://github.com/duckdb/duckdb/discussions/16071&quot;&gt;Yet&lt;/a&gt;. Sad quack.&lt;/p&gt;
&lt;p&gt;What can we do instead?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Benchmark the slower, standard way of case-insensitive substring matching, called &lt;code&gt;ILIKE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Benchmark the slower, other way of case-insensitive substring matching with regular expressions: &lt;code&gt;regex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Who needs built-in N-gram indexing when Gemini can build one (let’s call it &lt;code&gt;trigram&lt;/code&gt;) for you? We will soon find out if that’s a good idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;benefits-3&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ducks are cool&lt;/li&gt;
&lt;li&gt;Single file database&lt;/li&gt;
&lt;li&gt;Supports incremental updates&lt;/li&gt;
&lt;li&gt;“Proper” database queries, the results are well-structured&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trade-offs-2&quot;&gt;Trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Would the analytics work for proper sorting?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks-3&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No built-in N-gram indexing for fast substring matching, uh oh!&lt;/li&gt;
&lt;li&gt;Compression per row, not on the whole file&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;benchmarking-boundary-conditions&quot;&gt;Benchmarking Boundary Conditions&lt;/h2&gt;
&lt;p&gt;We will be testing for a lot of things at once, here’s a break-down.&lt;/p&gt;
&lt;h3 id=&quot;parameters&quot;&gt;Parameters&lt;/h3&gt;
&lt;p&gt;We are searching for four different search terms with increasing number of matches. This should give us enough data points to make out a trend.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“nps” (21 matches)&lt;/li&gt;
&lt;li&gt;“nvim” (1301 matches)&lt;/li&gt;
&lt;li&gt;“python” (21123 matches)&lt;/li&gt;
&lt;li&gt;“e” (131567 matches, almost the whole database)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-types&quot;&gt;Data Types&lt;/h3&gt;
&lt;p&gt;To be able to compare database performances with the current implementation of &lt;code&gt;nps&lt;/code&gt; we start with a “minimal” database, containing the package name, version, and short description. This mirrors the current implementation of &lt;code&gt;nps&lt;/code&gt; and allows for comparisons.&lt;/p&gt;
&lt;p&gt;The entire “minimal” data for the &lt;code&gt;abcde&lt;/code&gt; package look like this:&lt;/p&gt;
&lt;p&gt;abcde   2.9.3   Command-line audio CD ripperThen we try a “detailed” database, containing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;package name&lt;/li&gt;
&lt;li&gt;executable names (which might be different than the package name)&lt;/li&gt;
&lt;li&gt;version&lt;/li&gt;
&lt;li&gt;description (short)&lt;/li&gt;
&lt;li&gt;description (long)&lt;/li&gt;
&lt;li&gt;homepage URL&lt;/li&gt;
&lt;li&gt;and the URL to the package in the &lt;code&gt;nixpkgs&lt;/code&gt; repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Formatted, the information for the same package could look like this:&lt;/p&gt;
&lt;p&gt;abcde [abcde-musicbrainz-tool, abcde, cddb-tool]  2.9.3&lt;/p&gt;
&lt;p&gt;Command-line audio CD ripper
abcde is a front-end command-line utility (actually, a shell
script) that grabs tracks off a CD, encodes them to Ogg/Vorbis,
MP3, FLAC, Ogg/Speex and/or MPP/MP+ (Musepack) format, and tags
them, all in one go.
Project URL: &lt;a href=&quot;http://abcde.einval.com/wiki/&quot;&gt;http://abcde.einval.com/wiki/&lt;/a&gt;
Nixpkgs URL: &lt;a href=&quot;https://github.com/NixOS/nixpkgs/pkgs/by-name/ab/abcde/package.nix:83Off-topic&quot;&gt;https://github.com/NixOS/nixpkgs/pkgs/by-name/ab/abcde/package.nix:83Off-topic&lt;/a&gt;: this project’s website gives me heavy 90’s vibes, woah.&lt;/p&gt;
&lt;h3 id=&quot;hyperfine-engage&quot;&gt;&lt;code&gt;hyperfine&lt;/code&gt;, Engage&lt;/h3&gt;
&lt;p&gt;If you counted correctly, you should have four search terms, two data types, and eleven search approaches. We are skipping some combinations, e.g. “detailed search” is not supported on the O.G. &lt;code&gt;nps&lt;/code&gt;, and Tantivy and DuckDB can’t find anything shorter than 3 characters. In the end we have more than 80 distinctly different benchmarks. Some are run from Rust, some from the command line. To be able to compare them, we benchmark them with &lt;code&gt;[hyperfine](https://github.com/rmlmcfadden/hyperfine)&lt;/code&gt;. Bonus: on top of min-, max-, mean-, and median-runtimes we also get the memory usage of the runs. Nice!&lt;/p&gt;
&lt;p&gt;This is what a typical run on the command line looks like:&lt;/p&gt;
&lt;p&gt;$ hyperfine ‘nps neovim’
Benchmark 1: nps neovim
Time (mean ± σ):       6.0 ms ±   0.4 ms    [User: 1.5 ms, System: 4.4 ms]
Range (min … max):     5.0 ms …   7.3 ms    351 runsEven better, we can also get the results in JSON format. Unfortunately, this also means that it’s written to file.&lt;/p&gt;
&lt;p&gt;Sigh. So we have to read in that file to get the data we need. On the plus side, the JSON detour makes sure we don’t have any unforeseen hick-ups with data parsing, which could have happened if we wanted to retrieve the runtimes via regex from the output shown above.&lt;/p&gt;
&lt;p&gt;The JSON data looks like this:&lt;/p&gt;
&lt;p&gt;{
“results”: [
{
“command”: “nps neovim”,
“mean”: 0.006715249454725274,
“stddev”: 0.0026061538013605248,
“median”: 0.0065737821799999995,
“user”: 0.001504577142857143,
“system”: 0.005087126153846152,
“min”: 0.00505421018,
“max”: 0.03085960318,
“times”: [
0.03085960318,
0.00686827018,
…
],
“memory_usage_byte”: [
12791808,
12791808,
…
],
“exit_codes”: [
0,
0,
…
]
}
]
}For benchmarking, we are using &lt;code&gt;hyperfine&lt;/code&gt; the following way:&lt;/p&gt;
&lt;p&gt;hyperfine —shell=none —warmup=5 —export-json [filename] ‘COMMAND’Break-down of the moving parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--shell=none&lt;/code&gt; tells &lt;code&gt;hyperfine&lt;/code&gt; to, well, not start any shell. This shaves a few milliseconds off the benchmark score and allows for easier runtime comparisons.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--warmup=5&lt;/code&gt; tells &lt;code&gt;hyperfine&lt;/code&gt; to run &lt;code&gt;COMMAND&lt;/code&gt; 5 times before actually measuring the runtime. This makes sure that all files that are read are properly cached first.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--export-json [filename]&lt;/code&gt; tells &lt;code&gt;hyperfine&lt;/code&gt; to write out the data in JSON format.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gimme-numbers&quot;&gt;Gimme Numbers&lt;/h2&gt;
&lt;p&gt;Now to the fun part. Buckle up, it’s finally benchmark time! With repetitions, we have &gt;40.000 data retrieval runs.&lt;/p&gt;
&lt;p&gt;Below are all the tests we run against the above parameters and data types. To be able to compare apples to apples, these are the steps each approach conducts, unless noted otherwise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read in the data,&lt;/li&gt;
&lt;li&gt;Find package matches in the whole row (minimal databases) , or in the fields “package name”, “executable names”, and “package description (short)” (detailed databases),&lt;/li&gt;
&lt;li&gt;Split the matched data if necessary, so we have access to the “fields” of the data row,&lt;/li&gt;
&lt;li&gt;Collect the split data lines into an array, so we could sort and color them later, and&lt;/li&gt;
&lt;li&gt;Print all results to screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Disclaimer: Apart from &lt;em&gt;&lt;code&gt;*nps*&lt;/code&gt;&lt;/em&gt;, all search approaches are mostly vibe-coded with “Gemini 3 Pro Preview”. I wanted to iterate quickly to test as many approaches as needed. I did my best to avoid the common pitfalls, but it’s always possible that I missed something. To be fair, the same warning would apply if I coded it by hand.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This code will &lt;em&gt;not&lt;/em&gt; end up in production.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Once I identify the correct approach, I will re-write it from scratch and work it into the &lt;em&gt;&lt;code&gt;*nps*&lt;/code&gt;&lt;/em&gt; implementation. This way I make sure I am responsible for and understand every line of it.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;comparing-speed-against-current-nps&quot;&gt;Comparing Speed against Current &lt;code&gt;nps&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We start out to compare the new contenders against the existing approach. For this, we query the smaller, “minimal” database.&lt;/p&gt;
&lt;h3 id=&quot;nps-1&quot;&gt;&lt;code&gt;nps&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Providing a baseline, we try the current &lt;code&gt;nps&lt;/code&gt; program. It &lt;em&gt;should&lt;/em&gt; be slower than the other search implementations, since it provides the full pipeline instead of the four steps mentioned above; this includes forming proper columns and coloring the output.&lt;/p&gt;
&lt;p&gt;We also throw the Rust crate &lt;code&gt;grep&lt;/code&gt; into the ring; this is what &lt;code&gt;nps&lt;/code&gt; currently uses internally. Usually, Rust &lt;code&gt;grep&lt;/code&gt; likes to work with a data stream; this makes it really fast. For the benchmark, however, we are deliberately sabotaging its performance by collecting the output into a vector before printing. This is needed for the future &lt;code&gt;nps&lt;/code&gt; implementation, where we will sort the results and color them appropriately. Without hamstringing Rust &lt;code&gt;grep&lt;/code&gt;, the benchmark comparisons would not be entirely fair.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Regarding the data: often the &lt;em&gt;&lt;code&gt;*y*&lt;/code&gt;&lt;/em&gt;-axis (the vertical one) will be logarithmic. Each tick on the &lt;em&gt;&lt;code&gt;*y*&lt;/code&gt;&lt;/em&gt;-axis will denote “10x more than the previous one”. This makes sure we can comfortably see a difference between 2 ms, 2.5 ms and 2000 ms in the same plot.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-c8b7629b.DGTEI-TB_Z5Od7G.webp&quot; srcset=&quot;&quot;&gt;
Now we have something to aim for. If the pure search approach is slower than &lt;code&gt;nps&lt;/code&gt; – which includes creating columns and coloring the output – then we shout “boo!”. Is it faster than the current data retrieval “Rust grep”? Extra brownie points.&lt;/p&gt;
&lt;h3 id=&quot;gnu-grep&quot;&gt;GNU &lt;code&gt;grep&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;“Rust &lt;code&gt;grep&lt;/code&gt;” is already there. Now we compare it to “GNU grep” both from the command line and from within Rust. We keep the above run times for &lt;code&gt;nps&lt;/code&gt; and Rust &lt;code&gt;grep&lt;/code&gt; as a gray band for comparison.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-c3a768c9.GPlXR2xR_1TJjd.webp&quot; srcset=&quot;&quot;&gt;
The base speed is decent, but remarkably, the old “GNU &lt;code&gt;grep&lt;/code&gt; (CLI)” becomes &lt;em&gt;faster&lt;/em&gt; with shorter search terms. Afterwards there’s some extra work to do, namely splitting the lines into fields, negating this speed benefit somewhat. This run is labeled “GNU &lt;code&gt;grep&lt;/code&gt; (CLI, rs)”.&lt;/p&gt;
&lt;h3 id=&quot;ripgrep&quot;&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Will the Rust flavor of &lt;code&gt;grep&lt;/code&gt; fare any different?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-34a0003e.DkdtsC3M_1eaTBO.webp&quot; srcset=&quot;&quot;&gt;
Yes. Yes it does. Here we start faster than the “GNU &lt;code&gt;grep&lt;/code&gt; (CLI)” above, but take a bit more time the more matches we find, labeled “&lt;code&gt;ripgrep&lt;/code&gt; (CLI)”. Including line splitting, we’re competitive compared to &lt;code&gt;nps&lt;/code&gt;. This is marked as “&lt;code&gt;ripgrep&lt;/code&gt; (CLI, rs)”.&lt;/p&gt;
&lt;h3 id=&quot;tantivy&quot;&gt;&lt;code&gt;Tantivy&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Next, we put ChatGPT’s favorite through the wringer. Note that we are dropping the search for &lt;code&gt;e&lt;/code&gt;, since Tantivy cannot find it with the trigram matching in place.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-6e7b6b2c.BEF1GESd_ZPlmtJ.webp&quot; srcset=&quot;&quot;&gt;
While reasonably fast for few matches, it becomes pretty slow for increasing hits. Sad pony. After whining to ChatGPT about it, it suggests that it could have to do something with the number of files to be read. Doubtful, since it &lt;em&gt;can&lt;/em&gt; be fast for few matches. I’m not sure why it can’t keep up.&lt;/p&gt;
&lt;h3 id=&quot;duckdb&quot;&gt;&lt;code&gt;DuckDB&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We are probing three ducklings, one that uses &lt;code&gt;ILIKE&lt;/code&gt;, one that uses &lt;code&gt;regex&lt;/code&gt;, and the self-made &lt;code&gt;trigram&lt;/code&gt; indexing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-fd04450a.BCcx5qpP_gHCrQ.webp&quot; srcset=&quot;&quot;&gt;
Ok, this is bad. Really bad. Remember that we have a logarithmic &lt;code&gt;y&lt;/code&gt;-axis? The bump you see in the plot is the jump from 88 ms for searching for “nvim” to 2.3 s(!) for searching for “python”. For the letter “e” it probably uses the same fallback search that the other two versions have, since anything shorter than three letters not in the trigram index.&lt;/p&gt;
&lt;p&gt;Apparently Gemini cannot successfully hallucinate a feature which would take a small team of software engineers weeks to create, tune, polish, and test.&lt;/p&gt;
&lt;p&gt;Moving on. The other approaches are not disastrous, but they are not great either. Since DuckDB has to crawl through every row of data to find substring matches, that’s not too surprising. If we were searching for exact words &lt;em&gt;only&lt;/em&gt;, that would look much different. But alas, we’re not.&lt;/p&gt;
&lt;h3 id=&quot;sqlite&quot;&gt;&lt;code&gt;SQLite&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;How about the &lt;a href=&quot;https://en.wikipedia.org/wiki/Embedded_database#SQLite&quot;&gt;most widely deployed SQL database engine in the world&lt;/a&gt;?Fun fact, SQLite is open-source, but maybe not in a way you’d expect: instead of having a license attached, the code is entirely in the &lt;a href=&quot;https://sqlite.org/copyright.html&quot;&gt;Public Domain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-6b334e6c.govxRFMb_ZXex76.webp&quot; srcset=&quot;&quot;&gt;
Nice. For few-result queries, SQLite is &lt;em&gt;really&lt;/em&gt; fast. Approaching thousands of results, it’s on par with Rust &lt;code&gt;grep&lt;/code&gt; and only takes a moderate performance hit beyond that.&lt;/p&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Here we condense the above results in a single plot and aim for the realistic worst-case scenario of searching for “python”. The results are not spanning orders of magnitude, so the &lt;code&gt;y&lt;/code&gt;-axis is back to linear.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-ad585d61.BiwugPu__Z6kzfO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;comparing-speed-for-future-nps&quot;&gt;Comparing Speed for Future &lt;code&gt;nps&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To cut an entirely too long story slightly shorter, we get pretty much comparable results for querying the “detailed” database.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-aa3c82c3.McYyLmvj_Z2pSKee.webp&quot; srcset=&quot;&quot;&gt;
Let’s condense the above results in a single, easy-to-interpret table.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;409&quot; height=&quot;430&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-cf19c14b.CIHFNJx9_Z4hYYB.webp&quot; srcset=&quot;&quot;&gt;
So far Rust &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;ripgrep&lt;/code&gt; are leading the pack, with SQLite and GNU &lt;code&gt;grep&lt;/code&gt; hard on their virtual heels.&lt;/p&gt;
&lt;h3 id=&quot;database-size&quot;&gt;Database Size&lt;/h3&gt;
&lt;p&gt;That one is easy, we ask the disc usage tool &lt;code&gt;du&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;du —apparent-size -h *Break-down of the arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--apparent-size&lt;/code&gt; - show the size of the files as they would be without file-system compression, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-h&lt;/code&gt; - human-readable output, e.g. &lt;code&gt;M&lt;/code&gt; for megabytes instead of just bytes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On top of the plain size (as it would appear on a user’s machine), we also compress the databases with &lt;code&gt;gzip&lt;/code&gt; to see how large a typical download would be.&lt;/p&gt;
&lt;p&gt;$ du —apparent-size -h *
63M     detailed.sqlite
28M     detailed.sqlite.tar.gz
15M     detailed_duckdb.db
6.3M    detailed_duckdb.db.tar.gz
169M    detailed_duckdb_trigram.db
48M     detailed_duckdb_trigram.db.tar.gz
30M     detailed_tantivy_index
21M     detailed_tantivy_index.tar.gz
46M     minimal.sqlite
23M     minimal.sqlite.tar.gz
4.8M    minimal_duckdb.db
2.9M    minimal_duckdb.db.tar.gz
148M    minimal_duckdb_trigram.db
42M     minimal_duckdb_trigram.db.tar.gz
23M     minimal_tantivy_index
15M     minimal_tantivy_index.tar.gz
25M     package_list_detailed.txt
4.7M    package_list_detailed.txt.tar.gz
8.5M    package_list_minimal.txt
2.3M    package_list_minimal.txt.tar.gzIn the same discussion we also need to have a look at what updating the database with fresh package information would look like.&lt;/p&gt;
&lt;p&gt;For plain text files, we would either download the whole thing from scratch, or supply diff information, so the existing file could be “patched” with the updates. This would work on a per-row basis which is unfortunate, considering that most of the time you would have an updated version number. To make things worse, the diff would need to indicate the old data &lt;em&gt;and&lt;/em&gt; the new data. Not great.&lt;/p&gt;
&lt;p&gt;Tantivy cannot directly change data, but works with “delete” files that ignore entries. Once a data fragment is ignored in its entirety, it can be deleted. In practice this would mean that the local database size would slowly grow with “delete” files, until a whole, fresh database would be downloaded. The same per-row gotcha from plain text files applies here as well.&lt;/p&gt;
&lt;p&gt;DuckDB and SQLite not only support incremental updates, they also store the data as fields. This allows the updates to be tiny, containing just the information that has changed. This does require some data-dance of “downloadable full databases” and “incremental update files” as well as logic to combine those, but this is solvable.&lt;/p&gt;
&lt;p&gt;Summarized in a table:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;403&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-acd39667.DsJY5DAG_Z4A8Xp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;ram-usage&quot;&gt;RAM usage&lt;/h3&gt;
&lt;p&gt;For both “minimal” and “detailed” searches:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-7ab29ec9.DQKpIJuf_lI5rV.webp&quot; srcset=&quot;&quot;&gt;
This is excitingly unexciting. Ignoring the poor performance of DuckDB with bad &lt;code&gt;trigram&lt;/code&gt; indexing, the worst contender only uses a smidgen more than 30 Mb of RAM. This is fine for all but embedded systems, which would be outside the target group.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Tallied up in one neat overview:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;601&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-fbc295ef.gTMkNuhG_nOfVm.webp&quot; srcset=&quot;&quot;&gt;
The family of &lt;code&gt;grep&lt;/code&gt;s were surprisingly fast. They did a splendid job up till now, but do not scale too well with additional information. Larger datasets also introduce the challenge of download size for updating package information.&lt;/p&gt;
&lt;p&gt;Tantivy gallops quickly for few-result queries, but struggles a bit with large result sets. It’s unclear to me why that would be. Do let me know if you either know why, or point out where I made performance mistakes. Incremental updates are possible, but complicated.&lt;/p&gt;
&lt;p&gt;The paddling (this is the actual collective noun!) of ducks did not fare too well, no thanks to the missing N-gram indexing. It’s probably plenty fast for retrieving exact words, but that’s not what we’re after here. B̶u̶i̶l̶d̶i̶n̶g̶ ̶t̶h̶e̶ ̶i̶n̶d̶e̶x̶ ̶o̶u̶r̶s̶e̶l̶v̶e̶s̶ &lt;em&gt;Gemini vibing the index&lt;/em&gt; leads to the worst performance in all metrics. Shocker.&lt;/p&gt;
&lt;p&gt;SQLite truly shines here. Speed is great, even with many matches. The only challenge is the increased database size due to indexing, but this can be solved by both extra compression for downloads as well as tiny diff files for updating existing databases.&lt;/p&gt;
&lt;p&gt;Phew. That was longer than planned, but we finally have a candidate for the future &lt;code&gt;nps&lt;/code&gt; implementation.&lt;/p&gt;
&lt;h2 id=&quot;award-ceremony&quot;&gt;Award Ceremony&lt;/h2&gt;
&lt;p&gt;Due to outstanding scores in the “update” category, as well as excellent speed scores, we are handing the “cup of brrrrrr” to SQLite.&lt;/p&gt;
&lt;p&gt;🪶🏆👌&lt;/p&gt;
&lt;p&gt;The question of the data source remains unsolved. For the short term, I will scrape and provide the package data myself. Maybe in the future, &lt;code&gt;nixpkgs&lt;/code&gt; data could be offered as a SQLite database, or at least as a JSON file?&lt;/p&gt;
&lt;p&gt;But that, dear reader, is a challenge for another day.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They have their flaws as well. The packages that I want to check out are usually somewhere in the middle of a wall of text. Now I have to search the results of my previous search. Yay.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/peterldowns/nix-search-cli&quot;&gt;https://github.com/peterldowns/nix-search-cli&lt;/a&gt; and &lt;a href=&quot;https://github.com/nix-community/nh?tab=readme-ov-file#nh-search&quot;&gt;https://github.com/nix-community/nh?tab=readme-ov-file#nh-search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;About 27%, or 132,108 vs 103,640 — as of January 2026.&lt;/li&gt;
&lt;li&gt;This form of indexing stores strings of N letters pointing to the word they are extracted from: “duc”, “uck”, and “cks” would point to the word “ducks”, for N=3.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Wed, 18 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-bd7575b9.DXvMDkzN_Z1TbF5C.webp&quot; srcset=&quot;&quot;&gt;
I want this data, and I want it yesterday!&lt;em&gt;This post is adapted, with the &lt;em&gt;&lt;a href=&quot;https://ole-mn.medium.com/&quot;&gt;&lt;em&gt;author&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;’s permission and collaboration, from &lt;em&gt;&lt;a href=&quot;https://ole.mn/posts/2026-02-data-cache/&quot;&gt;&lt;em&gt;this post&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; in his personal blog.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is a quest. A quest for the right tool for the right job, for usability, and performance. We will torture databases, run tens of thousands of benchmarks and conjure charts, numbers, and tables. Because science. 🧑‍🔬&lt;/p&gt;
&lt;p&gt;But first, some background.&lt;/p&gt;
&lt;p&gt;The patient is the package search program &lt;code&gt;[nps](https://github.com/OleMussmann/nps/)&lt;/code&gt;, which provides information about all packages the &lt;code&gt;[nix](https://nixos.org/)&lt;/code&gt; package manager has to offer. What’s the patient’s complaint? &lt;code&gt;nps&lt;/code&gt; needs a better database and a better way to update its data.&lt;/p&gt;
&lt;p&gt;Erm, &lt;code&gt;nix&lt;/code&gt;? Never heard of it? It’s kinda special. Unlike &lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;pacman&lt;/code&gt;, or their siblings, it is declarative, reproducible and reliable. To top it off, it has a &lt;a href=&quot;https://repology.org/repositories/graphs&quot;&gt;gigantic library&lt;/a&gt;. If you don’t know what that means, no worries! Here’s a primer.&lt;/p&gt;
&lt;h2 id=&quot;nix-whats-that&quot;&gt;&lt;code&gt;nix&lt;/code&gt;? What’s That?&lt;/h2&gt;
&lt;p&gt;How do you set up your operating system? You install, for example, Ubuntu. Then you install a bunch of packages. You configure them. Then you set the wallpaper, the color scheme, the fonts, and make yourself at home. And if you set up a new system, you start again from square one. This whole process is &lt;em&gt;procedural&lt;/em&gt;, you follow one step after another. If you re-do all your steps again, you get the same result; and any changes to the recipe will result in a different outcome.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;nix&lt;/code&gt;, you describe the end state you want to have, and &lt;code&gt;nix&lt;/code&gt; will build and set up the system like you describe. Reliably. Reproducibly. &lt;code&gt;nix&lt;/code&gt; is &lt;em&gt;declarative&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Worry not, you can still apply tweaks and modifications. The desired end state including all customizations can be described in a single configuration file (keep it simple), or a set of files (make it modular). Let’s call this configuration file a “flake”. ❄️ Throw &lt;code&gt;git&lt;/code&gt; at this flake file and now you can jump between different versions on demand.&lt;/p&gt;
&lt;p&gt;If you share your flake with someone else, they can re-create the exact environment on their system. This is great for collaborative development! Runs on your computer? Runs everywhere. You can run other people’s software &lt;em&gt;without installing&lt;/em&gt;, and others can run yours. For even more portability, you can create Docker containers, virtual machines, or even a bootable ISO from your project.&lt;/p&gt;
&lt;p&gt;Sounds like magic? It comes close.&lt;/p&gt;
&lt;p&gt;Current gotchas include a lack of broad adoption, a steep learning curve for the &lt;code&gt;nix&lt;/code&gt; language, as well as not great (but improving) documentation. And, well, a distinct lack of a native, fast, offline program for searching packages.&lt;/p&gt;
&lt;h2 id=&quot;paper-cuts&quot;&gt;Paper Cuts&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;nix&lt;/code&gt;’s usability has, let’s say, still room for improvement. Prime example: how to find out which packages one can install. What do these packages do exactly, and what version do I get? The &lt;a href=&quot;https://wiki.nixos.org/wiki/Searching_packages&quot;&gt;recommended way&lt;/a&gt; is – drumroll – a website: &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;search.nixos.org/packages&lt;/a&gt;. It’s fast, comprehensive, and detailed. It works well.&lt;/p&gt;
&lt;p&gt;But it’s a website.&lt;/p&gt;
&lt;p&gt;When I’m pondering about installing packages, I’m not staring at a browser. I’m in the terminal. I want to have the equivalent of &lt;code&gt;apt search&lt;/code&gt; or &lt;code&gt;pacman -Ss&lt;/code&gt;¹.&lt;/p&gt;
&lt;p&gt;There are some wonderful CLI search programs out there², but they hook into the ElasticSearch database powering the backend of &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;search.nixos.org/packages&lt;/a&gt;. This means that you need to be online to get any package information, and (minor quibble, I know) it takes a bit for the information to appear on your screen.&lt;/p&gt;
&lt;h2 id=&quot;nps&quot;&gt;&lt;code&gt;nps&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I built the &lt;a href=&quot;https://github.com/OleMussmann/nps/&quot;&gt;Nix Package Search &lt;/a&gt;&lt;code&gt;[nps](https://github.com/OleMussmann/nps/)&lt;/code&gt; program to do my part to make &lt;code&gt;nix&lt;/code&gt; more user-friendly. &lt;code&gt;nps&lt;/code&gt; stores the package information locally, searches this cache, and presents the result – color-coded and sanely sorted. It works offline. It’s fast. It’s beautiful. Yeah, yeah, I know, I’m biased. Try it for yourself, though! Remember, you can run it without installing.&lt;/p&gt;
&lt;p&gt;Lately, &lt;a href=&quot;https://github.com/kevb1973&quot;&gt;kevb1973&lt;/a&gt; asked me to &lt;a href=&quot;https://github.com/OleMussmann/nps/issues/25&quot;&gt;provide more package information&lt;/a&gt; in the (dense) output that &lt;code&gt;nps&lt;/code&gt; provides. It’s a great idea and would increase the utility that &lt;code&gt;nps&lt;/code&gt; provides! Unfortunately, this is not something I can just bolt on to the existing program. Let’s have a look at the moving parts of &lt;code&gt;nps&lt;/code&gt; to understand why.&lt;/p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;
&lt;p&gt;Ok, architecture is a big word. Let me run by you how &lt;code&gt;nps&lt;/code&gt; currently works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;nix search nixpkgs ^&lt;/code&gt; – get all information for “all” packages.&lt;/li&gt;
&lt;li&gt;Create a text file with package names, versions, and descriptions and store them locally.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep&lt;/code&gt; through the text file (yes, it’s that low-tech) to find matches.&lt;/li&gt;
&lt;li&gt;Sort matches nicely into exact hits (searching for “avahi” matches package &lt;code&gt;avahi&lt;/code&gt;), direct hits (finds packages starting with “avahi”, e.g. &lt;code&gt;avahi-compat&lt;/code&gt;) and indirect hits (“avahi” appears anywhere in the package name or description).&lt;/li&gt;
&lt;li&gt;Create columns for better readability.&lt;/li&gt;
&lt;li&gt;Add a lick of paint to color-code the different types of matches.&lt;/li&gt;
&lt;li&gt;Print the result.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The issue: the data is stored as one row per package. Adding more information to each package row will make it harder for &lt;code&gt;grep&lt;/code&gt; to find the packages you’re looking for. This looks like a job for a “proper” database now. But which one? There’s plenty of cool tech out there, but which would be the “best” one for this use case?&lt;/p&gt;
&lt;h2 id=&quot;database-candidate-boundary-conditions&quot;&gt;Database Candidate Boundary Conditions&lt;/h2&gt;
&lt;p&gt;Alright, before we dive in, let’s define a few corner stones.&lt;/p&gt;
&lt;h3 id=&quot;data-source&quot;&gt;Data Source&lt;/h3&gt;
&lt;p&gt;Remember the &lt;code&gt;nix search&lt;/code&gt; command from above? It does not actually find “all” packages, &lt;a href=&quot;https://search.nixos.org&quot;&gt;https://search.nixos.org&lt;/a&gt; finds significantly more³. Why? No idea. Also, &lt;code&gt;nix search&lt;/code&gt; supplies only the package name, version, and description. No other information. Not great. Another aspect that’s missing is that packages might provide a differently named executable: you install the package &lt;code&gt;neovim&lt;/code&gt; and use the executable &lt;code&gt;nvim&lt;/code&gt;; some packages even provide multiple different executables. &lt;code&gt;nix search&lt;/code&gt; can’t find those.&lt;/p&gt;
&lt;p&gt;The data needs to come from a better source.&lt;/p&gt;
&lt;p&gt;The ElasticSearch backend is a good choice, but it’s meant to be queried, not downloaded. This means we have to scrape it in its entirety first.&lt;/p&gt;
&lt;p&gt;Setting up a project that does the scraping and regularly builds a cache that is usable by (a future version of) &lt;code&gt;nps&lt;/code&gt; is a task that goes beyond the scope of this post. Let’s assume for now that we have the data available, and we can squish (very scientific term here) it into any shape or form that we need for querying.&lt;/p&gt;
&lt;h3 id=&quot;substring-matching&quot;&gt;Substring Matching&lt;/h3&gt;
&lt;p&gt;Subwhat? A substring is a part of a string: “crow” is a substring of “miCROWave”. It can be anywhere in a string, beginning, middle, or end. When searching for “nvim” I want to find &lt;code&gt;nvim&lt;/code&gt; (duh!), as well as &lt;code&gt;nvimpager&lt;/code&gt; “use neovim as pager”, and &lt;code&gt;gnvim&lt;/code&gt; “GUI for neovim, without any web bloat”. As most databases are specialized in retrieving “exact” matches, substring matching might take some convincing.&lt;/p&gt;
&lt;h3 id=&quot;query-time&quot;&gt;Query Time&lt;/h3&gt;
&lt;p&gt;I want future &lt;code&gt;nps&lt;/code&gt; to stay fast. I’m happy with the responsiveness of the current implementation. To get a feeling for this, using &lt;code&gt;nps&lt;/code&gt; to search for the package &lt;code&gt;nps&lt;/code&gt; takes about 6ms on my desktop – so let’s take that as a baseline. If the pure data retrieval of the database candidates takes longer than current-&lt;code&gt;nps&lt;/code&gt;, then that’s a red flag, since sorting, coloring, etc. will take some extra time on top of that.&lt;/p&gt;
&lt;p&gt;Quick Cold Start**&lt;/p&gt;
&lt;p&gt;Related to “Query Time”: many “serious” databases are designed to run as a service; that makes querying fast, but you need something running in the background all the time. We don’t want that. Instead, we have a single program that starts up, queries a database, prints stuff, and then quits. This excludes many of the usual suspects like MySQL and its colleagues.&lt;/p&gt;
&lt;h3 id=&quot;data-amount&quot;&gt;Data Amount&lt;/h3&gt;
&lt;p&gt;The current data amount is about 8.5 Mb of package information and metadata for one &lt;code&gt;nixpkgs&lt;/code&gt; channel. The future, more detailed one (also including a long description, project URL and location within the &lt;code&gt;nixpkgs&lt;/code&gt; repo) would be 26 Mb of plain text. For three NixOS channels (“unstable”, “current stable”, “previous stable”), this would be about 80 Mb. While compression can bring this down a bit, some databases need to index their database to be able to search quickly; this will increase the data amount again. How much? That depends on the database used.&lt;/p&gt;
&lt;p&gt;The increased data amount is defensible when taking into account that one could regularly download the &lt;em&gt;incremental changes&lt;/em&gt; instead of the whole database for refreshing the cache.&lt;/p&gt;
&lt;p&gt;Yes, this is pretty hand-wavy for now. We’ll get more concrete about this later.&lt;/p&gt;
&lt;h3 id=&quot;memory-usage&quot;&gt;Memory Usage&lt;/h3&gt;
&lt;p&gt;A bit less crucial than the above, I’d like to use as little RAM as possible during the search. &lt;code&gt;nps&lt;/code&gt; is a guest on your machine and it should use only as much of your resources as needed.&lt;/p&gt;
&lt;p&gt;Many databases (as well as the good ol’ &lt;code&gt;grep&lt;/code&gt;) don’t load the whole data into memory before searching, they “crawl” through the data and drop the parts they have already used. I’d set that as a “nice to have”.&lt;/p&gt;
&lt;h2 id=&quot;database-candidates&quot;&gt;Database Candidates&lt;/h2&gt;
&lt;p&gt;First, let’s discuss the candidates and their structural strengths and weaknesses. We get to the hard numbers below, in the chapter &lt;a href=&quot;#37a0&quot;&gt;&lt;strong&gt;“Gimme Numbers!”&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;grep-a-text-file-&quot;&gt;&lt;code&gt;grep&lt;/code&gt; a Text File 🦖&lt;/h3&gt;
&lt;p&gt;Why change a working system? The old dinosaur &lt;code&gt;grep&lt;/code&gt; is fast. Really fast. We have the &lt;a href=&quot;https://www.gnu.org/software/grep/&quot;&gt;“GNU” flavor&lt;/a&gt; that runs on the command line, then there’s a &lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;Rust implementation called &lt;/a&gt;&lt;code&gt;[ripgrep](https://github.com/BurntSushi/ripgrep)&lt;/code&gt;, and lastly the &lt;a href=&quot;https://docs.rs/grep/latest/grep/&quot;&gt;Rust crate called &lt;/a&gt;&lt;code&gt;[grep](https://docs.rs/grep/latest/grep/)&lt;/code&gt;, which is – despite the name – closer to &lt;code&gt;ripgrep&lt;/code&gt; than to &lt;code&gt;grep&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let’s dial it up a notch. I’d like to see how just calling &lt;code&gt;grep&lt;/code&gt; or its cousin &lt;code&gt;ripgrep&lt;/code&gt; from the command line (equivalent to step 3. from &lt;a href=&quot;#architecture&quot;&gt;“Architecture”&lt;/a&gt;; we will label all those tests with the “CLI” suffix) compares to calling it from Rust and splitting the results (necessity for the “new” architecture). &lt;code&gt;ripgrep&lt;/code&gt; likes to work with streaming data, but we can’t do that if we want to form columns later. So what’s the overhead of the extra data mangling?&lt;/p&gt;
&lt;p&gt;That brings us to the following list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GNU &lt;code&gt;grep&lt;/code&gt; (called from CLI, results &lt;em&gt;not&lt;/em&gt; split)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ripgrep&lt;/code&gt; (called from CLI, results &lt;em&gt;not&lt;/em&gt; split)&lt;/li&gt;
&lt;li&gt;GNU &lt;code&gt;grep&lt;/code&gt; (called from Rust)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ripgrep&lt;/code&gt; (called from Rust)&lt;/li&gt;
&lt;li&gt;Rust crate &lt;code&gt;grep&lt;/code&gt; (called from Rust)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Simple&lt;/li&gt;
&lt;li&gt;Single file “database”&lt;/li&gt;
&lt;li&gt;Easy and good compression&lt;/li&gt;
&lt;li&gt;Trivial substring matching&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Extra finagling to only search certain parts of a line, yet still returning the whole row of data; in practice this means extra lines of code plus possibly a few extra gray hairs&lt;/li&gt;
&lt;li&gt;Incremental data updates are difficult&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;sqlite-&quot;&gt;SQLite 🪶&lt;/h3&gt;
&lt;p&gt;The gold standard for “simple” databases. Scales less well for serious applications than MySQL (or MariaDB or whatever), but should be “good enough” for a few hundred thousand packages.&lt;/p&gt;
&lt;p&gt;We use trigram (N-gram with N=3)⁴search to achieve fast substring matching. This makes it, well, fast. But it also inflates the database size and ignores any search terms shorter than 3 characters. One &lt;em&gt;could&lt;/em&gt; check for search string length and use a different matching algorithm for shorter terms, but is that worth the effort?&lt;/p&gt;
&lt;h3 id=&quot;benefits-1&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Single file database&lt;/li&gt;
&lt;li&gt;Battle-tested and stable&lt;/li&gt;
&lt;li&gt;“Proper” database queries, the results are well-structured&lt;/li&gt;
&lt;li&gt;Incremental updates are trivial&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trade-offs&quot;&gt;Trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;How compressible is an already compressed database?&lt;/li&gt;
&lt;li&gt;Needs indexing for fast substring matches, balancing database size vs performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks-1&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Compression per row, not on the whole file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;tantivy-&quot;&gt;Tantivy 🐎&lt;/h3&gt;
&lt;p&gt;I sparred with ChatGPT about which database to use, and it was very enthusiastic about Tantivy — we will see later if that was a good idea or not. It is designed for a quick cold-start and fast data retrieval, sounds like a match to me! Tantivy stores data in several files and has a &lt;code&gt;meta.json&lt;/code&gt; file to figure out what’s what.&lt;/p&gt;
&lt;p&gt;A quirk: technically, you can’t delete already stored data. Instead, you add a “delete” file that ignores entries and you can delete storage files that eventually become obsolete. Still, incremental updates should not be too hard this way. Every once in a while one would need to re-download the whole thing once the local index grew too large with all those “delete” files.&lt;/p&gt;
&lt;p&gt;Same as with &lt;code&gt;SQLite&lt;/code&gt;, we use trigram matching for speed, with the same benefits and drawbacks.&lt;/p&gt;
&lt;h3 id=&quot;benefits-2&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Pretty much designed for this purpose&lt;/li&gt;
&lt;li&gt;Incremental updates are easy&lt;/li&gt;
&lt;li&gt;“Proper” database queries, the results are well-structured&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trade-offs-1&quot;&gt;Trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The database is a folder with multiple files&lt;/li&gt;
&lt;li&gt;Needs indexing for fast substring matches, balancing database size vs performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks-2&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Incremental updates do need a strategy, with an occasional fresh download of the whole database&lt;/li&gt;
&lt;li&gt;The many files might take some time to read, benchmarks will tell if that’s an issue&lt;/li&gt;
&lt;li&gt;Compression per row, not on the whole file&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;duckdb-&quot;&gt;DuckDB 🦆&lt;/h3&gt;
&lt;p&gt;Completing our zoo is the new duckling on the block. DuckDB sports rad analytics which might be handy for retrieving already correctly sorted search results.&lt;/p&gt;
&lt;p&gt;However, DuckDB can’t do N-grams. &lt;a href=&quot;https://github.com/duckdb/duckdb/discussions/16071&quot;&gt;Yet&lt;/a&gt;. Sad quack.&lt;/p&gt;
&lt;p&gt;What can we do instead?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Benchmark the slower, standard way of case-insensitive substring matching, called &lt;code&gt;ILIKE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Benchmark the slower, other way of case-insensitive substring matching with regular expressions: &lt;code&gt;regex&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Who needs built-in N-gram indexing when Gemini can build one (let’s call it &lt;code&gt;trigram&lt;/code&gt;) for you? We will soon find out if that’s a good idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;benefits-3&quot;&gt;Benefits&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ducks are cool&lt;/li&gt;
&lt;li&gt;Single file database&lt;/li&gt;
&lt;li&gt;Supports incremental updates&lt;/li&gt;
&lt;li&gt;“Proper” database queries, the results are well-structured&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;trade-offs-2&quot;&gt;Trade-offs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Would the analytics work for proper sorting?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;drawbacks-3&quot;&gt;Drawbacks&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;No built-in N-gram indexing for fast substring matching, uh oh!&lt;/li&gt;
&lt;li&gt;Compression per row, not on the whole file&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;benchmarking-boundary-conditions&quot;&gt;Benchmarking Boundary Conditions&lt;/h2&gt;
&lt;p&gt;We will be testing for a lot of things at once, here’s a break-down.&lt;/p&gt;
&lt;h3 id=&quot;parameters&quot;&gt;Parameters&lt;/h3&gt;
&lt;p&gt;We are searching for four different search terms with increasing number of matches. This should give us enough data points to make out a trend.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“nps” (21 matches)&lt;/li&gt;
&lt;li&gt;“nvim” (1301 matches)&lt;/li&gt;
&lt;li&gt;“python” (21123 matches)&lt;/li&gt;
&lt;li&gt;“e” (131567 matches, almost the whole database)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;data-types&quot;&gt;Data Types&lt;/h3&gt;
&lt;p&gt;To be able to compare database performances with the current implementation of &lt;code&gt;nps&lt;/code&gt; we start with a “minimal” database, containing the package name, version, and short description. This mirrors the current implementation of &lt;code&gt;nps&lt;/code&gt; and allows for comparisons.&lt;/p&gt;
&lt;p&gt;The entire “minimal” data for the &lt;code&gt;abcde&lt;/code&gt; package look like this:&lt;/p&gt;
&lt;p&gt;abcde   2.9.3   Command-line audio CD ripperThen we try a “detailed” database, containing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;package name&lt;/li&gt;
&lt;li&gt;executable names (which might be different than the package name)&lt;/li&gt;
&lt;li&gt;version&lt;/li&gt;
&lt;li&gt;description (short)&lt;/li&gt;
&lt;li&gt;description (long)&lt;/li&gt;
&lt;li&gt;homepage URL&lt;/li&gt;
&lt;li&gt;and the URL to the package in the &lt;code&gt;nixpkgs&lt;/code&gt; repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Formatted, the information for the same package could look like this:&lt;/p&gt;
&lt;p&gt;abcde [abcde-musicbrainz-tool, abcde, cddb-tool]  2.9.3&lt;/p&gt;
&lt;p&gt;Command-line audio CD ripper
abcde is a front-end command-line utility (actually, a shell
script) that grabs tracks off a CD, encodes them to Ogg/Vorbis,
MP3, FLAC, Ogg/Speex and/or MPP/MP+ (Musepack) format, and tags
them, all in one go.
Project URL: &lt;a href=&quot;http://abcde.einval.com/wiki/&quot;&gt;http://abcde.einval.com/wiki/&lt;/a&gt;
Nixpkgs URL: &lt;a href=&quot;https://github.com/NixOS/nixpkgs/pkgs/by-name/ab/abcde/package.nix:83Off-topic&quot;&gt;https://github.com/NixOS/nixpkgs/pkgs/by-name/ab/abcde/package.nix:83Off-topic&lt;/a&gt;: this project’s website gives me heavy 90’s vibes, woah.&lt;/p&gt;
&lt;h3 id=&quot;hyperfine-engage&quot;&gt;&lt;code&gt;hyperfine&lt;/code&gt;, Engage&lt;/h3&gt;
&lt;p&gt;If you counted correctly, you should have four search terms, two data types, and eleven search approaches. We are skipping some combinations, e.g. “detailed search” is not supported on the O.G. &lt;code&gt;nps&lt;/code&gt;, and Tantivy and DuckDB can’t find anything shorter than 3 characters. In the end we have more than 80 distinctly different benchmarks. Some are run from Rust, some from the command line. To be able to compare them, we benchmark them with &lt;code&gt;[hyperfine](https://github.com/rmlmcfadden/hyperfine)&lt;/code&gt;. Bonus: on top of min-, max-, mean-, and median-runtimes we also get the memory usage of the runs. Nice!&lt;/p&gt;
&lt;p&gt;This is what a typical run on the command line looks like:&lt;/p&gt;
&lt;p&gt;$ hyperfine ‘nps neovim’
Benchmark 1: nps neovim
Time (mean ± σ):       6.0 ms ±   0.4 ms    [User: 1.5 ms, System: 4.4 ms]
Range (min … max):     5.0 ms …   7.3 ms    351 runsEven better, we can also get the results in JSON format. Unfortunately, this also means that it’s written to file.&lt;/p&gt;
&lt;p&gt;Sigh. So we have to read in that file to get the data we need. On the plus side, the JSON detour makes sure we don’t have any unforeseen hick-ups with data parsing, which could have happened if we wanted to retrieve the runtimes via regex from the output shown above.&lt;/p&gt;
&lt;p&gt;The JSON data looks like this:&lt;/p&gt;
&lt;p&gt;{
“results”: [
{
“command”: “nps neovim”,
“mean”: 0.006715249454725274,
“stddev”: 0.0026061538013605248,
“median”: 0.0065737821799999995,
“user”: 0.001504577142857143,
“system”: 0.005087126153846152,
“min”: 0.00505421018,
“max”: 0.03085960318,
“times”: [
0.03085960318,
0.00686827018,
…
],
“memory_usage_byte”: [
12791808,
12791808,
…
],
“exit_codes”: [
0,
0,
…
]
}
]
}For benchmarking, we are using &lt;code&gt;hyperfine&lt;/code&gt; the following way:&lt;/p&gt;
&lt;p&gt;hyperfine —shell=none —warmup=5 —export-json [filename] ‘COMMAND’Break-down of the moving parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--shell=none&lt;/code&gt; tells &lt;code&gt;hyperfine&lt;/code&gt; to, well, not start any shell. This shaves a few milliseconds off the benchmark score and allows for easier runtime comparisons.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--warmup=5&lt;/code&gt; tells &lt;code&gt;hyperfine&lt;/code&gt; to run &lt;code&gt;COMMAND&lt;/code&gt; 5 times before actually measuring the runtime. This makes sure that all files that are read are properly cached first.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--export-json [filename]&lt;/code&gt; tells &lt;code&gt;hyperfine&lt;/code&gt; to write out the data in JSON format.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;gimme-numbers&quot;&gt;Gimme Numbers&lt;/h2&gt;
&lt;p&gt;Now to the fun part. Buckle up, it’s finally benchmark time! With repetitions, we have &gt;40.000 data retrieval runs.&lt;/p&gt;
&lt;p&gt;Below are all the tests we run against the above parameters and data types. To be able to compare apples to apples, these are the steps each approach conducts, unless noted otherwise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read in the data,&lt;/li&gt;
&lt;li&gt;Find package matches in the whole row (minimal databases) , or in the fields “package name”, “executable names”, and “package description (short)” (detailed databases),&lt;/li&gt;
&lt;li&gt;Split the matched data if necessary, so we have access to the “fields” of the data row,&lt;/li&gt;
&lt;li&gt;Collect the split data lines into an array, so we could sort and color them later, and&lt;/li&gt;
&lt;li&gt;Print all results to screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Disclaimer: Apart from &lt;em&gt;&lt;code&gt;*nps*&lt;/code&gt;&lt;/em&gt;, all search approaches are mostly vibe-coded with “Gemini 3 Pro Preview”. I wanted to iterate quickly to test as many approaches as needed. I did my best to avoid the common pitfalls, but it’s always possible that I missed something. To be fair, the same warning would apply if I coded it by hand.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This code will &lt;em&gt;not&lt;/em&gt; end up in production.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Once I identify the correct approach, I will re-write it from scratch and work it into the &lt;em&gt;&lt;code&gt;*nps*&lt;/code&gt;&lt;/em&gt; implementation. This way I make sure I am responsible for and understand every line of it.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;comparing-speed-against-current-nps&quot;&gt;Comparing Speed against Current &lt;code&gt;nps&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We start out to compare the new contenders against the existing approach. For this, we query the smaller, “minimal” database.&lt;/p&gt;
&lt;h3 id=&quot;nps-1&quot;&gt;&lt;code&gt;nps&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Providing a baseline, we try the current &lt;code&gt;nps&lt;/code&gt; program. It &lt;em&gt;should&lt;/em&gt; be slower than the other search implementations, since it provides the full pipeline instead of the four steps mentioned above; this includes forming proper columns and coloring the output.&lt;/p&gt;
&lt;p&gt;We also throw the Rust crate &lt;code&gt;grep&lt;/code&gt; into the ring; this is what &lt;code&gt;nps&lt;/code&gt; currently uses internally. Usually, Rust &lt;code&gt;grep&lt;/code&gt; likes to work with a data stream; this makes it really fast. For the benchmark, however, we are deliberately sabotaging its performance by collecting the output into a vector before printing. This is needed for the future &lt;code&gt;nps&lt;/code&gt; implementation, where we will sort the results and color them appropriately. Without hamstringing Rust &lt;code&gt;grep&lt;/code&gt;, the benchmark comparisons would not be entirely fair.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Regarding the data: often the &lt;em&gt;&lt;code&gt;*y*&lt;/code&gt;&lt;/em&gt;-axis (the vertical one) will be logarithmic. Each tick on the &lt;em&gt;&lt;code&gt;*y*&lt;/code&gt;&lt;/em&gt;-axis will denote “10x more than the previous one”. This makes sure we can comfortably see a difference between 2 ms, 2.5 ms and 2000 ms in the same plot.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-c8b7629b.DGTEI-TB_Z5Od7G.webp&quot; srcset=&quot;&quot;&gt;
Now we have something to aim for. If the pure search approach is slower than &lt;code&gt;nps&lt;/code&gt; – which includes creating columns and coloring the output – then we shout “boo!”. Is it faster than the current data retrieval “Rust grep”? Extra brownie points.&lt;/p&gt;
&lt;h3 id=&quot;gnu-grep&quot;&gt;GNU &lt;code&gt;grep&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;“Rust &lt;code&gt;grep&lt;/code&gt;” is already there. Now we compare it to “GNU grep” both from the command line and from within Rust. We keep the above run times for &lt;code&gt;nps&lt;/code&gt; and Rust &lt;code&gt;grep&lt;/code&gt; as a gray band for comparison.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-c3a768c9.GPlXR2xR_1TJjd.webp&quot; srcset=&quot;&quot;&gt;
The base speed is decent, but remarkably, the old “GNU &lt;code&gt;grep&lt;/code&gt; (CLI)” becomes &lt;em&gt;faster&lt;/em&gt; with shorter search terms. Afterwards there’s some extra work to do, namely splitting the lines into fields, negating this speed benefit somewhat. This run is labeled “GNU &lt;code&gt;grep&lt;/code&gt; (CLI, rs)”.&lt;/p&gt;
&lt;h3 id=&quot;ripgrep&quot;&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Will the Rust flavor of &lt;code&gt;grep&lt;/code&gt; fare any different?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-34a0003e.DkdtsC3M_1eaTBO.webp&quot; srcset=&quot;&quot;&gt;
Yes. Yes it does. Here we start faster than the “GNU &lt;code&gt;grep&lt;/code&gt; (CLI)” above, but take a bit more time the more matches we find, labeled “&lt;code&gt;ripgrep&lt;/code&gt; (CLI)”. Including line splitting, we’re competitive compared to &lt;code&gt;nps&lt;/code&gt;. This is marked as “&lt;code&gt;ripgrep&lt;/code&gt; (CLI, rs)”.&lt;/p&gt;
&lt;h3 id=&quot;tantivy&quot;&gt;&lt;code&gt;Tantivy&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Next, we put ChatGPT’s favorite through the wringer. Note that we are dropping the search for &lt;code&gt;e&lt;/code&gt;, since Tantivy cannot find it with the trigram matching in place.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-6e7b6b2c.BEF1GESd_ZPlmtJ.webp&quot; srcset=&quot;&quot;&gt;
While reasonably fast for few matches, it becomes pretty slow for increasing hits. Sad pony. After whining to ChatGPT about it, it suggests that it could have to do something with the number of files to be read. Doubtful, since it &lt;em&gt;can&lt;/em&gt; be fast for few matches. I’m not sure why it can’t keep up.&lt;/p&gt;
&lt;h3 id=&quot;duckdb&quot;&gt;&lt;code&gt;DuckDB&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We are probing three ducklings, one that uses &lt;code&gt;ILIKE&lt;/code&gt;, one that uses &lt;code&gt;regex&lt;/code&gt;, and the self-made &lt;code&gt;trigram&lt;/code&gt; indexing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-fd04450a.BCcx5qpP_gHCrQ.webp&quot; srcset=&quot;&quot;&gt;
Ok, this is bad. Really bad. Remember that we have a logarithmic &lt;code&gt;y&lt;/code&gt;-axis? The bump you see in the plot is the jump from 88 ms for searching for “nvim” to 2.3 s(!) for searching for “python”. For the letter “e” it probably uses the same fallback search that the other two versions have, since anything shorter than three letters not in the trigram index.&lt;/p&gt;
&lt;p&gt;Apparently Gemini cannot successfully hallucinate a feature which would take a small team of software engineers weeks to create, tune, polish, and test.&lt;/p&gt;
&lt;p&gt;Moving on. The other approaches are not disastrous, but they are not great either. Since DuckDB has to crawl through every row of data to find substring matches, that’s not too surprising. If we were searching for exact words &lt;em&gt;only&lt;/em&gt;, that would look much different. But alas, we’re not.&lt;/p&gt;
&lt;h3 id=&quot;sqlite&quot;&gt;&lt;code&gt;SQLite&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;How about the &lt;a href=&quot;https://en.wikipedia.org/wiki/Embedded_database#SQLite&quot;&gt;most widely deployed SQL database engine in the world&lt;/a&gt;?Fun fact, SQLite is open-source, but maybe not in a way you’d expect: instead of having a license attached, the code is entirely in the &lt;a href=&quot;https://sqlite.org/copyright.html&quot;&gt;Public Domain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-6b334e6c.govxRFMb_ZXex76.webp&quot; srcset=&quot;&quot;&gt;
Nice. For few-result queries, SQLite is &lt;em&gt;really&lt;/em&gt; fast. Approaching thousands of results, it’s on par with Rust &lt;code&gt;grep&lt;/code&gt; and only takes a moderate performance hit beyond that.&lt;/p&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;Here we condense the above results in a single plot and aim for the realistic worst-case scenario of searching for “python”. The results are not spanning orders of magnitude, so the &lt;code&gt;y&lt;/code&gt;-axis is back to linear.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-ad585d61.BiwugPu__Z6kzfO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;comparing-speed-for-future-nps&quot;&gt;Comparing Speed for Future &lt;code&gt;nps&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To cut an entirely too long story slightly shorter, we get pretty much comparable results for querying the “detailed” database.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-aa3c82c3.McYyLmvj_Z2pSKee.webp&quot; srcset=&quot;&quot;&gt;
Let’s condense the above results in a single, easy-to-interpret table.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;409&quot; height=&quot;430&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-cf19c14b.CIHFNJx9_Z4hYYB.webp&quot; srcset=&quot;&quot;&gt;
So far Rust &lt;code&gt;grep&lt;/code&gt; and &lt;code&gt;ripgrep&lt;/code&gt; are leading the pack, with SQLite and GNU &lt;code&gt;grep&lt;/code&gt; hard on their virtual heels.&lt;/p&gt;
&lt;h3 id=&quot;database-size&quot;&gt;Database Size&lt;/h3&gt;
&lt;p&gt;That one is easy, we ask the disc usage tool &lt;code&gt;du&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;du —apparent-size -h *Break-down of the arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--apparent-size&lt;/code&gt; - show the size of the files as they would be without file-system compression, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-h&lt;/code&gt; - human-readable output, e.g. &lt;code&gt;M&lt;/code&gt; for megabytes instead of just bytes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On top of the plain size (as it would appear on a user’s machine), we also compress the databases with &lt;code&gt;gzip&lt;/code&gt; to see how large a typical download would be.&lt;/p&gt;
&lt;p&gt;$ du —apparent-size -h *
63M     detailed.sqlite
28M     detailed.sqlite.tar.gz
15M     detailed_duckdb.db
6.3M    detailed_duckdb.db.tar.gz
169M    detailed_duckdb_trigram.db
48M     detailed_duckdb_trigram.db.tar.gz
30M     detailed_tantivy_index
21M     detailed_tantivy_index.tar.gz
46M     minimal.sqlite
23M     minimal.sqlite.tar.gz
4.8M    minimal_duckdb.db
2.9M    minimal_duckdb.db.tar.gz
148M    minimal_duckdb_trigram.db
42M     minimal_duckdb_trigram.db.tar.gz
23M     minimal_tantivy_index
15M     minimal_tantivy_index.tar.gz
25M     package_list_detailed.txt
4.7M    package_list_detailed.txt.tar.gz
8.5M    package_list_minimal.txt
2.3M    package_list_minimal.txt.tar.gzIn the same discussion we also need to have a look at what updating the database with fresh package information would look like.&lt;/p&gt;
&lt;p&gt;For plain text files, we would either download the whole thing from scratch, or supply diff information, so the existing file could be “patched” with the updates. This would work on a per-row basis which is unfortunate, considering that most of the time you would have an updated version number. To make things worse, the diff would need to indicate the old data &lt;em&gt;and&lt;/em&gt; the new data. Not great.&lt;/p&gt;
&lt;p&gt;Tantivy cannot directly change data, but works with “delete” files that ignore entries. Once a data fragment is ignored in its entirety, it can be deleted. In practice this would mean that the local database size would slowly grow with “delete” files, until a whole, fresh database would be downloaded. The same per-row gotcha from plain text files applies here as well.&lt;/p&gt;
&lt;p&gt;DuckDB and SQLite not only support incremental updates, they also store the data as fields. This allows the updates to be tiny, containing just the information that has changed. This does require some data-dance of “downloadable full databases” and “incremental update files” as well as logic to combine those, but this is solvable.&lt;/p&gt;
&lt;p&gt;Summarized in a table:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;403&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-acd39667.DsJY5DAG_Z4A8Xp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;ram-usage&quot;&gt;RAM usage&lt;/h3&gt;
&lt;p&gt;For both “minimal” and “detailed” searches:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-7ab29ec9.DQKpIJuf_lI5rV.webp&quot; srcset=&quot;&quot;&gt;
This is excitingly unexciting. Ignoring the poor performance of DuckDB with bad &lt;code&gt;trigram&lt;/code&gt; indexing, the worst contender only uses a smidgen more than 30 Mb of RAM. This is fine for all but embedded systems, which would be outside the target group.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Tallied up in one neat overview:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Give Me Data, Yesterday&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;601&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-fbc295ef.gTMkNuhG_nOfVm.webp&quot; srcset=&quot;&quot;&gt;
The family of &lt;code&gt;grep&lt;/code&gt;s were surprisingly fast. They did a splendid job up till now, but do not scale too well with additional information. Larger datasets also introduce the challenge of download size for updating package information.&lt;/p&gt;
&lt;p&gt;Tantivy gallops quickly for few-result queries, but struggles a bit with large result sets. It’s unclear to me why that would be. Do let me know if you either know why, or point out where I made performance mistakes. Incremental updates are possible, but complicated.&lt;/p&gt;
&lt;p&gt;The paddling (this is the actual collective noun!) of ducks did not fare too well, no thanks to the missing N-gram indexing. It’s probably plenty fast for retrieving exact words, but that’s not what we’re after here. B̶u̶i̶l̶d̶i̶n̶g̶ ̶t̶h̶e̶ ̶i̶n̶d̶e̶x̶ ̶o̶u̶r̶s̶e̶l̶v̶e̶s̶ &lt;em&gt;Gemini vibing the index&lt;/em&gt; leads to the worst performance in all metrics. Shocker.&lt;/p&gt;
&lt;p&gt;SQLite truly shines here. Speed is great, even with many matches. The only challenge is the increased database size due to indexing, but this can be solved by both extra compression for downloads as well as tiny diff files for updating existing databases.&lt;/p&gt;
&lt;p&gt;Phew. That was longer than planned, but we finally have a candidate for the future &lt;code&gt;nps&lt;/code&gt; implementation.&lt;/p&gt;
&lt;h2 id=&quot;award-ceremony&quot;&gt;Award Ceremony&lt;/h2&gt;
&lt;p&gt;Due to outstanding scores in the “update” category, as well as excellent speed scores, we are handing the “cup of brrrrrr” to SQLite.&lt;/p&gt;
&lt;p&gt;🪶🏆👌&lt;/p&gt;
&lt;p&gt;The question of the data source remains unsolved. For the short term, I will scrape and provide the package data myself. Maybe in the future, &lt;code&gt;nixpkgs&lt;/code&gt; data could be offered as a SQLite database, or at least as a JSON file?&lt;/p&gt;
&lt;p&gt;But that, dear reader, is a challenge for another day.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They have their flaws as well. The packages that I want to check out are usually somewhere in the middle of a wall of text. Now I have to search the results of my previous search. Yay.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/peterldowns/nix-search-cli&quot;&gt;https://github.com/peterldowns/nix-search-cli&lt;/a&gt; and &lt;a href=&quot;https://github.com/nix-community/nh?tab=readme-ov-file#nh-search&quot;&gt;https://github.com/nix-community/nh?tab=readme-ov-file#nh-search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;About 27%, or 132,108 vs 103,640 — as of January 2026.&lt;/li&gt;
&lt;li&gt;This form of indexing stores strings of N letters pointing to the word they are extracted from: “duc”, “uck”, and “cks” would point to the word “ducks”, for N=3.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/give-me-data-yesterday-c8b7629b.DGTEI-TB.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Making LLMs Work for Science: How AI-Powered Storytelling Helps Researchers Communicate Their Software</title><link>https://blog2.esciencecenter.nl/posts/2026-02-26---making-llms-work-for-science-how-ai-powered-storytelling-hel</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-02-26---making-llms-work-for-science-how-ai-powered-storytelling-hel</guid><description>&lt;p&gt;Large language models get a lot of attention in research for what they might replace. We wanted to explore what they can enable: better, faster scientific communication that actually reaches the right audiences.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1372&quot; height=&quot;755&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_d1EFyNcb4difLC1_5QkMvg-a2755dce.CIpdYCd3_Z1MrcDA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Welcome page on the storytelling application.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Authors:&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/jesse-gonzalez/&quot;&gt;&lt;em&gt;Jesse González&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/pablo-rodriguez-sanchez/&quot;&gt;&lt;em&gt;Pablo Rodríguez&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/kody-moodley/&quot;&gt;&lt;em&gt;Kody Moodley&lt;/em&gt;&lt;/a&gt;*&lt;br&gt;
Application:* &lt;a href=&quot;https://nlesc.github.io/data-storytelling/&quot;&gt;https://nlesc.github.io/data-storytelling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There’s an ongoing conversation in the research community about large language models. Most of it focuses on risks: hallucinations, bias, the worry that generated text might replace genuine scholarly work. Those concerns are valid and worth taking seriously.&lt;/p&gt;
&lt;p&gt;But there’s another side to this conversation that doesn’t get enough attention. LLMs can be genuinely useful tools when they’re pointed at the right problems, with the right constraints and the right human oversight. Scientific communication is one of those problems.&lt;/p&gt;
&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we build research software across four scientific domains: &lt;strong&gt;Environment &amp;#x26; Sustainability&lt;/strong&gt;, &lt;strong&gt;Life Sciences&lt;/strong&gt;, &lt;strong&gt;Natural Sciences&lt;/strong&gt; &amp;#x26; &lt;strong&gt;Engineering&lt;/strong&gt; and &lt;strong&gt;Social Sciences &amp;#x26; Humanities&lt;/strong&gt;. This means hundreds of projects, each of them representing months or years of collaborative work with research teams across the country and internationally, all catalogued in the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt;. The software is solid, sometimes groundbreaking. But communicating that work to different audiences (the public, academic peers, funders, workshop participants) takes time that most research teams simply don’t have. There’s a persistent gap between the research software we produce and the stories we tell about it.&lt;/p&gt;
&lt;p&gt;We built a tool to close that gap. And in doing so, we learned some things about what it actually looks like when LLMs serve science instead of the other way around.&lt;/p&gt;
&lt;h2 id=&quot;an-interactive-journey-through-four-research-domains&quot;&gt;An interactive journey through four research domains&lt;/h2&gt;
&lt;p&gt;The first thing you see when you open the &lt;a href=&quot;https://github.com/NLeSC/data-storytelling&quot;&gt;Data Storytelling app&lt;/a&gt; is a 3D particle system. Not a dashboard. Not a table. A cloud of two thousand glowing dots that shift and pulse as you scroll down the page.&lt;/p&gt;
&lt;p&gt;The idea was simple: before you read a single word about a piece of software, you should already have a sense of the research domain it belongs to. Visuals create that context faster than text ever could.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1358&quot; height=&quot;844&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jHWTVqw8VvdPdCDGuCnAZA-1ec471a4.iXSBXRak_2b2YLV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Floating projects retrieved via the Research Software Directory&lt;/p&gt;
&lt;p&gt;The entire application is one long scroll. As you move down, you pass through the domains, each with its own custom 3D scene built in &lt;em&gt;Three.js&lt;/em&gt;. Each 3D scene is peppered with floating cards. Actual projects from the Research Software Directory, fetched live from the API. You hover over one, it glows and scales up. You click it and boom, a modal with the full project details. Description, DOI, metadata, links.&lt;/p&gt;
&lt;p&gt;And tucked inside that modal? A tab labelled “ &lt;strong&gt;Generate Story.&lt;/strong&gt;” That’s where the real magic happens.&lt;/p&gt;
&lt;h2 id=&quot;the-communication-bottleneck-in-research-software&quot;&gt;The communication bottleneck in research software&lt;/h2&gt;
&lt;p&gt;Anyone in research communications will recognise this situation.&lt;/p&gt;
&lt;p&gt;You’ve got a brilliant piece of software. It does something novel with satellite imagery or protein folding or natural language processing for historical Dutch manuscripts. You need to write about it. But write about it for &lt;strong&gt;whom&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;The version for the general public needs to be warm, accessible, maybe open with a compelling question like &lt;em&gt;“What if we could predict floods before they happen?”&lt;/em&gt; The version for an academic journal needs an abstract, proper methodology discussion, and citations formatted just so. The internal review for your board needs FTE estimates, risk assessments, and honest talk about technical debt. And your programme director just wants a one-pager they can scan in three minutes between meetings.&lt;/p&gt;
&lt;p&gt;Same project. Four different pieces of writing. And you need to do this for a hundred projects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is where good research software becomes invisible. Not because the work isn’t worth communicating, but because the communication itself is a bottleneck.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The software ships, the README gets written, maybe a tweet goes out, and that’s it. Months of collaborative work, reduced to a paragraph.&lt;/p&gt;
&lt;p&gt;This is also precisely the kind of problem where LLMs can be a real asset to researchers. Not as a replacement for human judgment, but as a drafting tool that handles the structural heavy lifting: tone calibration, audience adaptation, first-pass content generation. The key is being intentional about how you use them. Not &lt;em&gt;“throw a description at a chatbot and hope for the best”&lt;/em&gt;, but structured, context-rich prompts designed for specific communication goals.&lt;/p&gt;
&lt;h2 id=&quot;generating-stories-feeding-the-model-with-extra-information&quot;&gt;Generating stories feeding the model with extra information&lt;/h2&gt;
&lt;p&gt;The generator pulls related software from the same research domain via the RSD API, without any extra effort from the user. So if you’re generating a story about a climate modelling tool, &lt;strong&gt;it already knows about the other environmental software in the ecosystem and can reference them&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;851&quot; height=&quot;1041&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_w9zVYbuhgtBu_JsNujBL3g-231cdb75.DyuLa9XF_1YkGaM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Project &amp;#x26; Software Information&lt;/p&gt;
&lt;p&gt;You can also upload documents. PDFs, text files, markdown. Research proposals work great for this. The app extracts the text (up to 10,000 characters worth), folds it into the prompt, and the output goes from generic to grounded in specifics.&lt;/p&gt;
&lt;p&gt;For custom projects (things not in the RSD) there’s an “Own Project” button in the top navigation. Pop in a title, description, some reference URLs, upload whatever context you’ve got, pick your audience, and off you go. Same six templates, same quality, no RSD dependency.&lt;/p&gt;
&lt;h2 id=&quot;six-audiences-six-different-stories&quot;&gt;Six audiences, six different stories&lt;/h2&gt;
&lt;p&gt;The story generator ships with six prompt templates. I want to be specific about what these are, because “prompt template” sounds trivial and these are anything but.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1362&quot; height=&quot;1418&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CE8C0Vl-iE0Xjfy3E71HVw-084e4c64.ByNQYqe-_Z1Oa3eq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Generating the story given the selected audience.&lt;/p&gt;
&lt;p&gt;Each one is 500-plus words of careful instructions, closer to a creative brief than a prompt. They specify structure, tone, section order, word count targets, what to emphasise, what to skip. Here’s what each does:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Communications&lt;/strong&gt; (roughly 800 to 1,200 words). Tells the model to write like a science journalist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Academic&lt;/strong&gt; (1,500 to 2,000 words). Formal. Structured. Abstract up front, methodology section, validation results, related work comparison, citation placeholders in `[Author, Year]` format.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Internal Review&lt;/strong&gt; (1,000 to 1,500 words). This is the honest one. The prompt tells the model to be “candid about challenges and risks” and to include resource analysis with FTE estimates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One Pager&lt;/strong&gt; (under 300 words). Concise to the point of ruthlessness. What it does, who it’s for, key benefits, quick stats, how to get started.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Course Material&lt;/strong&gt; (2,000 to 3,000 words). We added this one not long ago and I’m kind of excited about it. It generates educational content you could hand to someone: learning objectives, a technology deep dive, step-by-step tutorials, three tiers of exercises (beginner, intermediate, advanced), and self-assessment questions. Give it to a workshop organiser and they’ve got a starting point for a full training session.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blog Post&lt;/strong&gt; (800 to 1,200 words). This one was modelled directly on the eScience Center’s own Medium blog. We analysed dozens of our published posts to capture the voice: community-focused, accessible, story-driven with a problem-solution structure. The idea is that a researcher or RSE could generate a first draft and hand it to communications with minimal rework.&lt;/p&gt;
&lt;p&gt;The difference between a good and a mediocre generated story almost never comes down to the model. &lt;strong&gt;It comes down to the prompt.&lt;/strong&gt; Two thousand five hundred words of structured instructions. That’s the actual product. The Gemini API call is almost the easy part.&lt;/p&gt;
&lt;h2 id=&quot;what-this-taught-us-about-llms-as-tools-for-science&quot;&gt;What this taught us about LLMs as tools for science&lt;/h2&gt;
&lt;p&gt;Building and using this tool surfaced a few insights about how LLMs can genuinely serve researchers, rather than just generate noise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nobody needs another text generator.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Researchers need a tool that adapts to the audience and understands the difference between writing for a review committee and writing for the general public. The real value is in the gap between generate some text about this software and generate an internal review with risk assessment and FTE estimates in the right tone, because once you add that kind of specificity to prompts, LLMs stop being gimmicks and start being useful.&lt;/p&gt;
&lt;p&gt;Another big win is generating multiple perspectives on the same project. If you create a communications piece, an academic paper, a review document, a one-pager, a course module, and a blog post from the same source, each lens reveals something different, like overlooked methodological contributions, the true core value in twenty words, what is actually teachable, and how the work connects to the wider research community, so the LLM becomes a thinking tool, not just a writing tool.&lt;/p&gt;
&lt;p&gt;And honestly, context matters more than model sophistication. Running the same prompt on Gemini Flash versus Gemini Pro changes little, but enriching the input with a research proposal, team info, and related software packages changes everything, which suggests institutions will get more value by investing in structured metadata and rich context than by chasing the newest model.&lt;/p&gt;
&lt;h2 id=&quot;llms-as-collaborators-not-replacements&quot;&gt;LLMs as collaborators, not replacements&lt;/h2&gt;
&lt;p&gt;Let me be clear about what this tool does and doesn’t do.&lt;/p&gt;
&lt;p&gt;It doesn’t replace the science communicator who knows that a particular project has a funny origin story, or that the lead developer gave a brilliant conference talk last month, or that “ &lt;em&gt;digital bridges&lt;/em&gt; ” works better for this audience than &lt;em&gt;“computational pipelines.”&lt;/em&gt; Those things require human judgment, institutional memory, and taste. No model provides that.&lt;/p&gt;
&lt;p&gt;That’s the pattern we think works for LLMs in science more broadly. Not autonomous generation. Not replacing experts. Instead: structured tools that handle well-defined tasks with rich context and human oversight. Tools that make researchers more effective at the parts of their job that aren’t their core expertise but still matter, like communicating their work to the people who need to hear about it.&lt;/p&gt;
&lt;p&gt;The conversation about LLMs in research is often framed as a threat. We think it’s more productive to ask: &lt;strong&gt;where can these tools genuinely help, and what does it take to use them responsibly?&lt;/strong&gt; For me, scientific communication turned out to be a great answer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A hundred projects, six audience types, one tool. The stories were always there. We just needed a better way to start telling them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;under-the-bonnet-tech-stack-for-the-curious-ones&quot;&gt;Under the bonnet tech stack (for the curious ones)&lt;/h2&gt;
&lt;p&gt;A few technical choices that I think are interesting, even if they’re invisible to most users:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No backend.&lt;/strong&gt; The Gemini API gets called straight from the browser. No server, no proxy, no infrastructure to babysit. You deploy it as a static site and walk away. The tradeoff? Users bring their own API key, stored in localStorage, never sent anywhere except to Google. For a research-oriented audience that already juggles API keys for half a dozen services, this felt like a reasonable ask.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Svelte 5 runes everywhere&lt;/strong&gt;. The whole app runs on Svelte 5’s new reactivity system: &lt;em&gt;`&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected group as argument to &amp;#x27;\&amp;#x60;&amp;#x27; at end of input: state\&amp;#x60;, \&amp;#x60;&quot; style=&quot;color:#cc0000&quot;&gt;state\`, \`&lt;/span&gt;derived`, `$effect`&lt;/em&gt;. When AI-generated text streams in, only the story display component re-renders. Not the 3D scene. Not the navigation. Not the settings panel. For something that’s running WebGL animations, parsing SSE streams, and managing modal state all at once, that granularity needs to be optional.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scroll velocity drives the 3D&lt;/strong&gt;. This is the detail I’m most proud of. The scroll store doesn’t just track how far down the page you are. It measures how &lt;strong&gt;fast&lt;/strong&gt; you’re scrolling and in which direction. That velocity feeds into the &lt;em&gt;Three.js&lt;/em&gt; scenes. Scroll fast and the camera pulls back, particles scatter wider, everything feels like it’s accelerating with you. Scroll slow and things settle into a gentle rotation. It’s the kind of thing you won’t notice unless you’re looking for it, which is the point. The best interactions are the ones you feel rather than see.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prompt engineering treated as product design.&lt;/strong&gt; I keep coming back to this because I think it’s the least obvious and most important decision we made. The prompt templates weren’t written by a developer in ten minutes. They were iterated on, tested against real projects, revised, tested again. The “Internal Review” template went through five or six drafts before it produced output a programme manager would find useful on a consistent basis. Treating prompts with the same rigour you’d give a product spec? That’s where the real value lives.&lt;/p&gt;
&lt;p&gt;— -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Data Storytelling application is open source at &lt;a href=&quot;https://github.com/NLeSC/data-storytelling&quot;&gt;https://github.com/NLeSC/data-storytelling&lt;/a&gt;. Built at the Netherlands eScience Center, and the Google Gemini API. We’d love to hear how other research organisations approach this challenge. Contributions and conversations welcome.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 26 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Large language models get a lot of attention in research for what they might replace. We wanted to explore what they can enable: better, faster scientific communication that actually reaches the right audiences.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1372&quot; height=&quot;755&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_d1EFyNcb4difLC1_5QkMvg-a2755dce.CIpdYCd3_Z1MrcDA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Welcome page on the storytelling application.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Authors:&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/jesse-gonzalez/&quot;&gt;&lt;em&gt;Jesse González&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/pablo-rodriguez-sanchez/&quot;&gt;&lt;em&gt;Pablo Rodríguez&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/kody-moodley/&quot;&gt;&lt;em&gt;Kody Moodley&lt;/em&gt;&lt;/a&gt;*&lt;br&gt;
Application:* &lt;a href=&quot;https://nlesc.github.io/data-storytelling/&quot;&gt;https://nlesc.github.io/data-storytelling&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There’s an ongoing conversation in the research community about large language models. Most of it focuses on risks: hallucinations, bias, the worry that generated text might replace genuine scholarly work. Those concerns are valid and worth taking seriously.&lt;/p&gt;
&lt;p&gt;But there’s another side to this conversation that doesn’t get enough attention. LLMs can be genuinely useful tools when they’re pointed at the right problems, with the right constraints and the right human oversight. Scientific communication is one of those problems.&lt;/p&gt;
&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we build research software across four scientific domains: &lt;strong&gt;Environment &amp;#x26; Sustainability&lt;/strong&gt;, &lt;strong&gt;Life Sciences&lt;/strong&gt;, &lt;strong&gt;Natural Sciences&lt;/strong&gt; &amp;#x26; &lt;strong&gt;Engineering&lt;/strong&gt; and &lt;strong&gt;Social Sciences &amp;#x26; Humanities&lt;/strong&gt;. This means hundreds of projects, each of them representing months or years of collaborative work with research teams across the country and internationally, all catalogued in the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt;. The software is solid, sometimes groundbreaking. But communicating that work to different audiences (the public, academic peers, funders, workshop participants) takes time that most research teams simply don’t have. There’s a persistent gap between the research software we produce and the stories we tell about it.&lt;/p&gt;
&lt;p&gt;We built a tool to close that gap. And in doing so, we learned some things about what it actually looks like when LLMs serve science instead of the other way around.&lt;/p&gt;
&lt;h2 id=&quot;an-interactive-journey-through-four-research-domains&quot;&gt;An interactive journey through four research domains&lt;/h2&gt;
&lt;p&gt;The first thing you see when you open the &lt;a href=&quot;https://github.com/NLeSC/data-storytelling&quot;&gt;Data Storytelling app&lt;/a&gt; is a 3D particle system. Not a dashboard. Not a table. A cloud of two thousand glowing dots that shift and pulse as you scroll down the page.&lt;/p&gt;
&lt;p&gt;The idea was simple: before you read a single word about a piece of software, you should already have a sense of the research domain it belongs to. Visuals create that context faster than text ever could.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1358&quot; height=&quot;844&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jHWTVqw8VvdPdCDGuCnAZA-1ec471a4.iXSBXRak_2b2YLV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Floating projects retrieved via the Research Software Directory&lt;/p&gt;
&lt;p&gt;The entire application is one long scroll. As you move down, you pass through the domains, each with its own custom 3D scene built in &lt;em&gt;Three.js&lt;/em&gt;. Each 3D scene is peppered with floating cards. Actual projects from the Research Software Directory, fetched live from the API. You hover over one, it glows and scales up. You click it and boom, a modal with the full project details. Description, DOI, metadata, links.&lt;/p&gt;
&lt;p&gt;And tucked inside that modal? A tab labelled “ &lt;strong&gt;Generate Story.&lt;/strong&gt;” That’s where the real magic happens.&lt;/p&gt;
&lt;h2 id=&quot;the-communication-bottleneck-in-research-software&quot;&gt;The communication bottleneck in research software&lt;/h2&gt;
&lt;p&gt;Anyone in research communications will recognise this situation.&lt;/p&gt;
&lt;p&gt;You’ve got a brilliant piece of software. It does something novel with satellite imagery or protein folding or natural language processing for historical Dutch manuscripts. You need to write about it. But write about it for &lt;strong&gt;whom&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;The version for the general public needs to be warm, accessible, maybe open with a compelling question like &lt;em&gt;“What if we could predict floods before they happen?”&lt;/em&gt; The version for an academic journal needs an abstract, proper methodology discussion, and citations formatted just so. The internal review for your board needs FTE estimates, risk assessments, and honest talk about technical debt. And your programme director just wants a one-pager they can scan in three minutes between meetings.&lt;/p&gt;
&lt;p&gt;Same project. Four different pieces of writing. And you need to do this for a hundred projects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is where good research software becomes invisible. Not because the work isn’t worth communicating, but because the communication itself is a bottleneck.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The software ships, the README gets written, maybe a tweet goes out, and that’s it. Months of collaborative work, reduced to a paragraph.&lt;/p&gt;
&lt;p&gt;This is also precisely the kind of problem where LLMs can be a real asset to researchers. Not as a replacement for human judgment, but as a drafting tool that handles the structural heavy lifting: tone calibration, audience adaptation, first-pass content generation. The key is being intentional about how you use them. Not &lt;em&gt;“throw a description at a chatbot and hope for the best”&lt;/em&gt;, but structured, context-rich prompts designed for specific communication goals.&lt;/p&gt;
&lt;h2 id=&quot;generating-stories-feeding-the-model-with-extra-information&quot;&gt;Generating stories feeding the model with extra information&lt;/h2&gt;
&lt;p&gt;The generator pulls related software from the same research domain via the RSD API, without any extra effort from the user. So if you’re generating a story about a climate modelling tool, &lt;strong&gt;it already knows about the other environmental software in the ecosystem and can reference them&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;851&quot; height=&quot;1041&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_w9zVYbuhgtBu_JsNujBL3g-231cdb75.DyuLa9XF_1YkGaM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Project &amp;#x26; Software Information&lt;/p&gt;
&lt;p&gt;You can also upload documents. PDFs, text files, markdown. Research proposals work great for this. The app extracts the text (up to 10,000 characters worth), folds it into the prompt, and the output goes from generic to grounded in specifics.&lt;/p&gt;
&lt;p&gt;For custom projects (things not in the RSD) there’s an “Own Project” button in the top navigation. Pop in a title, description, some reference URLs, upload whatever context you’ve got, pick your audience, and off you go. Same six templates, same quality, no RSD dependency.&lt;/p&gt;
&lt;h2 id=&quot;six-audiences-six-different-stories&quot;&gt;Six audiences, six different stories&lt;/h2&gt;
&lt;p&gt;The story generator ships with six prompt templates. I want to be specific about what these are, because “prompt template” sounds trivial and these are anything but.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1362&quot; height=&quot;1418&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CE8C0Vl-iE0Xjfy3E71HVw-084e4c64.ByNQYqe-_Z1Oa3eq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Generating the story given the selected audience.&lt;/p&gt;
&lt;p&gt;Each one is 500-plus words of careful instructions, closer to a creative brief than a prompt. They specify structure, tone, section order, word count targets, what to emphasise, what to skip. Here’s what each does:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Communications&lt;/strong&gt; (roughly 800 to 1,200 words). Tells the model to write like a science journalist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Academic&lt;/strong&gt; (1,500 to 2,000 words). Formal. Structured. Abstract up front, methodology section, validation results, related work comparison, citation placeholders in `[Author, Year]` format.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Internal Review&lt;/strong&gt; (1,000 to 1,500 words). This is the honest one. The prompt tells the model to be “candid about challenges and risks” and to include resource analysis with FTE estimates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One Pager&lt;/strong&gt; (under 300 words). Concise to the point of ruthlessness. What it does, who it’s for, key benefits, quick stats, how to get started.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Course Material&lt;/strong&gt; (2,000 to 3,000 words). We added this one not long ago and I’m kind of excited about it. It generates educational content you could hand to someone: learning objectives, a technology deep dive, step-by-step tutorials, three tiers of exercises (beginner, intermediate, advanced), and self-assessment questions. Give it to a workshop organiser and they’ve got a starting point for a full training session.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blog Post&lt;/strong&gt; (800 to 1,200 words). This one was modelled directly on the eScience Center’s own Medium blog. We analysed dozens of our published posts to capture the voice: community-focused, accessible, story-driven with a problem-solution structure. The idea is that a researcher or RSE could generate a first draft and hand it to communications with minimal rework.&lt;/p&gt;
&lt;p&gt;The difference between a good and a mediocre generated story almost never comes down to the model. &lt;strong&gt;It comes down to the prompt.&lt;/strong&gt; Two thousand five hundred words of structured instructions. That’s the actual product. The Gemini API call is almost the easy part.&lt;/p&gt;
&lt;h2 id=&quot;what-this-taught-us-about-llms-as-tools-for-science&quot;&gt;What this taught us about LLMs as tools for science&lt;/h2&gt;
&lt;p&gt;Building and using this tool surfaced a few insights about how LLMs can genuinely serve researchers, rather than just generate noise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nobody needs another text generator.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Researchers need a tool that adapts to the audience and understands the difference between writing for a review committee and writing for the general public. The real value is in the gap between generate some text about this software and generate an internal review with risk assessment and FTE estimates in the right tone, because once you add that kind of specificity to prompts, LLMs stop being gimmicks and start being useful.&lt;/p&gt;
&lt;p&gt;Another big win is generating multiple perspectives on the same project. If you create a communications piece, an academic paper, a review document, a one-pager, a course module, and a blog post from the same source, each lens reveals something different, like overlooked methodological contributions, the true core value in twenty words, what is actually teachable, and how the work connects to the wider research community, so the LLM becomes a thinking tool, not just a writing tool.&lt;/p&gt;
&lt;p&gt;And honestly, context matters more than model sophistication. Running the same prompt on Gemini Flash versus Gemini Pro changes little, but enriching the input with a research proposal, team info, and related software packages changes everything, which suggests institutions will get more value by investing in structured metadata and rich context than by chasing the newest model.&lt;/p&gt;
&lt;h2 id=&quot;llms-as-collaborators-not-replacements&quot;&gt;LLMs as collaborators, not replacements&lt;/h2&gt;
&lt;p&gt;Let me be clear about what this tool does and doesn’t do.&lt;/p&gt;
&lt;p&gt;It doesn’t replace the science communicator who knows that a particular project has a funny origin story, or that the lead developer gave a brilliant conference talk last month, or that “ &lt;em&gt;digital bridges&lt;/em&gt; ” works better for this audience than &lt;em&gt;“computational pipelines.”&lt;/em&gt; Those things require human judgment, institutional memory, and taste. No model provides that.&lt;/p&gt;
&lt;p&gt;That’s the pattern we think works for LLMs in science more broadly. Not autonomous generation. Not replacing experts. Instead: structured tools that handle well-defined tasks with rich context and human oversight. Tools that make researchers more effective at the parts of their job that aren’t their core expertise but still matter, like communicating their work to the people who need to hear about it.&lt;/p&gt;
&lt;p&gt;The conversation about LLMs in research is often framed as a threat. We think it’s more productive to ask: &lt;strong&gt;where can these tools genuinely help, and what does it take to use them responsibly?&lt;/strong&gt; For me, scientific communication turned out to be a great answer.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A hundred projects, six audience types, one tool. The stories were always there. We just needed a better way to start telling them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;under-the-bonnet-tech-stack-for-the-curious-ones&quot;&gt;Under the bonnet tech stack (for the curious ones)&lt;/h2&gt;
&lt;p&gt;A few technical choices that I think are interesting, even if they’re invisible to most users:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No backend.&lt;/strong&gt; The Gemini API gets called straight from the browser. No server, no proxy, no infrastructure to babysit. You deploy it as a static site and walk away. The tradeoff? Users bring their own API key, stored in localStorage, never sent anywhere except to Google. For a research-oriented audience that already juggles API keys for half a dozen services, this felt like a reasonable ask.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Svelte 5 runes everywhere&lt;/strong&gt;. The whole app runs on Svelte 5’s new reactivity system: &lt;em&gt;`&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected group as argument to &amp;#x27;\&amp;#x60;&amp;#x27; at end of input: state\&amp;#x60;, \&amp;#x60;&quot; style=&quot;color:#cc0000&quot;&gt;state\`, \`&lt;/span&gt;derived`, `$effect`&lt;/em&gt;. When AI-generated text streams in, only the story display component re-renders. Not the 3D scene. Not the navigation. Not the settings panel. For something that’s running WebGL animations, parsing SSE streams, and managing modal state all at once, that granularity needs to be optional.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scroll velocity drives the 3D&lt;/strong&gt;. This is the detail I’m most proud of. The scroll store doesn’t just track how far down the page you are. It measures how &lt;strong&gt;fast&lt;/strong&gt; you’re scrolling and in which direction. That velocity feeds into the &lt;em&gt;Three.js&lt;/em&gt; scenes. Scroll fast and the camera pulls back, particles scatter wider, everything feels like it’s accelerating with you. Scroll slow and things settle into a gentle rotation. It’s the kind of thing you won’t notice unless you’re looking for it, which is the point. The best interactions are the ones you feel rather than see.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prompt engineering treated as product design.&lt;/strong&gt; I keep coming back to this because I think it’s the least obvious and most important decision we made. The prompt templates weren’t written by a developer in ten minutes. They were iterated on, tested against real projects, revised, tested again. The “Internal Review” template went through five or six drafts before it produced output a programme manager would find useful on a consistent basis. Treating prompts with the same rigour you’d give a product spec? That’s where the real value lives.&lt;/p&gt;
&lt;p&gt;— -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Data Storytelling application is open source at &lt;a href=&quot;https://github.com/NLeSC/data-storytelling&quot;&gt;https://github.com/NLeSC/data-storytelling&lt;/a&gt;. Built at the Netherlands eScience Center, and the Google Gemini API. We’d love to hear how other research organisations approach this challenge. Contributions and conversations welcome.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_jHWTVqw8VvdPdCDGuCnAZA-1ec471a4.iXSBXRak.gif" medium="image"/><author>Jesse Gonzalez</author></item><item><title>Enabling best practices for sustainable software in the Natural &amp;amp; Engineering sciences (SS-NES)</title><link>https://blog2.esciencecenter.nl/posts/2026-02-11---enabling-best-practices-for-sustainable-software-in-the-natu</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-02-11---enabling-best-practices-for-sustainable-software-in-the-natu</guid><description>&lt;h1 id=&quot;enabling-best-practices-for-sustainable-software-in-the-natural--engineering-sciences-ss-nes&quot;&gt;&lt;strong&gt;Enabling best practices for sustainable software in the Natural &amp;#x26; Engineering sciences (SS-NES)&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Authors: Roel Janssen, Jason Maassen and Carlos Martinez-Ortiz&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With the available constellation of data and code repositories, it can be hard to choose the best way of making your research code and data available. Here we present an automated way of synchronizing &lt;em&gt;&lt;a href=&quot;https://community.data.4tu.nl/&quot;&gt;&lt;em&gt;4TU.ResearchData&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; with the &lt;em&gt;&lt;a href=&quot;https://research-software-directory.org/&quot;&gt;&lt;em&gt;Research Software Directory&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Enabling best practices for sustainable software in the Natural &amp;amp;#x26; Engineering sciences (SS-NES)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;329&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--312dc003.C2NZAdf8_1g5qpn.webp&quot; srcset=&quot;&quot;&gt;
4TU.ResearchData is a data and software repository for science, engineering and design domains, as well as support services and a vibrant community around them. The Research Software Directory is an open-source project initiated by the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and jointly developed with &lt;a href=&quot;https://www.helmholtz.de/&quot;&gt;Helmholtz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As part of the project &lt;a href=&quot;https://ss-nes.github.io/&quot;&gt;Enabling best practices for sustainable software in the Natural &amp;#x26; Engineering sciences (**&lt;/a&gt;**SS-NES) **the 4TU.ResearchData’s data repository and eScience Center’s Research Software Directory (RSD) collaborated to ensure software published in 4TU.ResearchData is also made available in the Research Software Directory.&lt;/p&gt;
&lt;p&gt;To achieve this goal, 4TU.ResearchData adapted its metadata intake and implemented API endpoints following the &lt;a href=&quot;https://codemeta.github.io/&quot;&gt;CodeMeta&lt;/a&gt; standard. Additionally, 4TU.ResearchData implemented API endpoints to communicate statistics on Git repositories following existing Github and Gitlab practices.&lt;/p&gt;
&lt;p&gt;The RSD implemented a harvester for 4TU.ResearchData which uses the CodeMeta metadata standard and a Communities feature to group software from a particular source.&lt;/p&gt;
&lt;h2 id=&quot;adding-to-the-research-software-landscape&quot;&gt;Adding to the research software landscape&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Enabling best practices for sustainable software in the Natural &amp;amp;#x26; Engineering sciences (SS-NES)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;408&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--2404cfd2.B3rnVSTT_Z1C7idO.webp&quot; srcset=&quot;&quot;&gt;
When creating software as part of your research activities, it is advisable to use a version control system like Git to manage the evolution of the software. At some point, the software needs to be shared with other researchers, either to reuse or extend it, or to validate the research results. Publishing the software provides the benefits of having a URL to cite as well as having a guarantee that the source code of the software is stored at a persistent location for the long term. These benefits are provided by 4TU.ResearchData.&lt;/p&gt;
&lt;p&gt;To publish the software in 4TU.ResearchData from Gitlab, Github or Codeberg, one can use Git’s “remotes” concept to push a copy to 4TU.ResearchData while retaining the active development on the hub.&lt;/p&gt;
&lt;p&gt;Fun fact**: Due to the collaboration between the eScienceCenter’s RSD and 4TU.ResearchData, the latter added the “Git repository name” and “Code hosting project URL” metadata fields so that they can be used and passed along to the RSD.&lt;/p&gt;
&lt;p&gt;We chose this approach because it works regardless of whether the repository is public or private, and regardless of the implementation of the hosting platform. We support Github, Gitlab, Codeberg, Savannah, or any other Git-based platform. Additionally, when dealing with private Git repositories, no systematic integration or information exposure is needed.&lt;/p&gt;
&lt;h2 id=&quot;finding-and-showcasing-software-in-the-research-software-landscape&quot;&gt;Finding and showcasing software in the research software landscape&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Enabling best practices for sustainable software in the Natural &amp;amp;#x26; Engineering sciences (SS-NES)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;643&quot; height=&quot;359&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--4f34d759.DxzODF57_Z10Rf5t.webp&quot; srcset=&quot;&quot;&gt;
Once the software is published on 4TU.ResearchData, it is automatically picked up by the RSD and added to the 4TU Community collection. The RSD uses the information recorded in 4TU.ResearchData to generate a unique software page designed to highlight the impact of the software.&lt;/p&gt;
&lt;p&gt;Next to showing basic static information about the software such as a short description, author list, keywords, and links to the source code, the RSD also enriches the software page with information harvested from other data sources in the open science and open-source ecosystem. Examples include information on software development activity, citation information for the different software releases, and a list of papers citing the software.&lt;/p&gt;
&lt;h2 id=&quot;concluding-words&quot;&gt;Concluding words&lt;/h2&gt;
&lt;p&gt;Publishing your software on a trusted repository is one of the good practices advocated by the SS-NES project and the eScience Center. With the integration between 4TU.ResearchData and the RSD, researchers automatically benefit from the findability and exposability of the RSD when they publish their software in 4TU.ResearchData. The RSD has become a more complete source of mapping the research software landscape by automatically harvesting 4TU.ResearchData’s software publications.&lt;/p&gt;</description><pubDate>Wed, 11 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;enabling-best-practices-for-sustainable-software-in-the-natural--engineering-sciences-ss-nes&quot;&gt;&lt;strong&gt;Enabling best practices for sustainable software in the Natural &amp;#x26; Engineering sciences (SS-NES)&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Authors: Roel Janssen, Jason Maassen and Carlos Martinez-Ortiz&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With the available constellation of data and code repositories, it can be hard to choose the best way of making your research code and data available. Here we present an automated way of synchronizing &lt;em&gt;&lt;a href=&quot;https://community.data.4tu.nl/&quot;&gt;&lt;em&gt;4TU.ResearchData&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; with the &lt;em&gt;&lt;a href=&quot;https://research-software-directory.org/&quot;&gt;&lt;em&gt;Research Software Directory&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Enabling best practices for sustainable software in the Natural &amp;amp;#x26; Engineering sciences (SS-NES)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;329&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--312dc003.C2NZAdf8_1g5qpn.webp&quot; srcset=&quot;&quot;&gt;
4TU.ResearchData is a data and software repository for science, engineering and design domains, as well as support services and a vibrant community around them. The Research Software Directory is an open-source project initiated by the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and jointly developed with &lt;a href=&quot;https://www.helmholtz.de/&quot;&gt;Helmholtz&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As part of the project &lt;a href=&quot;https://ss-nes.github.io/&quot;&gt;Enabling best practices for sustainable software in the Natural &amp;#x26; Engineering sciences (**&lt;/a&gt;**SS-NES) **the 4TU.ResearchData’s data repository and eScience Center’s Research Software Directory (RSD) collaborated to ensure software published in 4TU.ResearchData is also made available in the Research Software Directory.&lt;/p&gt;
&lt;p&gt;To achieve this goal, 4TU.ResearchData adapted its metadata intake and implemented API endpoints following the &lt;a href=&quot;https://codemeta.github.io/&quot;&gt;CodeMeta&lt;/a&gt; standard. Additionally, 4TU.ResearchData implemented API endpoints to communicate statistics on Git repositories following existing Github and Gitlab practices.&lt;/p&gt;
&lt;p&gt;The RSD implemented a harvester for 4TU.ResearchData which uses the CodeMeta metadata standard and a Communities feature to group software from a particular source.&lt;/p&gt;
&lt;h2 id=&quot;adding-to-the-research-software-landscape&quot;&gt;Adding to the research software landscape&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Enabling best practices for sustainable software in the Natural &amp;amp;#x26; Engineering sciences (SS-NES)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;408&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--2404cfd2.B3rnVSTT_Z1C7idO.webp&quot; srcset=&quot;&quot;&gt;
When creating software as part of your research activities, it is advisable to use a version control system like Git to manage the evolution of the software. At some point, the software needs to be shared with other researchers, either to reuse or extend it, or to validate the research results. Publishing the software provides the benefits of having a URL to cite as well as having a guarantee that the source code of the software is stored at a persistent location for the long term. These benefits are provided by 4TU.ResearchData.&lt;/p&gt;
&lt;p&gt;To publish the software in 4TU.ResearchData from Gitlab, Github or Codeberg, one can use Git’s “remotes” concept to push a copy to 4TU.ResearchData while retaining the active development on the hub.&lt;/p&gt;
&lt;p&gt;Fun fact**: Due to the collaboration between the eScienceCenter’s RSD and 4TU.ResearchData, the latter added the “Git repository name” and “Code hosting project URL” metadata fields so that they can be used and passed along to the RSD.&lt;/p&gt;
&lt;p&gt;We chose this approach because it works regardless of whether the repository is public or private, and regardless of the implementation of the hosting platform. We support Github, Gitlab, Codeberg, Savannah, or any other Git-based platform. Additionally, when dealing with private Git repositories, no systematic integration or information exposure is needed.&lt;/p&gt;
&lt;h2 id=&quot;finding-and-showcasing-software-in-the-research-software-landscape&quot;&gt;Finding and showcasing software in the research software landscape&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Enabling best practices for sustainable software in the Natural &amp;amp;#x26; Engineering sciences (SS-NES)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;643&quot; height=&quot;359&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--4f34d759.DxzODF57_Z10Rf5t.webp&quot; srcset=&quot;&quot;&gt;
Once the software is published on 4TU.ResearchData, it is automatically picked up by the RSD and added to the 4TU Community collection. The RSD uses the information recorded in 4TU.ResearchData to generate a unique software page designed to highlight the impact of the software.&lt;/p&gt;
&lt;p&gt;Next to showing basic static information about the software such as a short description, author list, keywords, and links to the source code, the RSD also enriches the software page with information harvested from other data sources in the open science and open-source ecosystem. Examples include information on software development activity, citation information for the different software releases, and a list of papers citing the software.&lt;/p&gt;
&lt;h2 id=&quot;concluding-words&quot;&gt;Concluding words&lt;/h2&gt;
&lt;p&gt;Publishing your software on a trusted repository is one of the good practices advocated by the SS-NES project and the eScience Center. With the integration between 4TU.ResearchData and the RSD, researchers automatically benefit from the findability and exposability of the RSD when they publish their software in 4TU.ResearchData. The RSD has become a more complete source of mapping the research software landscape by automatically harvesting 4TU.ResearchData’s software publications.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/enabling-best-practices-for-sustainable--312dc003.C2NZAdf8.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Use Julia to write code that runs on any GPU</title><link>https://blog2.esciencecenter.nl/posts/2026-01-15---use-julia-to-write-code-that-runs-on-any-gpu</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2026-01-15---use-julia-to-write-code-that-runs-on-any-gpu</guid><description>&lt;h1 id=&quot;use-julia-to-write-code-that-runs-on-any-gpu&quot;&gt;Use Julia to write code that runs on &lt;em&gt;any&lt;/em&gt; GPU&lt;/h1&gt;
&lt;p&gt;10&lt;/p&gt;
&lt;p&gt;&lt;em&gt;How to write Julia code than can run on any GPU, and why you would want to do that.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As the name implies, the main use of Graphics Processing Units is to process and render things to your screen, such as images, videos, or video games. Almost any device that has a display will have a GPU, although this can also come in the form of a chip integrated in the CPU instead of a separate graphics card. When using applications such as Google Maps, YouTube, or Netflix, the GPU renders the image/video to the screen more quickly and efficiently compared to the CPU. This can result in lower power consumption and a better user experience.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Use Julia to write code that runs on any GPU&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/use-julia-to-write-code-that-runs-on-any-f2817526.BrL0gaPi_1SLleG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@synesthe2ia?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Dimitris Chapsoulas&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To be able to render things to screen quickly, GPUs are able to do a lot of computations in parallel. Besides just graphics rendering, doing many computations in parallel can also come in use elsewhere, such as in (scientific) numerical models, and especially relevant recently, machine learning.&lt;/p&gt;
&lt;p&gt;Before the release of Nvidia’s CUDA platform in 2007, people would use routines designed for graphics processing (like &lt;a href=&quot;https://en.wikipedia.org/wiki/Shader&quot;&gt;shaders&lt;/a&gt;), for non-graphics purposes &lt;a href=&quot;https://doi.org/10.1145/882262.882363&quot;&gt;such as numerical solvers for the Navier-Stokes equations&lt;/a&gt;. However, with CUDA, and soon after also OpenCL, it became more straightforward to write General Purpose GPU code.&lt;/p&gt;
&lt;p&gt;When writing code for CUDA, you are locked into Nvidia designed GPUs, and the code cannot run elsewhere. With OpenCL, it &lt;em&gt;was&lt;/em&gt; possible to write GPU code that can run on many platforms. While it can still work well on most hardware, it is seeing less and less support from Apple and Nvidia, who prefer to push their own proprietary platforms (Metal and CUDA).&lt;/p&gt;
&lt;p&gt;Writing generic GPU code has a few benefits however, as you are not tied to a certain vendor, and there is a larger possible user base and thus more use cases. For example; accelerating a scientific model with GPU impacts both for laptop and high performance computing users.&lt;/p&gt;
&lt;p&gt;To continue writing GPU code that can run on any hardware you can make use of &lt;a href=&quot;https://juliagpu.org&quot;&gt;Julia’s GPU ecosystem&lt;/a&gt;. With the &lt;a href=&quot;https://juliagpu.github.io/KernelAbstractions.jl&quot;&gt;KernelAbstractions.jl&lt;/a&gt; package you can write a kernel (a function that runs on a GPU and executes in parallel) that will work on any of the supported backends. Currently supported are Nvidia’s CUDA, AMD’s ROCm, Apple Metal, and Intel oneAPI. Which means that nearly all modern GPUs are supported, ranging from small laptops to supercomputers.&lt;/p&gt;
&lt;h2 id=&quot;julia-example&quot;&gt;Julia example&lt;/h2&gt;
&lt;p&gt;To get started, after installing Julia, you can initialize arrays on the GPU with the appropriate backend package. As an example, I will use oneAPI, but the code will look the same for the other backends. The following line is the only one that’s machine dependent:&lt;/p&gt;
&lt;p&gt;import oneAPI.oneArray as GPUArrayHaving imported this, we can define arrays on the GPU. In this case a 2D matrix containing single-precision floating point numbers:&lt;/p&gt;
&lt;p&gt;A = GPUArray(ones(Float32, 1024, 1024))Now we can write a kernel. This example comes from the &lt;a href=&quot;https://juliagpu.github.io/KernelAbstractions.jl/stable/quickstart/&quot;&gt;KernelAbstractions documentation&lt;/a&gt;, and will simply multiply every element of the matrix by 2:&lt;/p&gt;
&lt;p&gt;using KernelAbstractions&lt;/p&gt;
&lt;p&gt;@kernel function mul2_kernel(A)
I = @index(Global)
A[I] = 2 * A[I]
endWe can apply the kernel to the matrix &lt;code&gt;A&lt;/code&gt; :&lt;/p&gt;
&lt;p&gt;backend = get_backend(A)
mul2_kernel(backend, 64)(A, ndrange=size(A))And that’s it! — &lt;em&gt;Note that &lt;em&gt;&lt;code&gt;64&lt;/code&gt;&lt;/em&gt; is the “workgroup size”, i.e., the number of the array elements assigned to one work group. Tuning this parameter can make the kernel run faster.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;import AcceleratedKernels as AK&lt;/p&gt;
&lt;p&gt;function cpu_copy!(dst, src)
for i in eachindex(src)
dst[i] = src[i]
end
end&lt;/p&gt;
&lt;p&gt;function gpu_copy!(dst, src)
AK.foreachindex(src) do i
dst[i] = src[i]
end
endThe &lt;code&gt;gpu_copy&lt;/code&gt; function will run on GPU if &lt;code&gt;dst&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; are GPU arrays. Otherwise the function will run on CPU.&lt;/p&gt;
&lt;h2 id=&quot;example-packages&quot;&gt;Example packages&lt;/h2&gt;
&lt;p&gt;There are already some great packages that use KernelAbstractions to run on both CPU and any GPU. One of these is &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0010465525002504&quot;&gt;WaterLily.jl&lt;/a&gt;, a Computational Fluid Dynamics solver. Because it uses KernelAbstractions, they were able to run simulations not only on Nvidia GPUs, but also on AMD GPUs available on the &lt;a href=&quot;https://www.surf.nl/en/services/compute/lumi&quot;&gt;LUMI supercomputer&lt;/a&gt; (one of the fastest in Europe!).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Use Julia to write code that runs on any GPU&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;490&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/use-julia-to-write-code-that-runs-on-any-6be9197d.C_s27B6T_19MMwC.webp&quot; srcset=&quot;&quot;&gt;
Simple 2D flow around the Julia logo, simulated using &lt;a href=&quot;https://github.com/WaterLily-jl/WaterLily.jl&quot;&gt;WaterLily.jl&lt;/a&gt; (source: WaterLily.jl)The animation above can be generated on a laptop using the CPU or integrated graphics, but can be easily adapted to a higher resolution or 3D simulation to be run on a supercomputer.&lt;/p&gt;
&lt;p&gt;The Julia GPU &lt;a href=&quot;https://juliagpu.org/showcases/&quot;&gt;showcase page&lt;/a&gt; has many more examples ranging from climate models to bioinformatics.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By using Julia’s generic GPU framework, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;run and debug code locally, on your laptop using your CPU or GPU&lt;/li&gt;
&lt;li&gt;have a larger community of users who can run the code on their own devices&lt;/li&gt;
&lt;li&gt;deploy the code on any supercomputer, e.g., both Snellius (Nvidia GPUs) and LUMI (AMD GPUs)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So next time you need code to be fast and portable, consider using Julia to write code that can run fast, anywhere.&lt;/p&gt;</description><pubDate>Thu, 15 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;use-julia-to-write-code-that-runs-on-any-gpu&quot;&gt;Use Julia to write code that runs on &lt;em&gt;any&lt;/em&gt; GPU&lt;/h1&gt;
&lt;p&gt;10&lt;/p&gt;
&lt;p&gt;&lt;em&gt;How to write Julia code than can run on any GPU, and why you would want to do that.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As the name implies, the main use of Graphics Processing Units is to process and render things to your screen, such as images, videos, or video games. Almost any device that has a display will have a GPU, although this can also come in the form of a chip integrated in the CPU instead of a separate graphics card. When using applications such as Google Maps, YouTube, or Netflix, the GPU renders the image/video to the screen more quickly and efficiently compared to the CPU. This can result in lower power consumption and a better user experience.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Use Julia to write code that runs on any GPU&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/use-julia-to-write-code-that-runs-on-any-f2817526.BrL0gaPi_1SLleG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@synesthe2ia?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Dimitris Chapsoulas&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To be able to render things to screen quickly, GPUs are able to do a lot of computations in parallel. Besides just graphics rendering, doing many computations in parallel can also come in use elsewhere, such as in (scientific) numerical models, and especially relevant recently, machine learning.&lt;/p&gt;
&lt;p&gt;Before the release of Nvidia’s CUDA platform in 2007, people would use routines designed for graphics processing (like &lt;a href=&quot;https://en.wikipedia.org/wiki/Shader&quot;&gt;shaders&lt;/a&gt;), for non-graphics purposes &lt;a href=&quot;https://doi.org/10.1145/882262.882363&quot;&gt;such as numerical solvers for the Navier-Stokes equations&lt;/a&gt;. However, with CUDA, and soon after also OpenCL, it became more straightforward to write General Purpose GPU code.&lt;/p&gt;
&lt;p&gt;When writing code for CUDA, you are locked into Nvidia designed GPUs, and the code cannot run elsewhere. With OpenCL, it &lt;em&gt;was&lt;/em&gt; possible to write GPU code that can run on many platforms. While it can still work well on most hardware, it is seeing less and less support from Apple and Nvidia, who prefer to push their own proprietary platforms (Metal and CUDA).&lt;/p&gt;
&lt;p&gt;Writing generic GPU code has a few benefits however, as you are not tied to a certain vendor, and there is a larger possible user base and thus more use cases. For example; accelerating a scientific model with GPU impacts both for laptop and high performance computing users.&lt;/p&gt;
&lt;p&gt;To continue writing GPU code that can run on any hardware you can make use of &lt;a href=&quot;https://juliagpu.org&quot;&gt;Julia’s GPU ecosystem&lt;/a&gt;. With the &lt;a href=&quot;https://juliagpu.github.io/KernelAbstractions.jl&quot;&gt;KernelAbstractions.jl&lt;/a&gt; package you can write a kernel (a function that runs on a GPU and executes in parallel) that will work on any of the supported backends. Currently supported are Nvidia’s CUDA, AMD’s ROCm, Apple Metal, and Intel oneAPI. Which means that nearly all modern GPUs are supported, ranging from small laptops to supercomputers.&lt;/p&gt;
&lt;h2 id=&quot;julia-example&quot;&gt;Julia example&lt;/h2&gt;
&lt;p&gt;To get started, after installing Julia, you can initialize arrays on the GPU with the appropriate backend package. As an example, I will use oneAPI, but the code will look the same for the other backends. The following line is the only one that’s machine dependent:&lt;/p&gt;
&lt;p&gt;import oneAPI.oneArray as GPUArrayHaving imported this, we can define arrays on the GPU. In this case a 2D matrix containing single-precision floating point numbers:&lt;/p&gt;
&lt;p&gt;A = GPUArray(ones(Float32, 1024, 1024))Now we can write a kernel. This example comes from the &lt;a href=&quot;https://juliagpu.github.io/KernelAbstractions.jl/stable/quickstart/&quot;&gt;KernelAbstractions documentation&lt;/a&gt;, and will simply multiply every element of the matrix by 2:&lt;/p&gt;
&lt;p&gt;using KernelAbstractions&lt;/p&gt;
&lt;p&gt;@kernel function mul2_kernel(A)
I = @index(Global)
A[I] = 2 * A[I]
endWe can apply the kernel to the matrix &lt;code&gt;A&lt;/code&gt; :&lt;/p&gt;
&lt;p&gt;backend = get_backend(A)
mul2_kernel(backend, 64)(A, ndrange=size(A))And that’s it! — &lt;em&gt;Note that &lt;em&gt;&lt;code&gt;64&lt;/code&gt;&lt;/em&gt; is the “workgroup size”, i.e., the number of the array elements assigned to one work group. Tuning this parameter can make the kernel run faster.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;import AcceleratedKernels as AK&lt;/p&gt;
&lt;p&gt;function cpu_copy!(dst, src)
for i in eachindex(src)
dst[i] = src[i]
end
end&lt;/p&gt;
&lt;p&gt;function gpu_copy!(dst, src)
AK.foreachindex(src) do i
dst[i] = src[i]
end
endThe &lt;code&gt;gpu_copy&lt;/code&gt; function will run on GPU if &lt;code&gt;dst&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt; are GPU arrays. Otherwise the function will run on CPU.&lt;/p&gt;
&lt;h2 id=&quot;example-packages&quot;&gt;Example packages&lt;/h2&gt;
&lt;p&gt;There are already some great packages that use KernelAbstractions to run on both CPU and any GPU. One of these is &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0010465525002504&quot;&gt;WaterLily.jl&lt;/a&gt;, a Computational Fluid Dynamics solver. Because it uses KernelAbstractions, they were able to run simulations not only on Nvidia GPUs, but also on AMD GPUs available on the &lt;a href=&quot;https://www.surf.nl/en/services/compute/lumi&quot;&gt;LUMI supercomputer&lt;/a&gt; (one of the fastest in Europe!).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Use Julia to write code that runs on any GPU&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;490&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/use-julia-to-write-code-that-runs-on-any-6be9197d.C_s27B6T_19MMwC.webp&quot; srcset=&quot;&quot;&gt;
Simple 2D flow around the Julia logo, simulated using &lt;a href=&quot;https://github.com/WaterLily-jl/WaterLily.jl&quot;&gt;WaterLily.jl&lt;/a&gt; (source: WaterLily.jl)The animation above can be generated on a laptop using the CPU or integrated graphics, but can be easily adapted to a higher resolution or 3D simulation to be run on a supercomputer.&lt;/p&gt;
&lt;p&gt;The Julia GPU &lt;a href=&quot;https://juliagpu.org/showcases/&quot;&gt;showcase page&lt;/a&gt; has many more examples ranging from climate models to bioinformatics.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By using Julia’s generic GPU framework, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;run and debug code locally, on your laptop using your CPU or GPU&lt;/li&gt;
&lt;li&gt;have a larger community of users who can run the code on their own devices&lt;/li&gt;
&lt;li&gt;deploy the code on any supercomputer, e.g., both Snellius (Nvidia GPUs) and LUMI (AMD GPUs)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So next time you need code to be fast and portable, consider using Julia to write code that can run fast, anywhere.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/use-julia-to-write-code-that-runs-on-any-f2817526.BrL0gaPi.jpg" medium="image"/><author>Bart Schilperoort</author></item><item><title>Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup</title><link>https://blog2.esciencecenter.nl/posts/2025-12-09---strengthening-research-software-management-in-dutch-umcs-hig</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-12-09---strengthening-research-software-management-in-dutch-umcs-hig</guid><description>&lt;h1 id=&quot;strengthening-research-software-management-in-dutch-umcs-highlights-from-the-second-dreams-community-meetup&quot;&gt;&lt;strong&gt;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Written by Anna Niehues, Özgün Balaban, Magnus Palmblad, Mariia Steeghs-Turchina, and the DReaMS Community&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dreams-community.github.io/about/&quot;&gt;DReaMS&lt;/a&gt; is a collaborative community formed by Digital Competence Centers (DCCs) from Dutch University Medical Centers (UMCs), committed to advancing research software management (RSM). During the LUMC Research Data Day on 23 September 2025, network members came together in Leiden for the second community meetup. The event aimed to align practices and foster collaboration across institutions, building on the momentum of the first meetup in 2024 (&lt;a href=&quot;https://blog2.esciencecenter.nl/how-is-research-software-managed-at-umcs-insights-from-a-first-meetup-4181e9626a60&quot;&gt;Pronk 2024&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;565&quot; height=&quot;313&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-3878cbea.CcpX6cFs_Z1FbAdX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Research Software includes source code files, algorithms, scripts, computational workflows and executables that were created during the research process or for a research purpose” &lt;em&gt;(&lt;/em&gt;&lt;a href=&quot;https://doi.org/10.5281/zenodo.5504016&quot;&gt;&lt;em&gt;Gruenpeter et al. 2021&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For Dutch UMCs, effectively managing research software is essential to ensuring reproducibility, efficiency, and reuse, while supporting compliance with Open Science policies and regulatory requirements.&lt;/p&gt;
&lt;h2 id=&quot;opening-session&quot;&gt;Opening Session&lt;/h2&gt;
&lt;p&gt;The opening session, co-chaired by Anna Niehues and Thomas Pronk, featured updates shared by participants, setting the stage for a day of engaging discussions and knowledge exchange. The meetup provided a valuable opportunity for the participating UMCs and national infrastructure partners — the Netherlands eScience Center and ELIXIR-NL — to connect, share updates, and explore key topics. The discussions focused on developing RSM guidelines, strategies for software sustainability, providing training, and identifying connection points to strengthen joint efforts.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;533&quot; height=&quot;256&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-0e793bd0.Cs3AvKJY_2f6Ib0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;towards-research-software-management-guidelines-for-dutch-umcs&quot;&gt;Towards Research Software Management Guidelines for Dutch UMCs&lt;/h2&gt;
&lt;p&gt;During the session on Research Software Management Guidelines, co-chaired by Mariia Steeghs-Turchina and Carlos Martinez, participants identified common questions that researchers have, mapped available support, and identified gaps across Dutch UMCs. We explored what researchers need most, how institutions respond, and where key gaps remain.&lt;/p&gt;
&lt;p&gt;Researchers regularly seek support on version control, Git or GitHub usage, and software maintenance. This indicates growing awareness but also uncertainty about best practices. In the absence of clear guidelines, RSM support staff often direct researchers to online tutorials, the&lt;a href=&quot;https://software-carpentry.org/&quot;&gt; Software Carpentry&lt;/a&gt; programme, the&lt;a href=&quot;https://everse.software/RSQKit/&quot;&gt; Research Software Quality Toolkit for Sciences (RSQkit)&lt;/a&gt; and institutional Git courses, as well as AI-powered coding assistants. These dispersed resources may be difficult to navigate and a shared resource hub connecting training and guiding materials could provide added value to researchers. Better recognition mechanisms, such as software citation, are also needed to incentivise the following best practices.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;343&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-cb0ad5db.CLv39PIQ_nnUCP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-sustainability-long-term-maintenance-and-reusability&quot;&gt;Research Software Sustainability: Long-term Maintenance and Reusability&lt;/h2&gt;
&lt;p&gt;During the breakout session on research software sustainability, which was co-chaired by Magnus Palmblad and Sietse Rispens, the challenges of maintaining software, especially when the original developer is no longer available, were discussed. Possible internal and external solutions were also explored.&lt;/p&gt;
&lt;p&gt;A critical phase occurs between the realisation that a particular piece of software has wider applicability and the developer’s departure, often after completing their studies or postdoctoral research. During this period, it is important to plan for sustainability as early as possible, with a focus on documenting the code, creating software metadata and involving more people in the development process.&lt;/p&gt;
&lt;p&gt;Good habits, such as writing code that is both readable and well-documented, encourages others to contribute to the codebase and help to sustain it. Students are often highly motivated to write software from scratch. While this is an important experience, students making significant contributions by adding novel functionality to existing projects should be rewarded equally. This requires a change in culture, away from “yet another tool to do X” to having more people contribute to community-supported open science projects. Training on how to use Git or how to contribute to community projects is essential. Journal editors should be encouraged to consider such contributions as potentially equally novel and useful as stand-alone software.&lt;/p&gt;
&lt;h2 id=&quot;research-software-training-through-the-lens-of-fair-and-open-science&quot;&gt;Research Software Training Through the Lens of FAIR and Open Science&lt;/h2&gt;
&lt;p&gt;While the first DReaMS meetup in 2024 identified a lack of intermediate-level training as a key challenge, this year’s breakout session on software training, co-chaired by Özgün Balaban and Bauke van der Velde, uncovered gaps in fundamental research software training.&lt;/p&gt;
&lt;p&gt;It is often challenging to identify suitable communication channels through which to raise awareness among new PhD students and researchers of research software practices and available training and resources. While some topics, such as Git, which also have a high popularity, are covered repeatedly by training programmes, others are underrepresented. These include, e.g., conceptual-level training for beginners, good coding practices, software management, documentation, and AI-supported development. A lack of balanced training coverage also poses a risk to the sustainability of research software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-f500b663.BJT5BEe7_Zgh0Fk.webp&quot; srcset=&quot;&quot;&gt;
The activities identified as being effective in increasing awareness include Coding CAFEs (&lt;a href=&quot;https://code-cafes-nl.github.io/cafe_playbook/&quot;&gt;Moopen et al. 2023&lt;/a&gt;), mentorship programmes, peer learning, peer reviews of software documentation, and guest lectures. Such formats do not only build practical skills, but also strengthen communities.&lt;/p&gt;
&lt;p&gt;Suggested collaboration opportunities include sharing course materials across institutions, setting up trainer communication channels, such as&lt;a href=&quot;https://researchsoftwaretraining.nl/&quot;&gt; RST-NL&lt;/a&gt;, and offering joint workshops. The next steps will be discussed during upcoming online meetings of the DReaMS community.&lt;/p&gt;
&lt;p&gt;A common challenge in the current training landscape and in the sustainability of research software is that initiatives are fragmented, resulting in uneven coverage across the software development lifecycle. A more coherent approach is required to address this, involving clear policies, long-term planning, secure funding and a sufficient workforce aligned with institutional project needs.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-the-dreams-community&quot;&gt;Get in Touch With the DReaMS Community&lt;/h2&gt;
&lt;p&gt;Take a look at our &lt;a href=&quot;https://dreams-community.github.io/&quot;&gt;website&lt;/a&gt; and get in touch with us via the community members.&lt;/p&gt;
&lt;p&gt;This blog is cross-posted here: &lt;a href=&quot;https://dreams-community.github.io/blog/second-meetup/&quot;&gt;https://dreams-community.github.io/blog/second-meetup/&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;strengthening-research-software-management-in-dutch-umcs-highlights-from-the-second-dreams-community-meetup&quot;&gt;&lt;strong&gt;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Written by Anna Niehues, Özgün Balaban, Magnus Palmblad, Mariia Steeghs-Turchina, and the DReaMS Community&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dreams-community.github.io/about/&quot;&gt;DReaMS&lt;/a&gt; is a collaborative community formed by Digital Competence Centers (DCCs) from Dutch University Medical Centers (UMCs), committed to advancing research software management (RSM). During the LUMC Research Data Day on 23 September 2025, network members came together in Leiden for the second community meetup. The event aimed to align practices and foster collaboration across institutions, building on the momentum of the first meetup in 2024 (&lt;a href=&quot;https://blog2.esciencecenter.nl/how-is-research-software-managed-at-umcs-insights-from-a-first-meetup-4181e9626a60&quot;&gt;Pronk 2024&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;565&quot; height=&quot;313&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-3878cbea.CcpX6cFs_Z1FbAdX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Research Software includes source code files, algorithms, scripts, computational workflows and executables that were created during the research process or for a research purpose” &lt;em&gt;(&lt;/em&gt;&lt;a href=&quot;https://doi.org/10.5281/zenodo.5504016&quot;&gt;&lt;em&gt;Gruenpeter et al. 2021&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For Dutch UMCs, effectively managing research software is essential to ensuring reproducibility, efficiency, and reuse, while supporting compliance with Open Science policies and regulatory requirements.&lt;/p&gt;
&lt;h2 id=&quot;opening-session&quot;&gt;Opening Session&lt;/h2&gt;
&lt;p&gt;The opening session, co-chaired by Anna Niehues and Thomas Pronk, featured updates shared by participants, setting the stage for a day of engaging discussions and knowledge exchange. The meetup provided a valuable opportunity for the participating UMCs and national infrastructure partners — the Netherlands eScience Center and ELIXIR-NL — to connect, share updates, and explore key topics. The discussions focused on developing RSM guidelines, strategies for software sustainability, providing training, and identifying connection points to strengthen joint efforts.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;533&quot; height=&quot;256&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-0e793bd0.Cs3AvKJY_2f6Ib0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;towards-research-software-management-guidelines-for-dutch-umcs&quot;&gt;Towards Research Software Management Guidelines for Dutch UMCs&lt;/h2&gt;
&lt;p&gt;During the session on Research Software Management Guidelines, co-chaired by Mariia Steeghs-Turchina and Carlos Martinez, participants identified common questions that researchers have, mapped available support, and identified gaps across Dutch UMCs. We explored what researchers need most, how institutions respond, and where key gaps remain.&lt;/p&gt;
&lt;p&gt;Researchers regularly seek support on version control, Git or GitHub usage, and software maintenance. This indicates growing awareness but also uncertainty about best practices. In the absence of clear guidelines, RSM support staff often direct researchers to online tutorials, the&lt;a href=&quot;https://software-carpentry.org/&quot;&gt; Software Carpentry&lt;/a&gt; programme, the&lt;a href=&quot;https://everse.software/RSQKit/&quot;&gt; Research Software Quality Toolkit for Sciences (RSQkit)&lt;/a&gt; and institutional Git courses, as well as AI-powered coding assistants. These dispersed resources may be difficult to navigate and a shared resource hub connecting training and guiding materials could provide added value to researchers. Better recognition mechanisms, such as software citation, are also needed to incentivise the following best practices.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;343&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-cb0ad5db.CLv39PIQ_nnUCP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-sustainability-long-term-maintenance-and-reusability&quot;&gt;Research Software Sustainability: Long-term Maintenance and Reusability&lt;/h2&gt;
&lt;p&gt;During the breakout session on research software sustainability, which was co-chaired by Magnus Palmblad and Sietse Rispens, the challenges of maintaining software, especially when the original developer is no longer available, were discussed. Possible internal and external solutions were also explored.&lt;/p&gt;
&lt;p&gt;A critical phase occurs between the realisation that a particular piece of software has wider applicability and the developer’s departure, often after completing their studies or postdoctoral research. During this period, it is important to plan for sustainability as early as possible, with a focus on documenting the code, creating software metadata and involving more people in the development process.&lt;/p&gt;
&lt;p&gt;Good habits, such as writing code that is both readable and well-documented, encourages others to contribute to the codebase and help to sustain it. Students are often highly motivated to write software from scratch. While this is an important experience, students making significant contributions by adding novel functionality to existing projects should be rewarded equally. This requires a change in culture, away from “yet another tool to do X” to having more people contribute to community-supported open science projects. Training on how to use Git or how to contribute to community projects is essential. Journal editors should be encouraged to consider such contributions as potentially equally novel and useful as stand-alone software.&lt;/p&gt;
&lt;h2 id=&quot;research-software-training-through-the-lens-of-fair-and-open-science&quot;&gt;Research Software Training Through the Lens of FAIR and Open Science&lt;/h2&gt;
&lt;p&gt;While the first DReaMS meetup in 2024 identified a lack of intermediate-level training as a key challenge, this year’s breakout session on software training, co-chaired by Özgün Balaban and Bauke van der Velde, uncovered gaps in fundamental research software training.&lt;/p&gt;
&lt;p&gt;It is often challenging to identify suitable communication channels through which to raise awareness among new PhD students and researchers of research software practices and available training and resources. While some topics, such as Git, which also have a high popularity, are covered repeatedly by training programmes, others are underrepresented. These include, e.g., conceptual-level training for beginners, good coding practices, software management, documentation, and AI-supported development. A lack of balanced training coverage also poses a risk to the sustainability of research software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Strengthening Research Software Management in Dutch UMCs: Highlights from the Second DReaMS Community Meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-f500b663.BJT5BEe7_Zgh0Fk.webp&quot; srcset=&quot;&quot;&gt;
The activities identified as being effective in increasing awareness include Coding CAFEs (&lt;a href=&quot;https://code-cafes-nl.github.io/cafe_playbook/&quot;&gt;Moopen et al. 2023&lt;/a&gt;), mentorship programmes, peer learning, peer reviews of software documentation, and guest lectures. Such formats do not only build practical skills, but also strengthen communities.&lt;/p&gt;
&lt;p&gt;Suggested collaboration opportunities include sharing course materials across institutions, setting up trainer communication channels, such as&lt;a href=&quot;https://researchsoftwaretraining.nl/&quot;&gt; RST-NL&lt;/a&gt;, and offering joint workshops. The next steps will be discussed during upcoming online meetings of the DReaMS community.&lt;/p&gt;
&lt;p&gt;A common challenge in the current training landscape and in the sustainability of research software is that initiatives are fragmented, resulting in uneven coverage across the software development lifecycle. A more coherent approach is required to address this, involving clear policies, long-term planning, secure funding and a sufficient workforce aligned with institutional project needs.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-the-dreams-community&quot;&gt;Get in Touch With the DReaMS Community&lt;/h2&gt;
&lt;p&gt;Take a look at our &lt;a href=&quot;https://dreams-community.github.io/&quot;&gt;website&lt;/a&gt; and get in touch with us via the community members.&lt;/p&gt;
&lt;p&gt;This blog is cross-posted here: &lt;a href=&quot;https://dreams-community.github.io/blog/second-meetup/&quot;&gt;https://dreams-community.github.io/blog/second-meetup/&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/strengthening-research-software-manageme-3878cbea.CcpX6cFs.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>A special gift (December 5th)</title><link>https://blog2.esciencecenter.nl/posts/2025-12-05---a-special-gift-december-5th</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-12-05---a-special-gift-december-5th</guid><description>&lt;h2 id=&quot;ode-to-the-research-software-engineer&quot;&gt;Ode to the research software engineer&lt;/h2&gt;
&lt;p&gt;8&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sinterklaas is a Dutch tradition featuring Saint Nicholas, who is said to arrive from Spain with his helpers and travel across rooftops to deliver small gifts and poems. Today, the Sint is visiting the eScience Center.&lt;/p&gt;
&lt;p&gt;As days are getting colder and the nights becoming long,
we make our office cozy with hot chocolate and song.
The fireplace is lit albeit on the conference screen;
it is an office atmosphere unlike you’ve ever seen.&lt;/p&gt;
&lt;p&gt;We sit together ‘round the fire and wait for what’s to come,
when suddenly we hear a heavy beating, like a drum.
We chase towards the office entrance seeing who is there,
but nothing’s to be seen except a letter near the stairs.&lt;/p&gt;
&lt;p&gt;The letter reads “My dearest friends and fellow RSEs,
please go back to your conference room and make yourself at ease.
You’ve made me feel so welcome and I brought you in return
a bundle of delights for you to live and love and learn.”&lt;/p&gt;
&lt;p&gt;Curious we sat once more around the makeshift fire,
stunned to find some gifts that any scientist should desire.
A bag full of best practices to make your software shine,
sparked with digital literacy and beautiful design.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A special gift (December 5th)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-special-gift-december-5th-d7100f1d.BgmdqWgn_21oTQh.webp&quot; srcset=&quot;&quot;&gt;
Chocolate letters are part of the traditionTo start it off we first unpacked a gift so smart and bright:
a coffee mug for every soul who codes late in the night.
On it was a text that read “your 9 to 5 is fine,
but if you rather work at night, some caffeine’s divine”.&lt;/p&gt;
&lt;p&gt;The next gift comes in handy for a project big or small
a touch of git to help you keep your code under control.
A branching scheme, a tidy diff, a history clear and clean
A present many researchers admit they’ve never seen.&lt;/p&gt;
&lt;p&gt;Then slips beneath the office door a test suite neatly wrapped,
with unit tests and fixtures all meticulously mapped.
“Oh generous Sint,” we all proclaim, “now bugs no more appear!”
(Though secretly he knows they will, but less, and less severe.)&lt;/p&gt;
&lt;p&gt;A handbook tied with twine he leaves, with pretty illustrations
on licenses and versioning and good documentation.
For knowledge lost is hard to find when months have come and gone,
but with this helpful guide the happy coding can go on.&lt;/p&gt;
&lt;p&gt;Sint conjures CI pipelines high above us in the cloud,
where automated checks and builds assemble clean and proud
A magical parade of green ticks marching in a row,
the sweetest sight for anyone who’s watched code fail to grow.&lt;/p&gt;
&lt;p&gt;But most of all, the Sint bestows a gift both rare and dear:
the quiet craft, the steady hand, the engineer’s career.
For research needs more than ideas just drifting in the air;
it needs the ones who shape the tools that make discovery FAIR.&lt;/p&gt;
&lt;p&gt;So here’s an ode to those who bridge two worlds with practiced grace:
who think in algorithms yet they keep the human pace.
Who build, maintain, refactor, teach, who safeguard truth with care,
the research software engineers, the heroes unaware.&lt;/p&gt;
&lt;p&gt;And as the Sint sails home again across December seas,
he leaves one final message carried softly by the breeze:
“Good science thrives when code is sound, transparent, shared, and clear,
so honour those who make it so; support them through the year.”&lt;/p&gt;
&lt;p&gt;This poem has been crafted in collaboration with AI-Piet*&lt;/p&gt;</description><pubDate>Fri, 05 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;ode-to-the-research-software-engineer&quot;&gt;Ode to the research software engineer&lt;/h2&gt;
&lt;p&gt;8&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sinterklaas is a Dutch tradition featuring Saint Nicholas, who is said to arrive from Spain with his helpers and travel across rooftops to deliver small gifts and poems. Today, the Sint is visiting the eScience Center.&lt;/p&gt;
&lt;p&gt;As days are getting colder and the nights becoming long,
we make our office cozy with hot chocolate and song.
The fireplace is lit albeit on the conference screen;
it is an office atmosphere unlike you’ve ever seen.&lt;/p&gt;
&lt;p&gt;We sit together ‘round the fire and wait for what’s to come,
when suddenly we hear a heavy beating, like a drum.
We chase towards the office entrance seeing who is there,
but nothing’s to be seen except a letter near the stairs.&lt;/p&gt;
&lt;p&gt;The letter reads “My dearest friends and fellow RSEs,
please go back to your conference room and make yourself at ease.
You’ve made me feel so welcome and I brought you in return
a bundle of delights for you to live and love and learn.”&lt;/p&gt;
&lt;p&gt;Curious we sat once more around the makeshift fire,
stunned to find some gifts that any scientist should desire.
A bag full of best practices to make your software shine,
sparked with digital literacy and beautiful design.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A special gift (December 5th)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-special-gift-december-5th-d7100f1d.BgmdqWgn_21oTQh.webp&quot; srcset=&quot;&quot;&gt;
Chocolate letters are part of the traditionTo start it off we first unpacked a gift so smart and bright:
a coffee mug for every soul who codes late in the night.
On it was a text that read “your 9 to 5 is fine,
but if you rather work at night, some caffeine’s divine”.&lt;/p&gt;
&lt;p&gt;The next gift comes in handy for a project big or small
a touch of git to help you keep your code under control.
A branching scheme, a tidy diff, a history clear and clean
A present many researchers admit they’ve never seen.&lt;/p&gt;
&lt;p&gt;Then slips beneath the office door a test suite neatly wrapped,
with unit tests and fixtures all meticulously mapped.
“Oh generous Sint,” we all proclaim, “now bugs no more appear!”
(Though secretly he knows they will, but less, and less severe.)&lt;/p&gt;
&lt;p&gt;A handbook tied with twine he leaves, with pretty illustrations
on licenses and versioning and good documentation.
For knowledge lost is hard to find when months have come and gone,
but with this helpful guide the happy coding can go on.&lt;/p&gt;
&lt;p&gt;Sint conjures CI pipelines high above us in the cloud,
where automated checks and builds assemble clean and proud
A magical parade of green ticks marching in a row,
the sweetest sight for anyone who’s watched code fail to grow.&lt;/p&gt;
&lt;p&gt;But most of all, the Sint bestows a gift both rare and dear:
the quiet craft, the steady hand, the engineer’s career.
For research needs more than ideas just drifting in the air;
it needs the ones who shape the tools that make discovery FAIR.&lt;/p&gt;
&lt;p&gt;So here’s an ode to those who bridge two worlds with practiced grace:
who think in algorithms yet they keep the human pace.
Who build, maintain, refactor, teach, who safeguard truth with care,
the research software engineers, the heroes unaware.&lt;/p&gt;
&lt;p&gt;And as the Sint sails home again across December seas,
he leaves one final message carried softly by the breeze:
“Good science thrives when code is sound, transparent, shared, and clear,
so honour those who make it so; support them through the year.”&lt;/p&gt;
&lt;p&gt;This poem has been crafted in collaboration with AI-Piet*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/a-special-gift-december-5th-d7100f1d.BgmdqWgn.jpeg" medium="image"/><author>Peter Kalverla</author></item><item><title>The story map</title><link>https://blog2.esciencecenter.nl/posts/2025-11-26---the-story-map</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-11-26---the-story-map</guid><description>&lt;p&gt;A framework for story-building&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-2090d51d.29pOVV-H_Z1ciFKC.webp&quot; srcset=&quot;&quot;&gt;
We are all natural-born storytellers. Or at the very least, storylisteners. The same drive lies behind a gathering around the fireplace, a night at the movies or listening to a podcast on your morning run: our brain’s hunger for narratives.&lt;/p&gt;
&lt;p&gt;Our brains are literally wired for storytelling, and yet creating a story can be challenging.&lt;/p&gt;
&lt;p&gt;This tutorial presents a strategy for simplifying the creative process of building a story. And as in any good story, we have to start from the beginning.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-story&quot;&gt;What is a story?&lt;/h2&gt;
&lt;p&gt;If you ever experienced the so-called &lt;em&gt;“blank page syndrome”&lt;/em&gt;, chances are that it originated not from a lack of ideas to write about, but from an overwhelming, chaotic pile of them.&lt;/p&gt;
&lt;p&gt;A story, any story, is linear. It doesn’t matter if it is a text, a speech, a movie or even a scientific publication: it will progress from a beginning to an end.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;More specifically, any story will be &lt;strong&gt;consumed&lt;/strong&gt;&lt;/em&gt;* on a linear way. Even a story which content is structured in a non-chronological order has a beginning and an end.*&lt;/p&gt;
&lt;p&gt;And here comes the challenge: our thoughts are rarely that linear. Most people entertain multiple thoughts simultaneously, or quickly switch from one to the other. It takes a conscious effort to order them into a coherent narrative.&lt;/p&gt;
&lt;h2 id=&quot;embracing-chaos&quot;&gt;Embracing chaos&lt;/h2&gt;
&lt;p&gt;Instead of getting frustrated about the chaotic nature of our thoughts, let’s just embrace it. Our thoughts are fine just how they are.&lt;/p&gt;
&lt;p&gt;Of course, it is not that practical to have our working memory juggling them all at once. So let’s free our memory and outsource them to… a piece of paper! Just write them down.&lt;/p&gt;
&lt;p&gt;My advice is to do it like in the figure below, in small squares, with no pre-defined order. Just drop them around as if they were LEGO bricks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-4c4616af.DDI9Un7Q_1n2PSp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;structuring-your-thoughts-the-building-blocks&quot;&gt;Structuring your thoughts: the building blocks&lt;/h2&gt;
&lt;p&gt;The challenge is set! Our goal is to build something with these bricks. But first we have to see our bricks, identify them, make sure we’re not missing any. Almost &lt;em&gt;feel&lt;/em&gt; them.&lt;/p&gt;
&lt;p&gt;Take a moment to look at your building blocks. Very likely, you’ll notice some of them are related. This relationship can be logical, narrative, chronological, … Draw a line between them if that’s the case.&lt;/p&gt;
&lt;p&gt;I suggest using &lt;strong&gt;solid lines for strong relatedness&lt;/strong&gt;, and &lt;strong&gt;dashed lines for less clear relatedness&lt;/strong&gt;. We are starting to have &lt;strong&gt;some&lt;/strong&gt; structure! We are slowly creating order out of chaos!¹&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-2090d51d.29pOVV-H_Z1ciFKC.webp&quot; srcset=&quot;&quot;&gt;
At this stage, you might realize some building blocks are missing. When that’s the case, just add them. You might also notice some building blocks are redundant. Well, just merge those together. You might even judge some of the blocks to be unnecessary. Drop those without hesitation! Nothing creates more order out of chaos than reducing the amount of moving parts!&lt;/p&gt;
&lt;h2 id=&quot;navigating-your-thoughts-the-story-map&quot;&gt;Navigating your thoughts: the story map&lt;/h2&gt;
&lt;p&gt;The ultimate goal would be to navigate your thoughts. And I don’t use the verb navigate lightly: you literally want to create a route from the beginning to the end. The diagram above will be very useful for achieving this.&lt;/p&gt;
&lt;p&gt;To begin with, the diagram shows clearly what the core topics are. This allows for drawing a first, straightforward route that covers just the basics. If your audience is already knowledgeable about the topic and your time is limited, this route is an excellent choice:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-07f540b2.6KPo7hGG_2bI9Do.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For many people, especially in academia, skipping information feels wrong. In the verge of immoral.*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;What we did above is tailoring your materials to our audience (sounds better than skipping, doesn’t it?). And yes, we did it by eliminating some of them. Actually, this is going to happen often, and it is very good news. Less complexity, less moving parts; less is more, remember?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Effective communication is not about turning everything that we write or say into a self-contained compendium, but about providing chunks that can be reasonably digested in whatever context they are delivered.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If your time is less limited, you can consider taking a detour and dropping an anecdote to make the experience more enjoyable:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-d2a0192d.DrWYqMrK_ZvO4Ro.webp&quot; srcset=&quot;&quot;&gt;
Last but not least, if you have the possibility of expanding as much as you want, you might want to cover all the topics. In such a case, a reasonable route will look like:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-363e168b.B9ZQjHOK_oudXO.webp&quot; srcset=&quot;&quot;&gt;
In the figure below we summarize three possible routes we could envision for the same material:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-60695bb7.DPKFnKkk_Z1KjG0F.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;applications&quot;&gt;Applications&lt;/h2&gt;
&lt;p&gt;I’ve used the described framework in many settings where storytelling played a role. Perhaps this sounds limited, but believe me: storytelling is everywhere. I used it for, among others:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scientific presentations&lt;/li&gt;
&lt;li&gt;Comedy monologues&lt;/li&gt;
&lt;li&gt;Software tutorials&lt;/li&gt;
&lt;li&gt;My own PhD dissertation&lt;/li&gt;
&lt;li&gt;Blog posts&lt;/li&gt;
&lt;li&gt;A strategic plan for a research institution&lt;/li&gt;
&lt;li&gt;Publications in research journals (real-life example &lt;a href=&quot;https://fuga.naukas.com/files/2021/03/IMG_20190301_091759-768x404.jpg&quot;&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A theater play&lt;/li&gt;
&lt;li&gt;And also for this text you are reading now&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I honestly encourage you to give it a try next time you face a blank page. It works wonders!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;This piece was born in the context of the &lt;a href=&quot;https://research-software-directory.org/projects/data-storytelling&quot;&gt;Data Storytelling project&lt;/a&gt;. Thanks to &lt;a href=&quot;https://www.esciencecenter.nl/team/jesse-gonzalez/&quot;&gt;Jesse González&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/kody-moodley/&quot;&gt;Kody Moodley&lt;/a&gt; for their feedback.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For those of you interested in knowledge management, chances are this method will remind you of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Zettelkasten&quot;&gt;Zettelkasten note-taking method&lt;/a&gt;, a strong, even more structured form of the ideas presented here. Also, you’d be interested in knowing that some software applications, such as &lt;a href=&quot;https://logseq.com/&quot;&gt;logseq&lt;/a&gt; or &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt;, are designed with this model in mind.↩&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A framework for story-building&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-2090d51d.29pOVV-H_Z1ciFKC.webp&quot; srcset=&quot;&quot;&gt;
We are all natural-born storytellers. Or at the very least, storylisteners. The same drive lies behind a gathering around the fireplace, a night at the movies or listening to a podcast on your morning run: our brain’s hunger for narratives.&lt;/p&gt;
&lt;p&gt;Our brains are literally wired for storytelling, and yet creating a story can be challenging.&lt;/p&gt;
&lt;p&gt;This tutorial presents a strategy for simplifying the creative process of building a story. And as in any good story, we have to start from the beginning.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-story&quot;&gt;What is a story?&lt;/h2&gt;
&lt;p&gt;If you ever experienced the so-called &lt;em&gt;“blank page syndrome”&lt;/em&gt;, chances are that it originated not from a lack of ideas to write about, but from an overwhelming, chaotic pile of them.&lt;/p&gt;
&lt;p&gt;A story, any story, is linear. It doesn’t matter if it is a text, a speech, a movie or even a scientific publication: it will progress from a beginning to an end.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;More specifically, any story will be &lt;strong&gt;consumed&lt;/strong&gt;&lt;/em&gt;* on a linear way. Even a story which content is structured in a non-chronological order has a beginning and an end.*&lt;/p&gt;
&lt;p&gt;And here comes the challenge: our thoughts are rarely that linear. Most people entertain multiple thoughts simultaneously, or quickly switch from one to the other. It takes a conscious effort to order them into a coherent narrative.&lt;/p&gt;
&lt;h2 id=&quot;embracing-chaos&quot;&gt;Embracing chaos&lt;/h2&gt;
&lt;p&gt;Instead of getting frustrated about the chaotic nature of our thoughts, let’s just embrace it. Our thoughts are fine just how they are.&lt;/p&gt;
&lt;p&gt;Of course, it is not that practical to have our working memory juggling them all at once. So let’s free our memory and outsource them to… a piece of paper! Just write them down.&lt;/p&gt;
&lt;p&gt;My advice is to do it like in the figure below, in small squares, with no pre-defined order. Just drop them around as if they were LEGO bricks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-4c4616af.DDI9Un7Q_1n2PSp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;structuring-your-thoughts-the-building-blocks&quot;&gt;Structuring your thoughts: the building blocks&lt;/h2&gt;
&lt;p&gt;The challenge is set! Our goal is to build something with these bricks. But first we have to see our bricks, identify them, make sure we’re not missing any. Almost &lt;em&gt;feel&lt;/em&gt; them.&lt;/p&gt;
&lt;p&gt;Take a moment to look at your building blocks. Very likely, you’ll notice some of them are related. This relationship can be logical, narrative, chronological, … Draw a line between them if that’s the case.&lt;/p&gt;
&lt;p&gt;I suggest using &lt;strong&gt;solid lines for strong relatedness&lt;/strong&gt;, and &lt;strong&gt;dashed lines for less clear relatedness&lt;/strong&gt;. We are starting to have &lt;strong&gt;some&lt;/strong&gt; structure! We are slowly creating order out of chaos!¹&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-2090d51d.29pOVV-H_Z1ciFKC.webp&quot; srcset=&quot;&quot;&gt;
At this stage, you might realize some building blocks are missing. When that’s the case, just add them. You might also notice some building blocks are redundant. Well, just merge those together. You might even judge some of the blocks to be unnecessary. Drop those without hesitation! Nothing creates more order out of chaos than reducing the amount of moving parts!&lt;/p&gt;
&lt;h2 id=&quot;navigating-your-thoughts-the-story-map&quot;&gt;Navigating your thoughts: the story map&lt;/h2&gt;
&lt;p&gt;The ultimate goal would be to navigate your thoughts. And I don’t use the verb navigate lightly: you literally want to create a route from the beginning to the end. The diagram above will be very useful for achieving this.&lt;/p&gt;
&lt;p&gt;To begin with, the diagram shows clearly what the core topics are. This allows for drawing a first, straightforward route that covers just the basics. If your audience is already knowledgeable about the topic and your time is limited, this route is an excellent choice:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-07f540b2.6KPo7hGG_2bI9Do.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For many people, especially in academia, skipping information feels wrong. In the verge of immoral.*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;What we did above is tailoring your materials to our audience (sounds better than skipping, doesn’t it?). And yes, we did it by eliminating some of them. Actually, this is going to happen often, and it is very good news. Less complexity, less moving parts; less is more, remember?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Effective communication is not about turning everything that we write or say into a self-contained compendium, but about providing chunks that can be reasonably digested in whatever context they are delivered.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If your time is less limited, you can consider taking a detour and dropping an anecdote to make the experience more enjoyable:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-d2a0192d.DrWYqMrK_ZvO4Ro.webp&quot; srcset=&quot;&quot;&gt;
Last but not least, if you have the possibility of expanding as much as you want, you might want to cover all the topics. In such a case, a reasonable route will look like:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-363e168b.B9ZQjHOK_oudXO.webp&quot; srcset=&quot;&quot;&gt;
In the figure below we summarize three possible routes we could envision for the same material:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The story map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;507&quot; height=&quot;411&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-story-map-60695bb7.DPKFnKkk_Z1KjG0F.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;applications&quot;&gt;Applications&lt;/h2&gt;
&lt;p&gt;I’ve used the described framework in many settings where storytelling played a role. Perhaps this sounds limited, but believe me: storytelling is everywhere. I used it for, among others:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scientific presentations&lt;/li&gt;
&lt;li&gt;Comedy monologues&lt;/li&gt;
&lt;li&gt;Software tutorials&lt;/li&gt;
&lt;li&gt;My own PhD dissertation&lt;/li&gt;
&lt;li&gt;Blog posts&lt;/li&gt;
&lt;li&gt;A strategic plan for a research institution&lt;/li&gt;
&lt;li&gt;Publications in research journals (real-life example &lt;a href=&quot;https://fuga.naukas.com/files/2021/03/IMG_20190301_091759-768x404.jpg&quot;&gt;here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A theater play&lt;/li&gt;
&lt;li&gt;And also for this text you are reading now&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I honestly encourage you to give it a try next time you face a blank page. It works wonders!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;This piece was born in the context of the &lt;a href=&quot;https://research-software-directory.org/projects/data-storytelling&quot;&gt;Data Storytelling project&lt;/a&gt;. Thanks to &lt;a href=&quot;https://www.esciencecenter.nl/team/jesse-gonzalez/&quot;&gt;Jesse González&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/kody-moodley/&quot;&gt;Kody Moodley&lt;/a&gt; for their feedback.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For those of you interested in knowledge management, chances are this method will remind you of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Zettelkasten&quot;&gt;Zettelkasten note-taking method&lt;/a&gt;, a strong, even more structured form of the ideas presented here. Also, you’d be interested in knowing that some software applications, such as &lt;a href=&quot;https://logseq.com/&quot;&gt;logseq&lt;/a&gt; or &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt;, are designed with this model in mind.↩&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/the-story-map-4c4616af.DDI9Un7Q.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.</title><link>https://blog2.esciencecenter.nl/posts/2025-11-06---from-phd-student-to-auto-tuning-gpu-expert-meet-floris-jan</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-11-06---from-phd-student-to-auto-tuning-gpu-expert-meet-floris-jan</guid><description>&lt;p&gt;Floris-Jan Willemsen has been a PhD student at the Netherlands eScience Center since 2021, working on auto-tuning GPU software as part of the &lt;a href=&quot;https://research-software-directory.org/projects/cortex&quot;&gt;CORTEX&lt;/a&gt; project under the supervision of Rob van Nieuwpoort (Professor in Computer Science at Leiden University) and Ben van Werkhoven (Assistant Professor at Leiden University and former Research Software Engineer at the eScience Center).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;222&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-e9522c8e.C_BHgcx8_uedXd.webp&quot; srcset=&quot;&quot;&gt;
Why auto-tune GPUs?**&lt;/p&gt;
&lt;p&gt;“My research focuses on auto-tuning: creating software and algorithms to optimize performance on hardware. Smarter and faster auto-tuning not only leads to quicker results but also consumes less energy, making it a more sustainable option. We did this within the context of a project where we, together with other institutes like ASTRON, want to investigate the ‘explosive universe’. To observe the universe at that scale means a lot of data, which requires big computers, but even that is not enough — we need to be smart about what data we focus on and how we process it. That requires auto-tuning, which essentially is like a panel of many different knobs and sliders, with only one combination of millions leading to optimal performance. Therefore, we first focused on creating an algorithm that was able to find those combinations in very few attempts.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-3fb6b98d.CN7VbsN6_1VIvDz.webp&quot; srcset=&quot;&quot;&gt;
Van Leeuwen/ASTRON (bron: NOS Nieuws)&lt;strong&gt;What were some challenges you experienced?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“This part of the project was itself a challenge, but the difficulty didn’t end when it was finished. The next step was to develop a uniform methodology. Each research group working with auto-tuning has a different way of visualizing and comparing data, as well as of reporting results. In 2022, we organized a Lorentz workshop to compare all these different methodologies and to design a new, uniform one. The major win was receiving the community’s mandate to spearhead this new methodology, which allows everyone to fairly compare auto-tuning performance — a significant breakthrough.&lt;/p&gt;
&lt;p&gt;After this, I removed a major bottleneck in the auto-tuning process. This, together with other important advances, ultimately allowed me to optimize the optimization algorithms themselves — ‘tuning the tuner’ if you will.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who can use this tool?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;311&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-5a2375db.BVyIPWij_1wazqK.webp&quot; srcset=&quot;&quot;&gt;
ESiWACE3What was special about doing your PhD at the Netherlands eScience Center?**&lt;/p&gt;
&lt;p&gt;“It allowed us to design tools that simply didn’t exist before. Building on the expertise of the Research Software Engineers at the Netherlands eScience Center, we were able to build high-quality software that is both at the cutting edge of research as well as user-friendly and stable. This is a combination that is rarely seen and allows us to put what we research today in the hands of scientists and developers tomorrow. Another perk was the focus on meeting with user bases through tutorials at a variety of international conferences like SuperComputing. At such conferences, we taught them new ways to get the most out of their hardware from us and we learned how users interacted with our software and how we could improve it further.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are your plans for the near future?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“I’m starting a new position as a Postdoctoral researcher at the Leiden Institute of Advanced Computer Science (LIACS) at Leiden University, where I’ll continue to build on the research I did during my Ph.D. and explore exciting new directions for auto-tuning. I’m looking forward to leveraging the experience I gained in building high-quality software in all future projects!”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What made working at the eScience Center a unique experience?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“The priority at universities is to always get the research done first, which tends to lead to software that gets the job done but is not accessible, maintainable, or usable outside of the exact scope of the research. The eScience Center has the combination of people experienced in both the academic and the software side of things, which puts it at a unique intersection to create sustainable scientific software. What I created during my time at the eScience Center is not limited to one specific purpose and can immediately be deployed in other people’s research. I’m proud to have been able to make an impact in that way.”&lt;/p&gt;
&lt;p&gt;Read the article the NOS wrote about the &lt;em&gt;&lt;a href=&quot;https://nos.nl/artikel/2552914-astronomen-westerbork-ontrafelen-lichtflits-mysterie-in-de-ruimte&quot;&gt;&lt;em&gt;CORTEX Project&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (link in Dutch) in January 2025.*&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who are we?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center is a research organization dedicated to applying research software to answer research questions in any scientific domain through project collaborations. It has the largest concentration of dedicated, high-level research software expertise in the Netherlands. The eScience Center also has a &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;fellowship programme&lt;/a&gt; and makes all of its software and training materials openly available online. For more information about what we offer, visit &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 06 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Floris-Jan Willemsen has been a PhD student at the Netherlands eScience Center since 2021, working on auto-tuning GPU software as part of the &lt;a href=&quot;https://research-software-directory.org/projects/cortex&quot;&gt;CORTEX&lt;/a&gt; project under the supervision of Rob van Nieuwpoort (Professor in Computer Science at Leiden University) and Ben van Werkhoven (Assistant Professor at Leiden University and former Research Software Engineer at the eScience Center).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;222&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-e9522c8e.C_BHgcx8_uedXd.webp&quot; srcset=&quot;&quot;&gt;
Why auto-tune GPUs?**&lt;/p&gt;
&lt;p&gt;“My research focuses on auto-tuning: creating software and algorithms to optimize performance on hardware. Smarter and faster auto-tuning not only leads to quicker results but also consumes less energy, making it a more sustainable option. We did this within the context of a project where we, together with other institutes like ASTRON, want to investigate the ‘explosive universe’. To observe the universe at that scale means a lot of data, which requires big computers, but even that is not enough — we need to be smart about what data we focus on and how we process it. That requires auto-tuning, which essentially is like a panel of many different knobs and sliders, with only one combination of millions leading to optimal performance. Therefore, we first focused on creating an algorithm that was able to find those combinations in very few attempts.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-3fb6b98d.CN7VbsN6_1VIvDz.webp&quot; srcset=&quot;&quot;&gt;
Van Leeuwen/ASTRON (bron: NOS Nieuws)&lt;strong&gt;What were some challenges you experienced?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“This part of the project was itself a challenge, but the difficulty didn’t end when it was finished. The next step was to develop a uniform methodology. Each research group working with auto-tuning has a different way of visualizing and comparing data, as well as of reporting results. In 2022, we organized a Lorentz workshop to compare all these different methodologies and to design a new, uniform one. The major win was receiving the community’s mandate to spearhead this new methodology, which allows everyone to fairly compare auto-tuning performance — a significant breakthrough.&lt;/p&gt;
&lt;p&gt;After this, I removed a major bottleneck in the auto-tuning process. This, together with other important advances, ultimately allowed me to optimize the optimization algorithms themselves — ‘tuning the tuner’ if you will.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who can use this tool?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From PhD Student to Auto-Tuning GPU Expert. Meet Floris-Jan.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;311&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-5a2375db.BVyIPWij_1wazqK.webp&quot; srcset=&quot;&quot;&gt;
ESiWACE3What was special about doing your PhD at the Netherlands eScience Center?**&lt;/p&gt;
&lt;p&gt;“It allowed us to design tools that simply didn’t exist before. Building on the expertise of the Research Software Engineers at the Netherlands eScience Center, we were able to build high-quality software that is both at the cutting edge of research as well as user-friendly and stable. This is a combination that is rarely seen and allows us to put what we research today in the hands of scientists and developers tomorrow. Another perk was the focus on meeting with user bases through tutorials at a variety of international conferences like SuperComputing. At such conferences, we taught them new ways to get the most out of their hardware from us and we learned how users interacted with our software and how we could improve it further.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are your plans for the near future?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“I’m starting a new position as a Postdoctoral researcher at the Leiden Institute of Advanced Computer Science (LIACS) at Leiden University, where I’ll continue to build on the research I did during my Ph.D. and explore exciting new directions for auto-tuning. I’m looking forward to leveraging the experience I gained in building high-quality software in all future projects!”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What made working at the eScience Center a unique experience?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“The priority at universities is to always get the research done first, which tends to lead to software that gets the job done but is not accessible, maintainable, or usable outside of the exact scope of the research. The eScience Center has the combination of people experienced in both the academic and the software side of things, which puts it at a unique intersection to create sustainable scientific software. What I created during my time at the eScience Center is not limited to one specific purpose and can immediately be deployed in other people’s research. I’m proud to have been able to make an impact in that way.”&lt;/p&gt;
&lt;p&gt;Read the article the NOS wrote about the &lt;em&gt;&lt;a href=&quot;https://nos.nl/artikel/2552914-astronomen-westerbork-ontrafelen-lichtflits-mysterie-in-de-ruimte&quot;&gt;&lt;em&gt;CORTEX Project&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; (link in Dutch) in January 2025.*&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who are we?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center is a research organization dedicated to applying research software to answer research questions in any scientific domain through project collaborations. It has the largest concentration of dedicated, high-level research software expertise in the Netherlands. The eScience Center also has a &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;fellowship programme&lt;/a&gt; and makes all of its software and training materials openly available online. For more information about what we offer, visit &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/from-phd-student-to-auto-tuning-gpu-expe-e9522c8e.C_BHgcx8.jpeg" medium="image"/><author>Netherlands eScience Center</author></item><item><title>Why companies win by investing in Open-Source Software</title><link>https://blog2.esciencecenter.nl/posts/2025-10-23---why-companies-win-by-investing-in-open-source-software</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-10-23---why-companies-win-by-investing-in-open-source-software</guid><description>&lt;p&gt;Why would a for-profit company want to invest in Open-Source Software? Our collaborator, prof. Eric-Jan Wagenmakers will tell you why.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why companies win by investing in Open-Source Software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;370&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-companies-win-by-investing-in-open-s-bfa19698.CtXRQL3T_18SmN6.webp&quot; srcset=&quot;&quot;&gt;
CC-BY license from: Kojima T, Oishi K, Matsubara Y, Uchiyama Y, Fukushima Y, Aoki N, et al. (2019) Cows painted with zebra-like striping can avoid biting fly attack. PLoS ONE 14(10): e0223447. &lt;a href=&quot;https://doi.org/10.1371/journal.pone.0223447&quot;&gt;https://doi.org/10.1371/journal.pone.0223447&lt;/a&gt;In 2025, the &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Ig_Nobel_Prize_winners&quot;&gt;IgNobel prize&lt;/a&gt; in Biology went to research on “&lt;a href=&quot;http://doi.org/10.1371/journal.pone.0223447&quot;&gt;whether cows painted with zebra-like striping can avoid being bitten by flies&lt;/a&gt;“. Suppose a fictitious company, ZebraCows, wishes to exploit the insights from this groundbreaking work, and adopts &lt;a href=&quot;https://jasp-stats.org/&quot;&gt;JASP&lt;/a&gt; for their quality control analyses.&lt;/p&gt;
&lt;p&gt;The head of the data-analytics department at ZebraCows is unfamiliar with open-source software, and two surprises await them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Their first surprise is that JASP can be freely installed on &lt;em&gt;all&lt;/em&gt; company computers, no strings attached. ZebraCows considers this a big win. Open-source is awesome, they think.&lt;/li&gt;
&lt;li&gt;To receive support and connect JASP even more closely to their needs, ZebraCows starts working together with the JASP Services company through one of their &lt;a href=&quot;https://www.jasp-services.com/service-plans-2/&quot;&gt;service plans&lt;/a&gt;. However, when they read the contracts they are in for a second surprise: all new features that a company requests are immediately added to the JASP open-source code base; this means that everybody in the whole wide world –students, researchers, unrelated and even rival companies– gets to profit from improvements that were requested and paid for by ZebraCows. That seems unfair to ZebraCows, who would prefer the new features to be exclusively available to employees from ZebraCows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below, I briefly outline why ZebraCows should in fact be &lt;em&gt;thrilled&lt;/em&gt; that the code they paid for is available to the whole world instead of only to them. Essentially, ZebraCows stands to profit from JASP being developed, extended, and improved by others –for free!–, while ZebraCows retains maximum digital autonomy**.&lt;/p&gt;
&lt;p&gt;Below is a non-exhaustive list of arguments in favor of open-source software (specifically, JASP) for companies:&lt;/p&gt;
&lt;h2 id=&quot;1-unlimited-free-installation&quot;&gt;1. Unlimited, Free Installation&lt;/h2&gt;
&lt;p&gt;Open-source software such as JASP can be installed on every computer in ZebraCows business network at zero cost. There are no license fees. There is no per-user pricing, and scalability is complete.&lt;/p&gt;
&lt;h2 id=&quot;2-continuous-improvement-at-no-extra-cost&quot;&gt;2. Continuous Improvement at No Extra Cost&lt;/h2&gt;
&lt;p&gt;Open-source features are visible to the &lt;a href=&quot;https://jasp-stats.org/world-map/&quot;&gt;global JASP community&lt;/a&gt;. External contributors (researchers, developers, students) can refine, extend, and maintain the features that ZebraCows cares about, for decades to come — and all for free.&lt;/p&gt;
&lt;h2 id=&quot;3-shared-development-pool&quot;&gt;3. Shared Development Pool&lt;/h2&gt;
&lt;p&gt;Other companies who also want additional features will invest in JASP too. ZebraCows automatically gains access to their improvements, without paying extra.&lt;/p&gt;
&lt;h2 id=&quot;4-no-vendor-lock-in&quot;&gt;4. No Vendor Lock-In&lt;/h2&gt;
&lt;p&gt;With closed-source software, ZebraCows may need to keep paying for updates just to keep their features working. With open-source, the code is available to ZebraCows forever. Nobody can take it away, restrict access, or increase license fees.&lt;/p&gt;
&lt;h2 id=&quot;5-transparency&quot;&gt;5. Transparency&lt;/h2&gt;
&lt;p&gt;Adoption of JASP means that ZebraCows attains complete transparency on the process by which JASP produces its results. In contrast to closed-source software, all the code that JASP uses is available for external inspection and public scrutiny. ZebraCows is not forced to rely exclusively on the documentation or the helpdesk and “take their word for it”.&lt;/p&gt;
&lt;h2 id=&quot;6-limited-costs-for-superior-service&quot;&gt;6. Limited Costs for Superior Service&lt;/h2&gt;
&lt;p&gt;Most open-source service contracts –and certainly those of JASP– are simply a great deal financially. A large commercial software product does not adjust or improve its code to accommodate the wishes of a medium-sized company such as ZebraCows. For only a modest investment, ZebraCows can interact with the JASP Services team and initiate improvements that benefit ZebraCows specifically. Try doing this with &amp;#x3C;insert the name of any large commercial program here*&gt;!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By investing in the development of open-source software such as JASP, companies gain much more than just the features they pay to see implemented. Companies also gain access to a continual, indefinite stream of free improvements, while being protected from lock-in or forced upgrade costs. This way companies profit from unlimited, future-proof access to a program that is designed to meet their needs.&lt;/p&gt;
&lt;p&gt;This piece is a repost (with minor adaptations) from &lt;a href=&quot;https://www.jasp-services.com/why-companies-win-by-investing-in-open-source-software/&quot;&gt;the JASP blog&lt;/a&gt;, reproduced here with permission (and encouragement) from the author, &lt;a href=&quot;https://www.uva.nl/en/profile/w/a/e.m.wagenmakers/e.m.wagenmakers.html&quot;&gt;Eric-Jan Wagenmakers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Professor Wagenmakers is a mathematical psychologist at the University of Amsterdam, the CEO of &lt;a href=&quot;https://jasp-stats.org/&quot;&gt;JASP&lt;/a&gt; (a popular open-source statistical software), and the proud owner of an IgNobel Prize (2024). Currently he is collaborating with the eScience Center in improving the user experience of the JASP module-making community.&lt;/p&gt;</description><pubDate>Thu, 23 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Why would a for-profit company want to invest in Open-Source Software? Our collaborator, prof. Eric-Jan Wagenmakers will tell you why.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why companies win by investing in Open-Source Software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;370&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-companies-win-by-investing-in-open-s-bfa19698.CtXRQL3T_18SmN6.webp&quot; srcset=&quot;&quot;&gt;
CC-BY license from: Kojima T, Oishi K, Matsubara Y, Uchiyama Y, Fukushima Y, Aoki N, et al. (2019) Cows painted with zebra-like striping can avoid biting fly attack. PLoS ONE 14(10): e0223447. &lt;a href=&quot;https://doi.org/10.1371/journal.pone.0223447&quot;&gt;https://doi.org/10.1371/journal.pone.0223447&lt;/a&gt;In 2025, the &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Ig_Nobel_Prize_winners&quot;&gt;IgNobel prize&lt;/a&gt; in Biology went to research on “&lt;a href=&quot;http://doi.org/10.1371/journal.pone.0223447&quot;&gt;whether cows painted with zebra-like striping can avoid being bitten by flies&lt;/a&gt;“. Suppose a fictitious company, ZebraCows, wishes to exploit the insights from this groundbreaking work, and adopts &lt;a href=&quot;https://jasp-stats.org/&quot;&gt;JASP&lt;/a&gt; for their quality control analyses.&lt;/p&gt;
&lt;p&gt;The head of the data-analytics department at ZebraCows is unfamiliar with open-source software, and two surprises await them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Their first surprise is that JASP can be freely installed on &lt;em&gt;all&lt;/em&gt; company computers, no strings attached. ZebraCows considers this a big win. Open-source is awesome, they think.&lt;/li&gt;
&lt;li&gt;To receive support and connect JASP even more closely to their needs, ZebraCows starts working together with the JASP Services company through one of their &lt;a href=&quot;https://www.jasp-services.com/service-plans-2/&quot;&gt;service plans&lt;/a&gt;. However, when they read the contracts they are in for a second surprise: all new features that a company requests are immediately added to the JASP open-source code base; this means that everybody in the whole wide world –students, researchers, unrelated and even rival companies– gets to profit from improvements that were requested and paid for by ZebraCows. That seems unfair to ZebraCows, who would prefer the new features to be exclusively available to employees from ZebraCows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below, I briefly outline why ZebraCows should in fact be &lt;em&gt;thrilled&lt;/em&gt; that the code they paid for is available to the whole world instead of only to them. Essentially, ZebraCows stands to profit from JASP being developed, extended, and improved by others –for free!–, while ZebraCows retains maximum digital autonomy**.&lt;/p&gt;
&lt;p&gt;Below is a non-exhaustive list of arguments in favor of open-source software (specifically, JASP) for companies:&lt;/p&gt;
&lt;h2 id=&quot;1-unlimited-free-installation&quot;&gt;1. Unlimited, Free Installation&lt;/h2&gt;
&lt;p&gt;Open-source software such as JASP can be installed on every computer in ZebraCows business network at zero cost. There are no license fees. There is no per-user pricing, and scalability is complete.&lt;/p&gt;
&lt;h2 id=&quot;2-continuous-improvement-at-no-extra-cost&quot;&gt;2. Continuous Improvement at No Extra Cost&lt;/h2&gt;
&lt;p&gt;Open-source features are visible to the &lt;a href=&quot;https://jasp-stats.org/world-map/&quot;&gt;global JASP community&lt;/a&gt;. External contributors (researchers, developers, students) can refine, extend, and maintain the features that ZebraCows cares about, for decades to come — and all for free.&lt;/p&gt;
&lt;h2 id=&quot;3-shared-development-pool&quot;&gt;3. Shared Development Pool&lt;/h2&gt;
&lt;p&gt;Other companies who also want additional features will invest in JASP too. ZebraCows automatically gains access to their improvements, without paying extra.&lt;/p&gt;
&lt;h2 id=&quot;4-no-vendor-lock-in&quot;&gt;4. No Vendor Lock-In&lt;/h2&gt;
&lt;p&gt;With closed-source software, ZebraCows may need to keep paying for updates just to keep their features working. With open-source, the code is available to ZebraCows forever. Nobody can take it away, restrict access, or increase license fees.&lt;/p&gt;
&lt;h2 id=&quot;5-transparency&quot;&gt;5. Transparency&lt;/h2&gt;
&lt;p&gt;Adoption of JASP means that ZebraCows attains complete transparency on the process by which JASP produces its results. In contrast to closed-source software, all the code that JASP uses is available for external inspection and public scrutiny. ZebraCows is not forced to rely exclusively on the documentation or the helpdesk and “take their word for it”.&lt;/p&gt;
&lt;h2 id=&quot;6-limited-costs-for-superior-service&quot;&gt;6. Limited Costs for Superior Service&lt;/h2&gt;
&lt;p&gt;Most open-source service contracts –and certainly those of JASP– are simply a great deal financially. A large commercial software product does not adjust or improve its code to accommodate the wishes of a medium-sized company such as ZebraCows. For only a modest investment, ZebraCows can interact with the JASP Services team and initiate improvements that benefit ZebraCows specifically. Try doing this with &amp;#x3C;insert the name of any large commercial program here*&gt;!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By investing in the development of open-source software such as JASP, companies gain much more than just the features they pay to see implemented. Companies also gain access to a continual, indefinite stream of free improvements, while being protected from lock-in or forced upgrade costs. This way companies profit from unlimited, future-proof access to a program that is designed to meet their needs.&lt;/p&gt;
&lt;p&gt;This piece is a repost (with minor adaptations) from &lt;a href=&quot;https://www.jasp-services.com/why-companies-win-by-investing-in-open-source-software/&quot;&gt;the JASP blog&lt;/a&gt;, reproduced here with permission (and encouragement) from the author, &lt;a href=&quot;https://www.uva.nl/en/profile/w/a/e.m.wagenmakers/e.m.wagenmakers.html&quot;&gt;Eric-Jan Wagenmakers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Professor Wagenmakers is a mathematical psychologist at the University of Amsterdam, the CEO of &lt;a href=&quot;https://jasp-stats.org/&quot;&gt;JASP&lt;/a&gt; (a popular open-source statistical software), and the proud owner of an IgNobel Prize (2024). Currently he is collaborating with the eScience Center in improving the user experience of the JASP module-making community.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/why-companies-win-by-investing-in-open-s-bfa19698.CtXRQL3T.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Why teach calculus in the age of AI</title><link>https://blog2.esciencecenter.nl/posts/2025-10-09---why-teach-calculus-in-the-age-of-ai</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-10-09---why-teach-calculus-in-the-age-of-ai</guid><description>&lt;p&gt;Why would I learn to compute a derivative by hand when Artificial Intelligence can do it for me?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why teach calculus in the age of AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-teach-calculus-in-the-age-of-ai-603e031b.bNi5rz1v_Z1aoeB5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@shubhamsharan?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Shubham Sharan&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you’re reading this, you’ve probably taken a calculus course before. How was it? Chances are you found it frustrating or, at least, complicated.&lt;/p&gt;
&lt;p&gt;You may remember one of the most feared parts of calculus courses: the computation of derivatives and integrals. For most students, this is the first time they face a mathematical problem whose solution is not a number, but a much more complicated object: a function. Computing derivatives and integrals involves memorizing tables, applying complicated composition rules and avoiding sneaky arithmetic errors. In short, it is hard.&lt;/p&gt;
&lt;h2 id=&quot;enters-technology&quot;&gt;Enters technology&lt;/h2&gt;
&lt;p&gt;For several decades now, it is possible to solve these problems using symbolic computation software packages, available for computers and even for some pocket calculators. Since the explosion of Artificial Intelligence (AI) engines, access to such tools is easier than ever. So, if you want to know the derivative of some function, you can just ask your favourite AI engine via your smartphone, and you’ll (most likely) get the correct answer.&lt;/p&gt;
&lt;p&gt;All of this raises a valid question: why bother learning all those tedious methods?&lt;/p&gt;
&lt;h2 id=&quot;calculus-is-not-only-about-calculations&quot;&gt;Calculus is not only about calculations&lt;/h2&gt;
&lt;p&gt;One of the reasons is that differentiation and integration involve much more than the algorithms. Like all mathematical operations, they have a meaning and applications. As a matter of fact, a huge number of applications: basically all physics and engineering relies on them.&lt;/p&gt;
&lt;p&gt;While it’s true that one doesn’t need to know how to compute derivatives or integrals in order to understand their meaning, it is quite hard to do it without wrestling with some exercises. They are a great way to internalize and create a solid understanding.&lt;/p&gt;
&lt;p&gt;For instance, by learning some of the algorithmic rules, we’ll also learn that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integration by substitution is just the chain rule for derivatives, read backwards.&lt;/li&gt;
&lt;li&gt;Integration by parts is the product rule for derivatives, just written differently.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even the quintessential tedious task, that of reading (and eventually) memorizing the tables, can teach valuable lessons, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A table of integrals is basically a table of derivatives read backwards.&lt;/li&gt;
&lt;li&gt;Derivatives destroy information, hence the arbitrary constant in the table of integrals.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other concepts that are difficult to grasp without “getting your hands dirty” are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integrals and derivatives can be estimated.&lt;/li&gt;
&lt;li&gt;Mathematics can manipulate objects more complicated than numbers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Perhaps more importantly, if you look deeper, you’ll see that studying calculus teaches you more than just mathematics. For instance, solving calculus problems shows you that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some questions have a clear, uncontroversial and verifiable answer.&lt;/li&gt;
&lt;li&gt;You can find out the solution to complicated-looking problems by yourself, using nothing more than pen and paper.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;AI is here to stay, and it is a wonderful tool for many applications. But it comes with some dangers too. One of the main criticisms that AI engines receive from the scientific and teaching communities is that they work as black boxes: they spit out results and encourage users to accept them without further scrutiny.&lt;/p&gt;
&lt;p&gt;Being able to reach conclusions with pen and paper (quite the opposite of a black box) is certainly not less important now than before. It is a crucial skill for responsibly using AI as a learning companion.&lt;/p&gt;
&lt;p&gt;Education is not only about getting the right answers. Education is also about learning how to ask the right questions, to reason clearly and to trust your own judgment.&lt;/p&gt;
&lt;p&gt;Technology can solve problems for you. Calculus teaches that, at least some of them, you can solve yourself. That kind of confidence, curiosity, and mental discipline is something no black box can give you.&lt;/p&gt;
&lt;p&gt;You earn it.&lt;/p&gt;
&lt;p&gt;This piece appeared first in &lt;em&gt;&lt;a href=&quot;https://mappingignorance.org/2025/08/18/why-teach-calculus-in-the-age-of-ai/&quot;&gt;&lt;em&gt;mappingignorance.org&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;</description><pubDate>Thu, 09 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Why would I learn to compute a derivative by hand when Artificial Intelligence can do it for me?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why teach calculus in the age of AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-teach-calculus-in-the-age-of-ai-603e031b.bNi5rz1v_Z1aoeB5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@shubhamsharan?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Shubham Sharan&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you’re reading this, you’ve probably taken a calculus course before. How was it? Chances are you found it frustrating or, at least, complicated.&lt;/p&gt;
&lt;p&gt;You may remember one of the most feared parts of calculus courses: the computation of derivatives and integrals. For most students, this is the first time they face a mathematical problem whose solution is not a number, but a much more complicated object: a function. Computing derivatives and integrals involves memorizing tables, applying complicated composition rules and avoiding sneaky arithmetic errors. In short, it is hard.&lt;/p&gt;
&lt;h2 id=&quot;enters-technology&quot;&gt;Enters technology&lt;/h2&gt;
&lt;p&gt;For several decades now, it is possible to solve these problems using symbolic computation software packages, available for computers and even for some pocket calculators. Since the explosion of Artificial Intelligence (AI) engines, access to such tools is easier than ever. So, if you want to know the derivative of some function, you can just ask your favourite AI engine via your smartphone, and you’ll (most likely) get the correct answer.&lt;/p&gt;
&lt;p&gt;All of this raises a valid question: why bother learning all those tedious methods?&lt;/p&gt;
&lt;h2 id=&quot;calculus-is-not-only-about-calculations&quot;&gt;Calculus is not only about calculations&lt;/h2&gt;
&lt;p&gt;One of the reasons is that differentiation and integration involve much more than the algorithms. Like all mathematical operations, they have a meaning and applications. As a matter of fact, a huge number of applications: basically all physics and engineering relies on them.&lt;/p&gt;
&lt;p&gt;While it’s true that one doesn’t need to know how to compute derivatives or integrals in order to understand their meaning, it is quite hard to do it without wrestling with some exercises. They are a great way to internalize and create a solid understanding.&lt;/p&gt;
&lt;p&gt;For instance, by learning some of the algorithmic rules, we’ll also learn that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integration by substitution is just the chain rule for derivatives, read backwards.&lt;/li&gt;
&lt;li&gt;Integration by parts is the product rule for derivatives, just written differently.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even the quintessential tedious task, that of reading (and eventually) memorizing the tables, can teach valuable lessons, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A table of integrals is basically a table of derivatives read backwards.&lt;/li&gt;
&lt;li&gt;Derivatives destroy information, hence the arbitrary constant in the table of integrals.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other concepts that are difficult to grasp without “getting your hands dirty” are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integrals and derivatives can be estimated.&lt;/li&gt;
&lt;li&gt;Mathematics can manipulate objects more complicated than numbers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Perhaps more importantly, if you look deeper, you’ll see that studying calculus teaches you more than just mathematics. For instance, solving calculus problems shows you that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some questions have a clear, uncontroversial and verifiable answer.&lt;/li&gt;
&lt;li&gt;You can find out the solution to complicated-looking problems by yourself, using nothing more than pen and paper.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;AI is here to stay, and it is a wonderful tool for many applications. But it comes with some dangers too. One of the main criticisms that AI engines receive from the scientific and teaching communities is that they work as black boxes: they spit out results and encourage users to accept them without further scrutiny.&lt;/p&gt;
&lt;p&gt;Being able to reach conclusions with pen and paper (quite the opposite of a black box) is certainly not less important now than before. It is a crucial skill for responsibly using AI as a learning companion.&lt;/p&gt;
&lt;p&gt;Education is not only about getting the right answers. Education is also about learning how to ask the right questions, to reason clearly and to trust your own judgment.&lt;/p&gt;
&lt;p&gt;Technology can solve problems for you. Calculus teaches that, at least some of them, you can solve yourself. That kind of confidence, curiosity, and mental discipline is something no black box can give you.&lt;/p&gt;
&lt;p&gt;You earn it.&lt;/p&gt;
&lt;p&gt;This piece appeared first in &lt;em&gt;&lt;a href=&quot;https://mappingignorance.org/2025/08/18/why-teach-calculus-in-the-age-of-ai/&quot;&gt;&lt;em&gt;mappingignorance.org&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/why-teach-calculus-in-the-age-of-ai-603e031b.bNi5rz1v.jpg" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Be like Jurriaan</title><link>https://blog2.esciencecenter.nl/posts/2025-09-25---be-like-jurriaan</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-09-25---be-like-jurriaan</guid><description>&lt;h2 id=&quot;write-copy-pasteable-readmes-for-developers&quot;&gt;Write copy-pasteable READMEs for developers&lt;/h2&gt;
&lt;p&gt;The main message of this post is short:&lt;/p&gt;
&lt;p&gt;Thank you,&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/fd96a2a5f9bc?source=post_page---user_mention--ac9e8926d1b3---------------------------------------&quot;&gt;Jurriaan H. Spaaks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;, for including developer’s READMEs in the &lt;a href=&quot;https://github.com/zenodraft/zenodraft&quot;&gt;zenodraft&lt;/a&gt; and the &lt;a href=&quot;https://github.com/zenodraft/action&quot;&gt;zenodraft GitHub action&lt;/a&gt; repos!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Zenodraft automates uploading releases of your repository to Zenodo. This story applies to any similar tool.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In particular, having copy-pasteable commands ready to get going saved my week. Without them, I would have dropped any hope of &lt;a href=&quot;https://github.com/NLeSC/guide/pull/443&quot;&gt;fixing the issues I had running a CI workflow&lt;/a&gt; … or worse, I would have had to rebuild something like zenodraft from scratch!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1141&quot; height=&quot;969&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SP0juQAauTLoEAw6Scb8RQ-1a7e6e06.BxgtAdcf_Z6b3kU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It doesn’t have to be long and complicated. Just having those commands ready to copy is all I need.&lt;/p&gt;
&lt;p&gt;Zenodraft is written in TypeScript, which is a foreign language to me. I’m unfamiliar with the tools necessary to make it work. The &lt;a href=&quot;https://github.com/zenodraft/action/blob/main/README.dev.md&quot;&gt;developer’s README&lt;/a&gt; file exactly fixed that issue, allowing me, a TypeScript-noob (but otherwise experienced programmer), to dive in and fix my problems within a few hours of building up the courage to even try. I was even able to contribute a &lt;a href=&quot;https://github.com/zenodraft/action/pull/31&quot;&gt;PR&lt;/a&gt;, my first one in a TypeScript project!&lt;/p&gt;
&lt;p&gt;In the world of open source (research) software, where ambitions are high and budgets are low, it turns out that such documentation can mean the difference between life and death for the software.&lt;/p&gt;
&lt;p&gt;If you are the owner of a package and expect to be unavailable to maintain your code, the best thing you can do is to enable the random passer-by to independently fix their own problems.&lt;/p&gt;
&lt;p&gt;Be like Jurriaan. Write developer’s READMEs!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;503&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xNfeV7xNnIrP31fx-c6c80d22.VWF9S1Sp_cBNay.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you had asked me a week ago whether such documentation is necessary I would have shrugged. This experience made me change my mind. A lazy, clutter-averse and/or “minimalist” person could argue that most development ecosystem tools are well documented on their own, and technically they might even be right (although rants on how soul-crushingly horrible Python’s or Javascript’s developers’ ecosystems are aren’t hard to find). Why duplicate efforts?&lt;/p&gt;
&lt;p&gt;Just ask yourself: would you take the effort of reading up on the current state of such an ecosystem just to make random-tool-on-GitHub do what you want? Even if it’s just a minor tweak in the code, the effort necessary to get that tweak into production can easily put developers off.&lt;/p&gt;
&lt;p&gt;So, just copy-paste the minimal commands you need to get a working development environment set up into a README file. You probably have these commands set up in your CI build job already, so it’s really not that much effort. And you might gain a new contributor…&lt;/p&gt;</description><pubDate>Thu, 25 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;write-copy-pasteable-readmes-for-developers&quot;&gt;Write copy-pasteable READMEs for developers&lt;/h2&gt;
&lt;p&gt;The main message of this post is short:&lt;/p&gt;
&lt;p&gt;Thank you,&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/fd96a2a5f9bc?source=post_page---user_mention--ac9e8926d1b3---------------------------------------&quot;&gt;Jurriaan H. Spaaks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;, for including developer’s READMEs in the &lt;a href=&quot;https://github.com/zenodraft/zenodraft&quot;&gt;zenodraft&lt;/a&gt; and the &lt;a href=&quot;https://github.com/zenodraft/action&quot;&gt;zenodraft GitHub action&lt;/a&gt; repos!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Zenodraft automates uploading releases of your repository to Zenodo. This story applies to any similar tool.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In particular, having copy-pasteable commands ready to get going saved my week. Without them, I would have dropped any hope of &lt;a href=&quot;https://github.com/NLeSC/guide/pull/443&quot;&gt;fixing the issues I had running a CI workflow&lt;/a&gt; … or worse, I would have had to rebuild something like zenodraft from scratch!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1141&quot; height=&quot;969&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SP0juQAauTLoEAw6Scb8RQ-1a7e6e06.BxgtAdcf_Z6b3kU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It doesn’t have to be long and complicated. Just having those commands ready to copy is all I need.&lt;/p&gt;
&lt;p&gt;Zenodraft is written in TypeScript, which is a foreign language to me. I’m unfamiliar with the tools necessary to make it work. The &lt;a href=&quot;https://github.com/zenodraft/action/blob/main/README.dev.md&quot;&gt;developer’s README&lt;/a&gt; file exactly fixed that issue, allowing me, a TypeScript-noob (but otherwise experienced programmer), to dive in and fix my problems within a few hours of building up the courage to even try. I was even able to contribute a &lt;a href=&quot;https://github.com/zenodraft/action/pull/31&quot;&gt;PR&lt;/a&gt;, my first one in a TypeScript project!&lt;/p&gt;
&lt;p&gt;In the world of open source (research) software, where ambitions are high and budgets are low, it turns out that such documentation can mean the difference between life and death for the software.&lt;/p&gt;
&lt;p&gt;If you are the owner of a package and expect to be unavailable to maintain your code, the best thing you can do is to enable the random passer-by to independently fix their own problems.&lt;/p&gt;
&lt;p&gt;Be like Jurriaan. Write developer’s READMEs!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;503&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xNfeV7xNnIrP31fx-c6c80d22.VWF9S1Sp_cBNay.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you had asked me a week ago whether such documentation is necessary I would have shrugged. This experience made me change my mind. A lazy, clutter-averse and/or “minimalist” person could argue that most development ecosystem tools are well documented on their own, and technically they might even be right (although rants on how soul-crushingly horrible Python’s or Javascript’s developers’ ecosystems are aren’t hard to find). Why duplicate efforts?&lt;/p&gt;
&lt;p&gt;Just ask yourself: would you take the effort of reading up on the current state of such an ecosystem just to make random-tool-on-GitHub do what you want? Even if it’s just a minor tweak in the code, the effort necessary to get that tweak into production can easily put developers off.&lt;/p&gt;
&lt;p&gt;So, just copy-paste the minimal commands you need to get a working development environment set up into a README file. You probably have these commands set up in your CI build job already, so it’s really not that much effort. And you might gain a new contributor…&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_SP0juQAauTLoEAw6Scb8RQ-1a7e6e06.BxgtAdcf.png" medium="image"/><author>Patrick Bos</author></item><item><title>5 tips for writing a successful eScience Center proposal</title><link>https://blog2.esciencecenter.nl/posts/2025-08-28---5-tips-for-writing-a-successful-escience-center-proposal</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-08-28---5-tips-for-writing-a-successful-escience-center-proposal</guid><description>&lt;p&gt;22&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Over the years, we’ve worked on a wide range of collaborative projects through our open calls. The most successful ones? They tend to have a few things in common right from the proposal stage. Here are five tips to help your proposal lay the foundation for a smooth, impactful, and genuinely rewarding collaboration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;5 tips for writing a successful eScience Center proposal&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/5-tips-for-writing-a-successful-escience-f7ee65e6.DCBqA6Y7_ZxiNhL.webp&quot; srcset=&quot;&quot;&gt;
Image adapted from &lt;a href=&quot;https://unsplash.com/photos/a-red-and-white-rocket-ship-flying-through-the-sky-O1jUvZX9DOA&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;1-describe-the-challenge-not-the-solution&quot;&gt;1. Describe the challenge, not the solution&lt;/h3&gt;
&lt;p&gt;We love a good challenge. If the technical solution is already fully defined, there’s less room for us to contribute meaningfully. For example, instead of saying &lt;em&gt;“we need a dashboard that does X”&lt;/em&gt;, describe the challenge: &lt;em&gt;“we struggle to analyze Y because current tools can’t handle Z.”&lt;/em&gt; That kind of framing sparks our curiosity and drives the creative collaboration we love.&lt;/p&gt;
&lt;h3 id=&quot;2-dedicate-real-time-to-the-project&quot;&gt;2. Dedicate real time to the project&lt;/h3&gt;
&lt;p&gt;We’re looking for genuine teamwork — whether that’s you, your postdocs, or PhD students. The best projects have collaborators who test the software as it is built. For example: &lt;em&gt;“we tried the new analysis module this week, here’s where it’s slow, and here’s a feature we hadn’t thought of before.”&lt;/em&gt; Aligning your proposal with existing commitments makes this kind of feedback loop much easier.&lt;/p&gt;
&lt;h3 id=&quot;3-be-realistic&quot;&gt;3. Be realistic&lt;/h3&gt;
&lt;p&gt;Ambition gets projects funded. And we love bold ideas — but bold doesn’t mean bloated. Make sure your proposal has a solid core to build on, and leave room for exploration, iteration — even failure. A focused project with space to explore usually delivers more than an overpacked one that runs out of steam.&lt;/p&gt;
&lt;h3 id=&quot;4-build-on-what-you-have&quot;&gt;4. Build on what you have&lt;/h3&gt;
&lt;p&gt;We love improving workflows and building better tools — but starting from scratch rarely works in one project. If the data is missing, the workflow doesn’t exist, or the whole thing is still hypothetical, that’s a red flag. Don’t think what might be useful for &lt;em&gt;someone, someday&lt;/em&gt;. Instead, think what would help *you, today, *and make your code and data available before submitting the proposal. Even a messy dataset or clunky script gives us a real starting point, so we can hit the ground running.&lt;/p&gt;
&lt;h3 id=&quot;5-think-beyond-the-project&quot;&gt;5. Think beyond the project&lt;/h3&gt;
&lt;p&gt;A successful project doesn’t stop when the funding ends. Our calls require a sustainability plan — and for good &lt;a href=&quot;https://doi.org/10.5281/zenodo.15646827&quot;&gt;reason&lt;/a&gt;. The tools that have the biggest impact are those that become part of daily workflows and get shared, adapted, and improved over time by a community of users. So think about how your software fits into your everyday research, and who else might use or build on it after the project wraps up. Check out the &lt;a href=&quot;https://smp.research.software/&quot;&gt;SMP tool&lt;/a&gt; to get a jump start.&lt;/p&gt;
&lt;p&gt;Ready to collaborate? Check our &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/calls-for-proposals/&quot;&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; for an up-to-date overview of past and open calls, or simply &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/contact-us/&quot;&gt;&lt;em&gt;get in touch&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog post represents original content created with AI assistance.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 28 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;22&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Over the years, we’ve worked on a wide range of collaborative projects through our open calls. The most successful ones? They tend to have a few things in common right from the proposal stage. Here are five tips to help your proposal lay the foundation for a smooth, impactful, and genuinely rewarding collaboration.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;5 tips for writing a successful eScience Center proposal&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/5-tips-for-writing-a-successful-escience-f7ee65e6.DCBqA6Y7_ZxiNhL.webp&quot; srcset=&quot;&quot;&gt;
Image adapted from &lt;a href=&quot;https://unsplash.com/photos/a-red-and-white-rocket-ship-flying-through-the-sky-O1jUvZX9DOA&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;1-describe-the-challenge-not-the-solution&quot;&gt;1. Describe the challenge, not the solution&lt;/h3&gt;
&lt;p&gt;We love a good challenge. If the technical solution is already fully defined, there’s less room for us to contribute meaningfully. For example, instead of saying &lt;em&gt;“we need a dashboard that does X”&lt;/em&gt;, describe the challenge: &lt;em&gt;“we struggle to analyze Y because current tools can’t handle Z.”&lt;/em&gt; That kind of framing sparks our curiosity and drives the creative collaboration we love.&lt;/p&gt;
&lt;h3 id=&quot;2-dedicate-real-time-to-the-project&quot;&gt;2. Dedicate real time to the project&lt;/h3&gt;
&lt;p&gt;We’re looking for genuine teamwork — whether that’s you, your postdocs, or PhD students. The best projects have collaborators who test the software as it is built. For example: &lt;em&gt;“we tried the new analysis module this week, here’s where it’s slow, and here’s a feature we hadn’t thought of before.”&lt;/em&gt; Aligning your proposal with existing commitments makes this kind of feedback loop much easier.&lt;/p&gt;
&lt;h3 id=&quot;3-be-realistic&quot;&gt;3. Be realistic&lt;/h3&gt;
&lt;p&gt;Ambition gets projects funded. And we love bold ideas — but bold doesn’t mean bloated. Make sure your proposal has a solid core to build on, and leave room for exploration, iteration — even failure. A focused project with space to explore usually delivers more than an overpacked one that runs out of steam.&lt;/p&gt;
&lt;h3 id=&quot;4-build-on-what-you-have&quot;&gt;4. Build on what you have&lt;/h3&gt;
&lt;p&gt;We love improving workflows and building better tools — but starting from scratch rarely works in one project. If the data is missing, the workflow doesn’t exist, or the whole thing is still hypothetical, that’s a red flag. Don’t think what might be useful for &lt;em&gt;someone, someday&lt;/em&gt;. Instead, think what would help *you, today, *and make your code and data available before submitting the proposal. Even a messy dataset or clunky script gives us a real starting point, so we can hit the ground running.&lt;/p&gt;
&lt;h3 id=&quot;5-think-beyond-the-project&quot;&gt;5. Think beyond the project&lt;/h3&gt;
&lt;p&gt;A successful project doesn’t stop when the funding ends. Our calls require a sustainability plan — and for good &lt;a href=&quot;https://doi.org/10.5281/zenodo.15646827&quot;&gt;reason&lt;/a&gt;. The tools that have the biggest impact are those that become part of daily workflows and get shared, adapted, and improved over time by a community of users. So think about how your software fits into your everyday research, and who else might use or build on it after the project wraps up. Check out the &lt;a href=&quot;https://smp.research.software/&quot;&gt;SMP tool&lt;/a&gt; to get a jump start.&lt;/p&gt;
&lt;p&gt;Ready to collaborate? Check our &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/calls-for-proposals/&quot;&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; for an up-to-date overview of past and open calls, or simply &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/contact-us/&quot;&gt;&lt;em&gt;get in touch&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog post represents original content created with AI assistance.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/5-tips-for-writing-a-successful-escience-f7ee65e6.DCBqA6Y7.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Could AI be (in) FAIR?</title><link>https://blog2.esciencecenter.nl/posts/2025-07-10---could-ai-be-in-fair</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-07-10---could-ai-be-in-fair</guid><description>&lt;p&gt;&lt;em&gt;Open Science is driven by FAIR principles. Made for data, adapted for software, how can they survive the current wave of “Artificial Intelligence”? Resistance from those selling it as a solution for all problems is to be expected.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Scientific progress is actively hindered if research data is stored on inaccessible servers or private hard disks, in proprietary formats, or preprocessed in unknown ways. The authors of the &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;original FAIR&lt;/a&gt; &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;paper&lt;/a&gt; have therefore demanded to leave non-collaborative practices behind: instead, make data F**indable, &lt;strong&gt;A&lt;/strong&gt;ccessible, &lt;strong&gt;I&lt;/strong&gt;nteroperable and &lt;strong&gt;R&lt;/strong&gt;eusable (FAIR)!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-4309ea06.BpquOFT5_2wdBHI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@theshantanukr?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Shantanu Kumar&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;The underlying ideas have been pillars of scientific methodology &lt;a href=&quot;https://blog2.esciencecenter.nl/fair-principles-5000-years-of-common-sense-ba85086ba79c&quot;&gt;for thousands of years&lt;/a&gt;, but the rise of computerized methods in practically all research fields has created the need to make the FAIR principles explicit. The increase of computational processing power and algorithms to make efficient use of it have interwoven disciplines including Natural Language Processing, Information Retrieval, Information Science, and Computer Science. Artificial Intelligence is one of the products and has now impacted not only academic research, but also medicine, [education](&lt;a href=&quot;https://doi.org/10.48550/ar&quot;&gt;https://doi.org/10.48550/ar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Xiv.2412.06651), libraries and archives, and even &lt;a href=&quot;https://www.rollingstone.com/culture/culture-features/ai-spiritual-delusions-destroying-human-relationships-1235330175/&quot;&gt;spirituality&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fair-vs-ai&quot;&gt;Fair vs. AI&lt;/h2&gt;
&lt;p&gt;Not reinventing the wheel for each study is the essence of scientific progress; hence, reusability is the primary goal of the FAIR principles. Promises about advances to be expected by current AI generations are bold. Supposedly, they achieve “&lt;a href=&quot;https://arxiv.org/abs/2311.12022&quot;&gt;PhD-level intelligence&lt;/a&gt;” already, even though a closer look reveals that this merely refers to the ability to fill in exam questions accurately. Anyway, the FAIR principles seem to be falling off the wagon, as ChatGPT and its colleagues are happy to confirm (see Figures 1–3).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;621&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-9836fa99.BECPsWIg_Z2b781H.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: According to ChatGPT, the letters “A” and “I” do not appear in FAIR.The paper “&lt;a href=&quot;https://www.nature.com/articles/s41597-023-02298-6&quot;&gt;FAIR for AI: An interdisciplinary and international community building perspective&lt;/a&gt;” proposed the following definitions for FAIR AI models:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An AI model is &lt;strong&gt;Findable&lt;/strong&gt; when a digital object identifier (DOI) can direct a human or machine to a digital resource […];&lt;/li&gt;
&lt;li&gt;it is &lt;strong&gt;Accessible&lt;/strong&gt; when it and its metadata may be readily downloaded […];&lt;/li&gt;
&lt;li&gt;it is &lt;strong&gt;Interoperable&lt;/strong&gt; when it can seamlessly interact with other models, data, software, and hardware architectures;&lt;/li&gt;
&lt;li&gt;and it is &lt;strong&gt;Reusable&lt;/strong&gt; when it can be used by humans, machines and other models to reproduce its expected inference capabilities […].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These definitions are a promising step forward, but apply to models as static artifacts. However, they do not address the methodology that uses AI.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;207&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-4394aa7c.Ca9SB3Hi_Z2oEBSa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: Gemini cannot see the “AI” in “FAIR”, either.&lt;/p&gt;
&lt;h2 id=&quot;fair-software&quot;&gt;FAIR Software&lt;/h2&gt;
&lt;p&gt;Software did not fit into the original FAIR principles that assumed static data sets, hence specific FAIR principles for research software were &lt;a href=&quot;https://www.nature.com/articles/s41597-022-01710-x&quot;&gt;introduced&lt;/a&gt;, along with a &lt;a href=&quot;https://fairsoftwarechecklist.net/&quot;&gt;checklist&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;F&lt;/strong&gt;indable: the software should have a globally unique identifier and be registered in e.g. the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt;, […].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt;ccessible: users can access the software, including its source code […].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I&lt;/strong&gt;nteroperable: the software should read and write open data formats, […].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;R&lt;/strong&gt;eusable: all information to compile the software is provided, […].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together with DANS, we have also provided &lt;a href=&quot;https://fair-software.eu/&quot;&gt;recommendations&lt;/a&gt; on how to practically implement these criteria using available services.&lt;/p&gt;
&lt;h2 id=&quot;ai-in-science&quot;&gt;AI in Science&lt;/h2&gt;
&lt;p&gt;AI impacts scientific methods in different ways than software did, though. A &lt;a href=&quot;https://royalsociety.org/news-resources/projects/science-in-the-age-of-ai/&quot;&gt;report by the Royal Society&lt;/a&gt; lists six use cases for AI in research:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extract and learn features from raw data and extensive datasets&lt;/li&gt;
&lt;li&gt;Gain insights from unstructured, multi-modal and fragmented data&lt;/li&gt;
&lt;li&gt;Generate predictions and synthetic data from existing content&lt;/li&gt;
&lt;li&gt;Information synthesis in academic writing, literature reviews and summarization&lt;/li&gt;
&lt;li&gt;Generate software code&lt;/li&gt;
&lt;li&gt;Automate labour-intensive tasks to test diverse hypotheses&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In these examples, machine learning and language models are not the subject of research but instead serve as means to various ends.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;203&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-fc40bcad.Db99iNnf_Z2seaDg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: the Llama model is certain that there is no AI in FAIR.Computational linguists have shown that (Large) Language Models serve as &lt;a href=&quot;https://doi.org/10.1145/3442188.3445922&quot;&gt;parrots&lt;/a&gt; that remix the data they have been trained on in unpredictable ways, which entails risks including ecological harm, economic monopolization and encoded biases. When putting those aside for a moment, ‘parroting’ might not sound too bad from a reproducibility point of view. However, nobody knows what a generative language model is parroting exactly. Not even the developers, let alone the users, can trace back the &lt;a href=&quot;https://suchir.net/fair_use.html&quot;&gt;impact of specific data samples on the weights of a model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://doi.org/10.1145/3442188.3445922&quot;&gt;Royal Society report&lt;/a&gt; lists additional concerns, for instance, researchers with misconceptions about statistics, overreliance on machine learning outputs, and a lack of skills and incentives for academic researchers. Lack of transparency is often built into proprietary products, but LLMs are a particularly hard-to-open black box, as they involve complex stochastic processes. Misleading marketing claims and bold promises from the companies behind the chatbots increase transparency even more, rather than mitigating them.&lt;/p&gt;
&lt;h2 id=&quot;new-fair-principles&quot;&gt;New FAIR Principles&lt;/h2&gt;
&lt;p&gt;FAIR principles for AI must make sure that all information about AI-based research is provided so that other researchers can understand, verify and reproduce the results of a colleague. The enormous resources required to develop a new language model make reusability particularly relevant. Reinventing a wheel of that size again and again is too costly for any society.&lt;/p&gt;
&lt;p&gt;The fuzziness of the decades&lt;a href=&quot;https://doi.org/10.3233/HSM-1985-5207&quot;&gt;-old term Artificial Intelligence&lt;/a&gt;, as well as its misuse &lt;a href=&quot;https://bookshop.org/p/books/empire-of-ai-dreams-and-nightmares-in-sam-altman-s-openai-karen-hao/22156498&quot;&gt;for utopian and dystopian myths&lt;/a&gt; and &lt;a href=&quot;https://thecon.ai/&quot;&gt;cons,&lt;/a&gt; has created a semantic fog around AI that is counterproductive for spreading technical understanding, sometimes causing &lt;a href=&quot;https://www.theatlantic.com/culture/archive/2025/06/artificial-intelligence-illiteracy/683021/&quot;&gt;catastrophic consequences for the users&lt;/a&gt;. Recent studies have shown how the most recent trend within the AI community, “reasoning models”, creates an &lt;a href=&quot;https://substack.com/inbox/post/166103484&quot;&gt;illusion of thinking&lt;/a&gt;. At the same time, the go-to methods for evaluating Chatbots have turned out to be misleading, as shown in the &lt;a href=&quot;http://arxiv.org/abs/2504.20879&quot;&gt;Leaderboard Illusion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1293&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-b427a737.Bdkc9wXy_1VP1Ap.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4: LLMs tend to fail on reasoning tasks if they do not exactly match the training data.Those who sell the promise of redemption through AGI (Artificial General Intelligence*) are not interested in transparency or Open Science. Bringing FAIRness into the field, on the other hand, facilitates scientific progress. FAIR principles for AI must allow researchers to understand AI and enable them to make informed decisions about how to incorporate it into their research.&lt;/p&gt;
&lt;p&gt;The first step is to move away from referring to LLM-based, generative AI in a mystifying manner. Instead, researchers must discuss tangible tasks and techniques that can be evaluated objectively. Only this will allow us to define FAIR principles for AI: how can we make sure, LLM outputs can be f**ound by anyone, are &lt;strong&gt;a&lt;/strong&gt;ccessible through open protocols, &lt;strong&gt;i&lt;/strong&gt;nteroperable with other research data, and — perhaps most importantly — become &lt;strong&gt;r&lt;/strong&gt;eproducible?&lt;/p&gt;</description><pubDate>Thu, 10 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Open Science is driven by FAIR principles. Made for data, adapted for software, how can they survive the current wave of “Artificial Intelligence”? Resistance from those selling it as a solution for all problems is to be expected.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Scientific progress is actively hindered if research data is stored on inaccessible servers or private hard disks, in proprietary formats, or preprocessed in unknown ways. The authors of the &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;original FAIR&lt;/a&gt; &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;paper&lt;/a&gt; have therefore demanded to leave non-collaborative practices behind: instead, make data F**indable, &lt;strong&gt;A&lt;/strong&gt;ccessible, &lt;strong&gt;I&lt;/strong&gt;nteroperable and &lt;strong&gt;R&lt;/strong&gt;eusable (FAIR)!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-4309ea06.BpquOFT5_2wdBHI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@theshantanukr?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Shantanu Kumar&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;The underlying ideas have been pillars of scientific methodology &lt;a href=&quot;https://blog2.esciencecenter.nl/fair-principles-5000-years-of-common-sense-ba85086ba79c&quot;&gt;for thousands of years&lt;/a&gt;, but the rise of computerized methods in practically all research fields has created the need to make the FAIR principles explicit. The increase of computational processing power and algorithms to make efficient use of it have interwoven disciplines including Natural Language Processing, Information Retrieval, Information Science, and Computer Science. Artificial Intelligence is one of the products and has now impacted not only academic research, but also medicine, [education](&lt;a href=&quot;https://doi.org/10.48550/ar&quot;&gt;https://doi.org/10.48550/ar&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Xiv.2412.06651), libraries and archives, and even &lt;a href=&quot;https://www.rollingstone.com/culture/culture-features/ai-spiritual-delusions-destroying-human-relationships-1235330175/&quot;&gt;spirituality&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fair-vs-ai&quot;&gt;Fair vs. AI&lt;/h2&gt;
&lt;p&gt;Not reinventing the wheel for each study is the essence of scientific progress; hence, reusability is the primary goal of the FAIR principles. Promises about advances to be expected by current AI generations are bold. Supposedly, they achieve “&lt;a href=&quot;https://arxiv.org/abs/2311.12022&quot;&gt;PhD-level intelligence&lt;/a&gt;” already, even though a closer look reveals that this merely refers to the ability to fill in exam questions accurately. Anyway, the FAIR principles seem to be falling off the wagon, as ChatGPT and its colleagues are happy to confirm (see Figures 1–3).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;621&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-9836fa99.BECPsWIg_Z2b781H.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: According to ChatGPT, the letters “A” and “I” do not appear in FAIR.The paper “&lt;a href=&quot;https://www.nature.com/articles/s41597-023-02298-6&quot;&gt;FAIR for AI: An interdisciplinary and international community building perspective&lt;/a&gt;” proposed the following definitions for FAIR AI models:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An AI model is &lt;strong&gt;Findable&lt;/strong&gt; when a digital object identifier (DOI) can direct a human or machine to a digital resource […];&lt;/li&gt;
&lt;li&gt;it is &lt;strong&gt;Accessible&lt;/strong&gt; when it and its metadata may be readily downloaded […];&lt;/li&gt;
&lt;li&gt;it is &lt;strong&gt;Interoperable&lt;/strong&gt; when it can seamlessly interact with other models, data, software, and hardware architectures;&lt;/li&gt;
&lt;li&gt;and it is &lt;strong&gt;Reusable&lt;/strong&gt; when it can be used by humans, machines and other models to reproduce its expected inference capabilities […].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These definitions are a promising step forward, but apply to models as static artifacts. However, they do not address the methodology that uses AI.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;207&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-4394aa7c.Ca9SB3Hi_Z2oEBSa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: Gemini cannot see the “AI” in “FAIR”, either.&lt;/p&gt;
&lt;h2 id=&quot;fair-software&quot;&gt;FAIR Software&lt;/h2&gt;
&lt;p&gt;Software did not fit into the original FAIR principles that assumed static data sets, hence specific FAIR principles for research software were &lt;a href=&quot;https://www.nature.com/articles/s41597-022-01710-x&quot;&gt;introduced&lt;/a&gt;, along with a &lt;a href=&quot;https://fairsoftwarechecklist.net/&quot;&gt;checklist&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;F&lt;/strong&gt;indable: the software should have a globally unique identifier and be registered in e.g. the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt;, […].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt;ccessible: users can access the software, including its source code […].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I&lt;/strong&gt;nteroperable: the software should read and write open data formats, […].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;R&lt;/strong&gt;eusable: all information to compile the software is provided, […].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together with DANS, we have also provided &lt;a href=&quot;https://fair-software.eu/&quot;&gt;recommendations&lt;/a&gt; on how to practically implement these criteria using available services.&lt;/p&gt;
&lt;h2 id=&quot;ai-in-science&quot;&gt;AI in Science&lt;/h2&gt;
&lt;p&gt;AI impacts scientific methods in different ways than software did, though. A &lt;a href=&quot;https://royalsociety.org/news-resources/projects/science-in-the-age-of-ai/&quot;&gt;report by the Royal Society&lt;/a&gt; lists six use cases for AI in research:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Extract and learn features from raw data and extensive datasets&lt;/li&gt;
&lt;li&gt;Gain insights from unstructured, multi-modal and fragmented data&lt;/li&gt;
&lt;li&gt;Generate predictions and synthetic data from existing content&lt;/li&gt;
&lt;li&gt;Information synthesis in academic writing, literature reviews and summarization&lt;/li&gt;
&lt;li&gt;Generate software code&lt;/li&gt;
&lt;li&gt;Automate labour-intensive tasks to test diverse hypotheses&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In these examples, machine learning and language models are not the subject of research but instead serve as means to various ends.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;203&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-fc40bcad.Db99iNnf_Z2seaDg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: the Llama model is certain that there is no AI in FAIR.Computational linguists have shown that (Large) Language Models serve as &lt;a href=&quot;https://doi.org/10.1145/3442188.3445922&quot;&gt;parrots&lt;/a&gt; that remix the data they have been trained on in unpredictable ways, which entails risks including ecological harm, economic monopolization and encoded biases. When putting those aside for a moment, ‘parroting’ might not sound too bad from a reproducibility point of view. However, nobody knows what a generative language model is parroting exactly. Not even the developers, let alone the users, can trace back the &lt;a href=&quot;https://suchir.net/fair_use.html&quot;&gt;impact of specific data samples on the weights of a model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://doi.org/10.1145/3442188.3445922&quot;&gt;Royal Society report&lt;/a&gt; lists additional concerns, for instance, researchers with misconceptions about statistics, overreliance on machine learning outputs, and a lack of skills and incentives for academic researchers. Lack of transparency is often built into proprietary products, but LLMs are a particularly hard-to-open black box, as they involve complex stochastic processes. Misleading marketing claims and bold promises from the companies behind the chatbots increase transparency even more, rather than mitigating them.&lt;/p&gt;
&lt;h2 id=&quot;new-fair-principles&quot;&gt;New FAIR Principles&lt;/h2&gt;
&lt;p&gt;FAIR principles for AI must make sure that all information about AI-based research is provided so that other researchers can understand, verify and reproduce the results of a colleague. The enormous resources required to develop a new language model make reusability particularly relevant. Reinventing a wheel of that size again and again is too costly for any society.&lt;/p&gt;
&lt;p&gt;The fuzziness of the decades&lt;a href=&quot;https://doi.org/10.3233/HSM-1985-5207&quot;&gt;-old term Artificial Intelligence&lt;/a&gt;, as well as its misuse &lt;a href=&quot;https://bookshop.org/p/books/empire-of-ai-dreams-and-nightmares-in-sam-altman-s-openai-karen-hao/22156498&quot;&gt;for utopian and dystopian myths&lt;/a&gt; and &lt;a href=&quot;https://thecon.ai/&quot;&gt;cons,&lt;/a&gt; has created a semantic fog around AI that is counterproductive for spreading technical understanding, sometimes causing &lt;a href=&quot;https://www.theatlantic.com/culture/archive/2025/06/artificial-intelligence-illiteracy/683021/&quot;&gt;catastrophic consequences for the users&lt;/a&gt;. Recent studies have shown how the most recent trend within the AI community, “reasoning models”, creates an &lt;a href=&quot;https://substack.com/inbox/post/166103484&quot;&gt;illusion of thinking&lt;/a&gt;. At the same time, the go-to methods for evaluating Chatbots have turned out to be misleading, as shown in the &lt;a href=&quot;http://arxiv.org/abs/2504.20879&quot;&gt;Leaderboard Illusion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Could AI be (in) FAIR?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1293&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-b427a737.Bdkc9wXy_1VP1Ap.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4: LLMs tend to fail on reasoning tasks if they do not exactly match the training data.Those who sell the promise of redemption through AGI (Artificial General Intelligence*) are not interested in transparency or Open Science. Bringing FAIRness into the field, on the other hand, facilitates scientific progress. FAIR principles for AI must allow researchers to understand AI and enable them to make informed decisions about how to incorporate it into their research.&lt;/p&gt;
&lt;p&gt;The first step is to move away from referring to LLM-based, generative AI in a mystifying manner. Instead, researchers must discuss tangible tasks and techniques that can be evaluated objectively. Only this will allow us to define FAIR principles for AI: how can we make sure, LLM outputs can be f**ound by anyone, are &lt;strong&gt;a&lt;/strong&gt;ccessible through open protocols, &lt;strong&gt;i&lt;/strong&gt;nteroperable with other research data, and — perhaps most importantly — become &lt;strong&gt;r&lt;/strong&gt;eproducible?&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/could-ai-be-in-fair-4309ea06.BpquOFT5.jpg" medium="image"/><author>Carsten Schnober</author></item><item><title>Empirically evaluating privacy in machine learning I: Introduction</title><link>https://blog2.esciencecenter.nl/posts/2025-06-27---empirically-evaluating-privacy-in-machine-learning-i-introdu</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-06-27---empirically-evaluating-privacy-in-machine-learning-i-introdu</guid><description>&lt;p&gt;Research in the social and health sciences often relies on accessing data sourced from statistical agencies or healthcare organizations. Such data sets contain sensitive information, which requires restrictions on who can access the data. This can slow down not only scientific progress — if data were completely open, more researchers could investigate them — , but also the translation of progress to applications — for instance, machine learning models trained on medical data cannot easily be shared and re-used for personalized treatments.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning I: Introduction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;445&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-4e61e1c6.CszbPpVQ_Z14axac.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nci?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;National Cancer Institute&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Differential privacy is one technology that aims to solve this problem. Intuitively, it is a method that adds calibrated noise to the data, and so prevents a malevolent actor from learning sensitive attributes about any person in the underlying data. But because statistical noise makes statistical inference harder, there is an inherent trade-off between statistical utility and privacy — making differential privacy challenging to deploy in practice (&lt;a href=&quot;https://arxiv.org/abs/2406.12103&quot;&gt;Cummings &amp;#x26; Sarathy, 2023&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In addition, using differential privacy in machine learning has its own challenges. First, often it’s impossible to have reasonable privacy and utility at the same time. Second, differential privacy for machine learning makes strong assumptions about the capabilities of the malevolent actor. Third, implementing it in software is not straightforward, and there is evidence of bugs (&lt;a href=&quot;https://arxiv.org/abs/2304.06929&quot;&gt;Cummings et al, 2023&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2302.07956&quot;&gt;Nasr et al, 2023&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2303.00654&quot;&gt;Ponomareva et al, 2023&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;For this reason, empirically evaluating the privacy of machine learning models has become an important field of research. Privacy testing probes whether a trained machine learning model leaks sensitive information. It can be an important indicator for model developers and owners of sensitive data whether the privacy-preserving training mechanism can be trusted.&lt;/p&gt;
&lt;h3 id=&quot;the-plan-for-this-series-of-blog-posts&quot;&gt;The plan for this series of blog posts&lt;/h3&gt;
&lt;p&gt;Despite this, most resources in this topic are in research articles. The goal of this series of blog posts is to make the topic more accessible. We will build knowledge from the ground up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first blog posts introduces differential privacy, and gives some economic intuition. It is aimed at readers unfamiliar with differential privacy.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;second&lt;/a&gt; post explains how differential privacy can be interpreted from a perspective of statistical hypothesis testing. It is aimed at readers familiar with differential privacy and some concepts from statistics and machine learning.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-iii-functional-gaussian-differential-privacy-ccef13153e12&quot;&gt;third&lt;/a&gt; post discusses how the hypothesis testing perspective has been used to reformulate differential privacy with functional differential privacy and Gaussian differential privacy. It is aimed at readers interested in understanding privacy testing of machine learning.&lt;/li&gt;
&lt;li&gt;The fourth blog post discusses some recent papers that audit machine learning models and make use of Gaussian differential privacy. It is aimed at an audience similar to the third post.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning I: Introduction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-6ef4dfa5.C41y5zu0_Z2omCrL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@tobiastu?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Tobias Tullius&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-short-introduction-with-an-example&quot;&gt;A short introduction with an example&lt;/h2&gt;
&lt;p&gt;This section builds on &lt;a href=&quot;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf&quot;&gt;Dwork &amp;#x26; Roth (2013)&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;randomized-response&quot;&gt;Randomized response&lt;/h3&gt;
&lt;p&gt;Imagine a researcher wants to know the fraction of people that engage in a behavior that is illegal or socially not accepted — for instance, if they have income that they do not declare to the tax agency. The researcher runs a survey and asks people whether they have such income. Denote this behavior by the variable &lt;em&gt;X&lt;/em&gt;, and let’s say it can take values 0 or 1, where 1 indicates the person earns undeclared income, and 0 indicates the person does not.&lt;/p&gt;
&lt;p&gt;How can the researcher ensure that people are willing to share this sensitive information with them? To solve this problem, social scientists have developed a method called &lt;em&gt;randomized response&lt;/em&gt;, which gives survey participants the following instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flip a coin privately&lt;/li&gt;
&lt;li&gt;If it comes up heads, answer truthfully&lt;/li&gt;
&lt;li&gt;If it comes up tails, flip again. If the second flip is heads, answer with “1”, if the second flip is tails, answer with “0”.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach strikes a balance between privacy and statistical utility. First, privacy comes from plausible deniability — anyone can always plausibly claim not to engage in behavior *X, *independently of the answer they have given. Second, statistical accuracy comes from understanding how the noise was generated: because we know the response mechanism, we can infer the mean of &lt;em&gt;X&lt;/em&gt; in the population.&lt;/p&gt;
&lt;p&gt;In addition, in a more general setting, one could replace the first coin flip with a draw from a continuous random variable that takes values between 0 and 1, and instruct people to respond truthfully if the random variable is above some threshold &lt;code&gt;p&lt;/code&gt;. Varying &lt;code&gt;p&lt;/code&gt; amounts to varying the amount of noise we introduce to the response. On one hand, if &lt;code&gt;p=0&lt;/code&gt; , we have perfect accuracy but no privacy. If &lt;code&gt;p=1&lt;/code&gt; , we have perfect privacy but no accuracy.&lt;/p&gt;
&lt;h3 id=&quot;formal-definition-of-differential-privacy&quot;&gt;Formal definition of differential privacy&lt;/h3&gt;
&lt;p&gt;Define &lt;code&gt;db&lt;/code&gt; as a tabular database where each row corresponds to the data of one person. We call &lt;code&gt;db0&lt;/code&gt; and &lt;code&gt;db1&lt;/code&gt; neighboring databases when they differ by one record: they hold the exact same information, except for one person called Anne. For instance, it can be that Anne is not present in database &lt;code&gt;db0&lt;/code&gt; but in &lt;code&gt;db1&lt;/code&gt;, or that some column in Anne’s row is altered in &lt;code&gt;db1&lt;/code&gt; but not &lt;code&gt;db0&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Now, consider an algorithm &lt;code&gt;M&lt;/code&gt; that takes &lt;code&gt;db&lt;/code&gt; as input and creates some output. The algorithm is randomized because its outcome is not deterministic, but drawn from some distribution: The distribution of outcomes of the algorithm when fed with &lt;code&gt;db&lt;/code&gt; is denoted &lt;code&gt;M(db)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Such an algorithm is called &lt;code&gt;(epsilon,0)&lt;/code&gt; -differentially private** if the distribution of &lt;code&gt;M(db0)&lt;/code&gt; and the distribution &lt;code&gt;M(db1)&lt;/code&gt; are not too different from each other — formally, if the log odds of observing any outcome from &lt;code&gt;M(db0)&lt;/code&gt; vs &lt;code&gt;M(db1)&lt;/code&gt; are not larger than &lt;code&gt;epsilon&lt;/code&gt;. The &lt;code&gt;0&lt;/code&gt; in the &lt;code&gt;(epsilon,0)&lt;/code&gt; expression is a second parameter called &lt;code&gt;delta&lt;/code&gt;, which denotes the probability that this guarantee fails. It is typically a very small number that decreases in the size of the database &lt;code&gt;db&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;differential-privacy-of-randomized-response&quot;&gt;Differential Privacy of randomized response&lt;/h3&gt;
&lt;p&gt;This is an abstract definition, but we now show that randomized response satisfies differential privacy. To do so, we assume that the database &lt;code&gt;db&lt;/code&gt; only consists of one person — one row — , and one variable — the answer to the survey. We will relax this assumption later.&lt;/p&gt;
&lt;p&gt;Let &lt;code&gt;y_i = M(x_i)=1&lt;/code&gt; denoting that person &lt;code&gt;i &lt;/code&gt;with attribute &lt;code&gt;x_i&lt;/code&gt; answers 1 to the survey. Note that we only observe &lt;code&gt;y_i&lt;/code&gt; and &lt;code&gt;x_i&lt;/code&gt; is kept private. The randomized mechanism &lt;code&gt;M&lt;/code&gt; is the protocol that instructs people to flip coins and respond accordingly; &lt;code&gt;M&lt;/code&gt; generates a Bernoulli distribution of outcomes over neighboring databases with the following probabilities.&lt;/p&gt;
&lt;p&gt;We can construct neighboring databases by varying person &lt;code&gt;i&lt;/code&gt;‘s sensitive attribute &lt;code&gt;x_i&lt;/code&gt;: One input database has &lt;code&gt;x_i=1&lt;/code&gt;, and the other has &lt;code&gt;x_i=0&lt;/code&gt; . Running randomized response, what are the probabilities of &lt;code&gt;y_i=1&lt;/code&gt; given values for &lt;code&gt;x&lt;/code&gt; ? If &lt;code&gt;x_i=1&lt;/code&gt;, the person answers “1” with probability 0.75; if &lt;code&gt;x_i=0&lt;/code&gt; , the person answers “1” with probability 0.25. In other words, for person&lt;code&gt;i&lt;/code&gt; , the odds ratio for randomized response returning &lt;code&gt;y_i=1&lt;/code&gt; when having &lt;code&gt;x_i=1&lt;/code&gt; as opposed to having &lt;code&gt;x_i=0&lt;/code&gt; is &lt;code&gt;P[y_i=1|x_i=1]/P[y_i=1|x_i=0]=(3/4)/(1/4)=3&lt;/code&gt; . We can do a similar analysis for the outcome &lt;code&gt;y_i=0&lt;/code&gt; . Therefore, randomized response satisfies &lt;code&gt;(ln(3),0)&lt;/code&gt; differential privacy.&lt;/p&gt;
&lt;h3 id=&quot;economic-intuition&quot;&gt;Economic intuition&lt;/h3&gt;
&lt;p&gt;What does differential privacy promise? Let’s continue with the example of undeclared income. Suppose the researcher publishes the finding that 50% of people have some undeclared income. In response, the tax agency improves their enforcement, finds the people that do not declare income, and fines them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning I: Introduction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;473&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-c531cffb.iqzll6ry_ZFHth2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nypl?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;The New York Public Library&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pick one person, Bob, who is a tax dodger and who participated in the original survey of the researcher. Because of better enforcement, he gets caught by the tax office and needs to pay a fine. Does differential privacy guarantee that Bob is not being penalized for his behavior?&lt;/p&gt;
&lt;p&gt;No. Recall that differential privacy guarantees a similar distribution of outcomes under two neighboring databases. Releasing the survey result does impact Bob’s utility, but it does so independently of whether Bob is in the data or not: Even if Bob did not participate in the original survey, the tax office would have learned that many people do not declare their income, and started stronger enforcement, possibly leading to Bob being caught and fined.&lt;/p&gt;
&lt;p&gt;In other words, Bob’s expected utility is similar in the two scenarios considered, and no differential harm* is caused to Bob from releasing the survey results. This highlights a crucial aspect of differential privacy: &lt;strong&gt;what matters is the difference in outcomes from being in the database and from not being in the database&lt;/strong&gt;. Differential privacy makes no guarantees about the &lt;em&gt;level&lt;/em&gt; of utility of records in the database. And in consequence, “Statistical Inference is Not a Privacy Violation” (&lt;a href=&quot;https://differentialprivacy.org/inference-is-not-a-privacy-violation/&quot;&gt;Bun et. al., 2021&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;the-limits-of-this-example&quot;&gt;The limits of this example&lt;/h2&gt;
&lt;p&gt;Above, we made the simplifying assumption that a database consists only of one row and one column. In real life, databases have multiple rows and columns. That’s why it is common to define neighboring databases by taking two databases that vary exactly by one row, but are otherwise identical.&lt;/p&gt;
&lt;p&gt;But working with this definition, applying randomized response to the sensitive attribute &lt;code&gt;x_i&lt;/code&gt; is not enough anymore to guarantee the privacy of each person in the survey. For instance, if for each person, the researcher published the randomized response &lt;code&gt;y_i&lt;/code&gt; along with some of their true identifying information — for instance their address and age — , it would be possible for the tax office to prosecute people with &lt;code&gt;y_i=1&lt;/code&gt;, since they are more likely to have &lt;code&gt;x_i=1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead, the researcher needs to collect the real answers of all participants, decide which statistic to use for publishing the results, and apply a respective algorithm that satisfies differential privacy. But this then also requires that the survey participants trust the researcher that they will not use the sensitive data against them.&lt;/p&gt;
&lt;h3 id=&quot;differential-privacys-model-of-computation&quot;&gt;Differential privacy’s model of computation&lt;/h3&gt;
&lt;p&gt;These questions bring us to two important assumptions behind the theory of differential privacy. The first assumption is that there is a &lt;strong&gt;trusted curator&lt;/strong&gt; of the data — in our case the researcher that holds the individual survey responses are trusted to not leak the individual responses to the tax office.&lt;/p&gt;
&lt;p&gt;The second assumption is that only results to &lt;strong&gt;queries&lt;/strong&gt; are released — in our case, a relevant statistic of the survey such as “the fraction of people that have undeclared income”.&lt;/p&gt;
&lt;p&gt;Another important aspect of differential privacy is that multiple queries of the same data weaken privacy, even if each query itself satisfies differential privacy. For instance, suppose the researcher allowed the tax office to get multiple differentially private queries of the original data. Then, the tax office could gradually refine their queries and potentially identify a certain person that does not pay their taxes.&lt;/p&gt;
&lt;p&gt;This problem is known as &lt;strong&gt;composition&lt;/strong&gt;, and differential privacy provides mathematical tools to study how exactly privacy degrades with composition. We will touch on it again in the context of differentially private machine learning.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We used an example from social science research to illustrate how differential privacy can strike a trade-off between utility and privacy. The example helped illustrate the assumptions that are important for privacy guarantees. In the &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;next&lt;/a&gt; blog post, we will look at the hypothesis testing interpretation of differential privacy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Kody Moodley, Erik Tjong Kim Sang and Lourens Veen for commenting on and discussing an earlier draft.&lt;/p&gt;</description><pubDate>Fri, 27 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Research in the social and health sciences often relies on accessing data sourced from statistical agencies or healthcare organizations. Such data sets contain sensitive information, which requires restrictions on who can access the data. This can slow down not only scientific progress — if data were completely open, more researchers could investigate them — , but also the translation of progress to applications — for instance, machine learning models trained on medical data cannot easily be shared and re-used for personalized treatments.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning I: Introduction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;445&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-4e61e1c6.CszbPpVQ_Z14axac.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nci?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;National Cancer Institute&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Differential privacy is one technology that aims to solve this problem. Intuitively, it is a method that adds calibrated noise to the data, and so prevents a malevolent actor from learning sensitive attributes about any person in the underlying data. But because statistical noise makes statistical inference harder, there is an inherent trade-off between statistical utility and privacy — making differential privacy challenging to deploy in practice (&lt;a href=&quot;https://arxiv.org/abs/2406.12103&quot;&gt;Cummings &amp;#x26; Sarathy, 2023&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In addition, using differential privacy in machine learning has its own challenges. First, often it’s impossible to have reasonable privacy and utility at the same time. Second, differential privacy for machine learning makes strong assumptions about the capabilities of the malevolent actor. Third, implementing it in software is not straightforward, and there is evidence of bugs (&lt;a href=&quot;https://arxiv.org/abs/2304.06929&quot;&gt;Cummings et al, 2023&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2302.07956&quot;&gt;Nasr et al, 2023&lt;/a&gt;; &lt;a href=&quot;https://arxiv.org/abs/2303.00654&quot;&gt;Ponomareva et al, 2023&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;For this reason, empirically evaluating the privacy of machine learning models has become an important field of research. Privacy testing probes whether a trained machine learning model leaks sensitive information. It can be an important indicator for model developers and owners of sensitive data whether the privacy-preserving training mechanism can be trusted.&lt;/p&gt;
&lt;h3 id=&quot;the-plan-for-this-series-of-blog-posts&quot;&gt;The plan for this series of blog posts&lt;/h3&gt;
&lt;p&gt;Despite this, most resources in this topic are in research articles. The goal of this series of blog posts is to make the topic more accessible. We will build knowledge from the ground up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first blog posts introduces differential privacy, and gives some economic intuition. It is aimed at readers unfamiliar with differential privacy.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;second&lt;/a&gt; post explains how differential privacy can be interpreted from a perspective of statistical hypothesis testing. It is aimed at readers familiar with differential privacy and some concepts from statistics and machine learning.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-iii-functional-gaussian-differential-privacy-ccef13153e12&quot;&gt;third&lt;/a&gt; post discusses how the hypothesis testing perspective has been used to reformulate differential privacy with functional differential privacy and Gaussian differential privacy. It is aimed at readers interested in understanding privacy testing of machine learning.&lt;/li&gt;
&lt;li&gt;The fourth blog post discusses some recent papers that audit machine learning models and make use of Gaussian differential privacy. It is aimed at an audience similar to the third post.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning I: Introduction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-6ef4dfa5.C41y5zu0_Z2omCrL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@tobiastu?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Tobias Tullius&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-short-introduction-with-an-example&quot;&gt;A short introduction with an example&lt;/h2&gt;
&lt;p&gt;This section builds on &lt;a href=&quot;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf&quot;&gt;Dwork &amp;#x26; Roth (2013)&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;randomized-response&quot;&gt;Randomized response&lt;/h3&gt;
&lt;p&gt;Imagine a researcher wants to know the fraction of people that engage in a behavior that is illegal or socially not accepted — for instance, if they have income that they do not declare to the tax agency. The researcher runs a survey and asks people whether they have such income. Denote this behavior by the variable &lt;em&gt;X&lt;/em&gt;, and let’s say it can take values 0 or 1, where 1 indicates the person earns undeclared income, and 0 indicates the person does not.&lt;/p&gt;
&lt;p&gt;How can the researcher ensure that people are willing to share this sensitive information with them? To solve this problem, social scientists have developed a method called &lt;em&gt;randomized response&lt;/em&gt;, which gives survey participants the following instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flip a coin privately&lt;/li&gt;
&lt;li&gt;If it comes up heads, answer truthfully&lt;/li&gt;
&lt;li&gt;If it comes up tails, flip again. If the second flip is heads, answer with “1”, if the second flip is tails, answer with “0”.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach strikes a balance between privacy and statistical utility. First, privacy comes from plausible deniability — anyone can always plausibly claim not to engage in behavior *X, *independently of the answer they have given. Second, statistical accuracy comes from understanding how the noise was generated: because we know the response mechanism, we can infer the mean of &lt;em&gt;X&lt;/em&gt; in the population.&lt;/p&gt;
&lt;p&gt;In addition, in a more general setting, one could replace the first coin flip with a draw from a continuous random variable that takes values between 0 and 1, and instruct people to respond truthfully if the random variable is above some threshold &lt;code&gt;p&lt;/code&gt;. Varying &lt;code&gt;p&lt;/code&gt; amounts to varying the amount of noise we introduce to the response. On one hand, if &lt;code&gt;p=0&lt;/code&gt; , we have perfect accuracy but no privacy. If &lt;code&gt;p=1&lt;/code&gt; , we have perfect privacy but no accuracy.&lt;/p&gt;
&lt;h3 id=&quot;formal-definition-of-differential-privacy&quot;&gt;Formal definition of differential privacy&lt;/h3&gt;
&lt;p&gt;Define &lt;code&gt;db&lt;/code&gt; as a tabular database where each row corresponds to the data of one person. We call &lt;code&gt;db0&lt;/code&gt; and &lt;code&gt;db1&lt;/code&gt; neighboring databases when they differ by one record: they hold the exact same information, except for one person called Anne. For instance, it can be that Anne is not present in database &lt;code&gt;db0&lt;/code&gt; but in &lt;code&gt;db1&lt;/code&gt;, or that some column in Anne’s row is altered in &lt;code&gt;db1&lt;/code&gt; but not &lt;code&gt;db0&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Now, consider an algorithm &lt;code&gt;M&lt;/code&gt; that takes &lt;code&gt;db&lt;/code&gt; as input and creates some output. The algorithm is randomized because its outcome is not deterministic, but drawn from some distribution: The distribution of outcomes of the algorithm when fed with &lt;code&gt;db&lt;/code&gt; is denoted &lt;code&gt;M(db)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Such an algorithm is called &lt;code&gt;(epsilon,0)&lt;/code&gt; -differentially private** if the distribution of &lt;code&gt;M(db0)&lt;/code&gt; and the distribution &lt;code&gt;M(db1)&lt;/code&gt; are not too different from each other — formally, if the log odds of observing any outcome from &lt;code&gt;M(db0)&lt;/code&gt; vs &lt;code&gt;M(db1)&lt;/code&gt; are not larger than &lt;code&gt;epsilon&lt;/code&gt;. The &lt;code&gt;0&lt;/code&gt; in the &lt;code&gt;(epsilon,0)&lt;/code&gt; expression is a second parameter called &lt;code&gt;delta&lt;/code&gt;, which denotes the probability that this guarantee fails. It is typically a very small number that decreases in the size of the database &lt;code&gt;db&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;differential-privacy-of-randomized-response&quot;&gt;Differential Privacy of randomized response&lt;/h3&gt;
&lt;p&gt;This is an abstract definition, but we now show that randomized response satisfies differential privacy. To do so, we assume that the database &lt;code&gt;db&lt;/code&gt; only consists of one person — one row — , and one variable — the answer to the survey. We will relax this assumption later.&lt;/p&gt;
&lt;p&gt;Let &lt;code&gt;y_i = M(x_i)=1&lt;/code&gt; denoting that person &lt;code&gt;i &lt;/code&gt;with attribute &lt;code&gt;x_i&lt;/code&gt; answers 1 to the survey. Note that we only observe &lt;code&gt;y_i&lt;/code&gt; and &lt;code&gt;x_i&lt;/code&gt; is kept private. The randomized mechanism &lt;code&gt;M&lt;/code&gt; is the protocol that instructs people to flip coins and respond accordingly; &lt;code&gt;M&lt;/code&gt; generates a Bernoulli distribution of outcomes over neighboring databases with the following probabilities.&lt;/p&gt;
&lt;p&gt;We can construct neighboring databases by varying person &lt;code&gt;i&lt;/code&gt;‘s sensitive attribute &lt;code&gt;x_i&lt;/code&gt;: One input database has &lt;code&gt;x_i=1&lt;/code&gt;, and the other has &lt;code&gt;x_i=0&lt;/code&gt; . Running randomized response, what are the probabilities of &lt;code&gt;y_i=1&lt;/code&gt; given values for &lt;code&gt;x&lt;/code&gt; ? If &lt;code&gt;x_i=1&lt;/code&gt;, the person answers “1” with probability 0.75; if &lt;code&gt;x_i=0&lt;/code&gt; , the person answers “1” with probability 0.25. In other words, for person&lt;code&gt;i&lt;/code&gt; , the odds ratio for randomized response returning &lt;code&gt;y_i=1&lt;/code&gt; when having &lt;code&gt;x_i=1&lt;/code&gt; as opposed to having &lt;code&gt;x_i=0&lt;/code&gt; is &lt;code&gt;P[y_i=1|x_i=1]/P[y_i=1|x_i=0]=(3/4)/(1/4)=3&lt;/code&gt; . We can do a similar analysis for the outcome &lt;code&gt;y_i=0&lt;/code&gt; . Therefore, randomized response satisfies &lt;code&gt;(ln(3),0)&lt;/code&gt; differential privacy.&lt;/p&gt;
&lt;h3 id=&quot;economic-intuition&quot;&gt;Economic intuition&lt;/h3&gt;
&lt;p&gt;What does differential privacy promise? Let’s continue with the example of undeclared income. Suppose the researcher publishes the finding that 50% of people have some undeclared income. In response, the tax agency improves their enforcement, finds the people that do not declare income, and fines them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning I: Introduction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;473&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-c531cffb.iqzll6ry_ZFHth2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nypl?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;The New York Public Library&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pick one person, Bob, who is a tax dodger and who participated in the original survey of the researcher. Because of better enforcement, he gets caught by the tax office and needs to pay a fine. Does differential privacy guarantee that Bob is not being penalized for his behavior?&lt;/p&gt;
&lt;p&gt;No. Recall that differential privacy guarantees a similar distribution of outcomes under two neighboring databases. Releasing the survey result does impact Bob’s utility, but it does so independently of whether Bob is in the data or not: Even if Bob did not participate in the original survey, the tax office would have learned that many people do not declare their income, and started stronger enforcement, possibly leading to Bob being caught and fined.&lt;/p&gt;
&lt;p&gt;In other words, Bob’s expected utility is similar in the two scenarios considered, and no differential harm* is caused to Bob from releasing the survey results. This highlights a crucial aspect of differential privacy: &lt;strong&gt;what matters is the difference in outcomes from being in the database and from not being in the database&lt;/strong&gt;. Differential privacy makes no guarantees about the &lt;em&gt;level&lt;/em&gt; of utility of records in the database. And in consequence, “Statistical Inference is Not a Privacy Violation” (&lt;a href=&quot;https://differentialprivacy.org/inference-is-not-a-privacy-violation/&quot;&gt;Bun et. al., 2021&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;the-limits-of-this-example&quot;&gt;The limits of this example&lt;/h2&gt;
&lt;p&gt;Above, we made the simplifying assumption that a database consists only of one row and one column. In real life, databases have multiple rows and columns. That’s why it is common to define neighboring databases by taking two databases that vary exactly by one row, but are otherwise identical.&lt;/p&gt;
&lt;p&gt;But working with this definition, applying randomized response to the sensitive attribute &lt;code&gt;x_i&lt;/code&gt; is not enough anymore to guarantee the privacy of each person in the survey. For instance, if for each person, the researcher published the randomized response &lt;code&gt;y_i&lt;/code&gt; along with some of their true identifying information — for instance their address and age — , it would be possible for the tax office to prosecute people with &lt;code&gt;y_i=1&lt;/code&gt;, since they are more likely to have &lt;code&gt;x_i=1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead, the researcher needs to collect the real answers of all participants, decide which statistic to use for publishing the results, and apply a respective algorithm that satisfies differential privacy. But this then also requires that the survey participants trust the researcher that they will not use the sensitive data against them.&lt;/p&gt;
&lt;h3 id=&quot;differential-privacys-model-of-computation&quot;&gt;Differential privacy’s model of computation&lt;/h3&gt;
&lt;p&gt;These questions bring us to two important assumptions behind the theory of differential privacy. The first assumption is that there is a &lt;strong&gt;trusted curator&lt;/strong&gt; of the data — in our case the researcher that holds the individual survey responses are trusted to not leak the individual responses to the tax office.&lt;/p&gt;
&lt;p&gt;The second assumption is that only results to &lt;strong&gt;queries&lt;/strong&gt; are released — in our case, a relevant statistic of the survey such as “the fraction of people that have undeclared income”.&lt;/p&gt;
&lt;p&gt;Another important aspect of differential privacy is that multiple queries of the same data weaken privacy, even if each query itself satisfies differential privacy. For instance, suppose the researcher allowed the tax office to get multiple differentially private queries of the original data. Then, the tax office could gradually refine their queries and potentially identify a certain person that does not pay their taxes.&lt;/p&gt;
&lt;p&gt;This problem is known as &lt;strong&gt;composition&lt;/strong&gt;, and differential privacy provides mathematical tools to study how exactly privacy degrades with composition. We will touch on it again in the context of differentially private machine learning.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We used an example from social science research to illustrate how differential privacy can strike a trade-off between utility and privacy. The example helped illustrate the assumptions that are important for privacy guarantees. In the &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;next&lt;/a&gt; blog post, we will look at the hypothesis testing interpretation of differential privacy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Kody Moodley, Erik Tjong Kim Sang and Lourens Veen for commenting on and discussing an earlier draft.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-4e61e1c6.CszbPpVQ.jpg" medium="image"/><author>Flavio Hafner</author></item><item><title>Empirically evaluating privacy in machine learning II: Hypothesis testing</title><link>https://blog2.esciencecenter.nl/posts/2025-06-17---empirically-evaluating-privacy-in-machine-learning-ii-hypoth</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-06-17---empirically-evaluating-privacy-in-machine-learning-ii-hypoth</guid><description>&lt;p&gt;Using statistics to think like a hacker, so we can avoid them!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;348&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-597dd224.B0jnjMFF_1md9I8.webp&quot; srcset=&quot;&quot;&gt;
Image from page 182 of “Elements of statistics” (1954). Licensed under creative commons.This post is the second in a series on evaluating privacy in machine learning models (see first episode &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;here&lt;/a&gt;). It explains the hypothesis testing interpretation of differential privacy by showing how differential privacy constrains the success of any attacker in finding out about the underlying data.&lt;/p&gt;
&lt;p&gt;The post assumes readers are familiar with differential privacy and some concepts in statistics and machine learning. In addition, it keeps concepts such as an “input database” and a “data release” abstract. If you are unfamiliar with either of these terms, you can have a look at the &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;previous post&lt;/a&gt;. It introduces differential privacy and has a specific example for an input database and a data release.&lt;/p&gt;
&lt;h2 id=&quot;differential-privacy-through-the-lens-of-hypothesis-testing&quot;&gt;Differential privacy through the lens of hypothesis testing&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;first blog post&lt;/a&gt; of this series showed that differential privacy has adversarial thinking built-in: Leaking sensitive information may allow a malevolent actor to use the information to the disadvantage of a person in the database. In a differentially private mechanism, the more noise is added, the less any adversary can learn about any particular record in the database.&lt;/p&gt;
&lt;h3 id=&quot;adversarial-inference-as-a-hypothesis-test&quot;&gt;Adversarial inference as a hypothesis test&lt;/h3&gt;
&lt;p&gt;This intuition was formalized by &lt;a href=&quot;https://arxiv.org/abs/0811.2501&quot;&gt;Wasserman &amp;#x26; Zou (2009)&lt;/a&gt;. Imagine an adversary has access to a differentially private data release &lt;code&gt;Y&lt;/code&gt; from a tabular database &lt;code&gt;db&lt;/code&gt;. And suppose the adversary wants to find out if a particular person &lt;code&gt;i&lt;/code&gt; was part of the database &lt;code&gt;db&lt;/code&gt;. Define the neighboring databases &lt;code&gt;db0&lt;/code&gt; and &lt;code&gt;db1&lt;/code&gt;, where &lt;code&gt;i&lt;/code&gt; is only in &lt;code&gt;db1&lt;/code&gt; but not in &lt;code&gt;db0&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Then, the adversary faces the following hypothesis testing problem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;H0: &lt;code&gt;Y&lt;/code&gt; was drawn from &lt;code&gt;db0&lt;/code&gt;, so that &lt;code&gt;i&lt;/code&gt; was not in the input data for &lt;code&gt;Y&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;H1: &lt;code&gt;Y&lt;/code&gt; was drawn from &lt;code&gt;db1&lt;/code&gt;, so that &lt;code&gt;i&lt;/code&gt; was in the input data for &lt;code&gt;Y&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When seeing the data, the adversary needs to make an inference about the true state of &lt;code&gt;db&lt;/code&gt; , having seen only &lt;code&gt;Y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are four possible scenarios.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The adversary correctly predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db0&lt;/code&gt;. This is a true negative.&lt;/li&gt;
&lt;li&gt;The adversary correctly predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db1&lt;/code&gt;. This is a true positive.&lt;/li&gt;
&lt;li&gt;The adversary predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db0&lt;/code&gt;, but in truth it was based on &lt;code&gt;db1&lt;/code&gt;. This is a false negative.&lt;/li&gt;
&lt;li&gt;The adversary predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db1&lt;/code&gt;, but in truth it was based on &lt;code&gt;db0&lt;/code&gt;. This is a false positive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;deriving-the-roc-curve&quot;&gt;Deriving the ROC curve&lt;/h3&gt;
&lt;p&gt;How does the adversary make their inference? They need a decision rule that takes the observed data &lt;code&gt;Y&lt;/code&gt; and returns an output that is &lt;code&gt;db0&lt;/code&gt; or &lt;code&gt;db1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In a future blog post, we will be more specific on what such a rule can look like and how one can derive it. For now, we assume the adversary has the following decision rule: First, they have a trained logistic regression model that takes &lt;code&gt;Y&lt;/code&gt; as input and returns a score. Second, the adversary decides on a threshold: if the score is above the threshold, the decision rule returns &lt;code&gt;db1&lt;/code&gt;, and &lt;code&gt;db0&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;p&gt;In other words, the adversary rejects H0 in favor of H1 if the score is above the threshold. Then, lowering the threshold means rejecting H0 more often, and so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The adversary is more likely to detect cases when &lt;code&gt;Y&lt;/code&gt; is based on &lt;code&gt;db1&lt;/code&gt;. This means a higher true positive rate, which is good for the adversary.&lt;/li&gt;
&lt;li&gt;But the adversary is also more likely to predict that &lt;code&gt;Y&lt;/code&gt; is based on &lt;code&gt;db1&lt;/code&gt; when in truth it is based on &lt;code&gt;db0&lt;/code&gt;. This means a higher false positive rate, which is bad for the adversary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can visualize this trade-off with the &lt;a href=&quot;https://en.wikipedia.org/wiki/Receiver_operating_characteristic&quot;&gt;Receiver Operating Characteristic curve&lt;/a&gt;, or ROC curve:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;537&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-921b027b.XiBibI1p_ZysgiE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: The blue line is an ROC curve. The distinguishing between H0 and H1 becomes easier as the True Positive Rate increases and the False Positive Rate decreases, thus moving North-West n the figure.In the figure above, the blue line defines the trade-off between the False Positive Rate &lt;code&gt;FPR&lt;/code&gt; and the True Positive Rate &lt;code&gt;TPR&lt;/code&gt; for a given prediction model. Lowering the &lt;code&gt;FPR&lt;/code&gt; comes at the cost of a lower &lt;code&gt;TPR&lt;/code&gt;, and vice-versa.&lt;/p&gt;
&lt;p&gt;Moreover, the red arrow indicates the direction in which it becomes easier to distinguish between H0 and H1, meaning a lower &lt;code&gt;FPR&lt;/code&gt; and a higher &lt;code&gt;TPR&lt;/code&gt;: An ideal decision rule gives an &lt;code&gt;FPR&lt;/code&gt; of 0 and a &lt;code&gt;TPR&lt;/code&gt; of 1. On the other hand, the dotted line indicates the performance of a decision rule that randomly rejects or does not reject H0.&lt;/p&gt;
&lt;p&gt;The ROC curve is a standard tool in machine learning for binary classification — and from here it is only a few steps to visualizing how differential privacy restricts the amount of information an adversary can learn from a data release.&lt;/p&gt;
&lt;h3 id=&quot;flipping-the-roc-curve&quot;&gt;Flipping the ROC curve&lt;/h3&gt;
&lt;p&gt;To start, let’s flip the y-axis in the above figure, and recognize that &lt;code&gt;1-TPR&lt;/code&gt; is the False Negative Rate &lt;code&gt;FNR&lt;/code&gt;. Thus, we have a curve in the &lt;code&gt;FPR-FNR&lt;/code&gt; space:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;568&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-57b92446.C8NgN7dQ_ZPkyQT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: The blue line is an ROC’ curve, which is the ROC curve with a flipped y-axis. The hypothesis test gets easier as we move South-West.This figure shows the same information as the previous figure. Importantly, the hypothesis test is easier the closer the blue &lt;code&gt;ROC&lt;/code&gt; curve follows the two axes— in other words, the more convex the curve is.&lt;/p&gt;
&lt;h3 id=&quot;differential-privacy-puts-constraints-on-the-best-possible-roc-curve&quot;&gt;Differential privacy puts constraints on the best possible ROC curve**&lt;/h3&gt;
&lt;p&gt;Next, &lt;a href=&quot;https://arxiv.org/abs/1311.0776&quot;&gt;Kairouz et al (2015)&lt;/a&gt; show that if an algorithm satisfies &lt;code&gt;(epsilon, delta)&lt;/code&gt; differential privacy, then the adversary’s success in the hypothesis testing problem is bounded by a function of &lt;code&gt;epsilon&lt;/code&gt; and &lt;code&gt;delta&lt;/code&gt;. Specifically, this bound can be drawn in the &lt;code&gt;FPR-FNR&lt;/code&gt; space as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;540&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-281169dd.CpvFrWOn_Z2aqDrX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: The performance boundaries of a hypothesis test for two differentially private mechanisms: The blue is from a mechanism that is (epsilon1, delta) differentially private. The red is from a mechanism that is (epsilon2, delta) differentially private. The latter allows for a more convex ROC’ curve of the adversary, and therefore provides less privacy than the first mechanism.First, the blue line indicates the best possible performance any adversary can achieve in the hypothesis testing problem when the data satisfy &lt;code&gt;(epsilon1, delta)&lt;/code&gt; differential privacy. This means the &lt;code&gt;ROC&apos;&lt;/code&gt; curve from the previous figure, cannot cross the blue line — for any* adversarial decision rule. As before, the dotted line shows the performance of a decision rule that is completely random.&lt;/p&gt;
&lt;p&gt;Second, the figure illustrates that the parameter &lt;code&gt;delta&lt;/code&gt; defines the intercepts of the line on both the &lt;code&gt;FPR&lt;/code&gt; and &lt;code&gt;FNR&lt;/code&gt; axes. Intuitively, &lt;code&gt;delta&lt;/code&gt; defines an area where the adversary’s trade-off is not bounded — for instance, they can lower the &lt;code&gt;FNR&lt;/code&gt; without increasing the &lt;code&gt;FPR&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Lastly, the figure illustrates how &lt;code&gt;epsilon&lt;/code&gt; defines the slope of the constraint. Consider two mechanisms with equal &lt;code&gt;delta&lt;/code&gt; , but varying &lt;code&gt;epsilon&lt;/code&gt;parameters — denoted &lt;code&gt;epsilon1&lt;/code&gt; and &lt;code&gt;epsilon2&lt;/code&gt; with &lt;code&gt;epsilon1 &amp;#x26;lt; epsilon2&lt;/code&gt; . Then, we see that the constraint for &lt;code&gt;epsilon2&lt;/code&gt; is closer to the origin of the diagram — showing that a higher &lt;code&gt;epsilon&lt;/code&gt; means lower privacy and an easier business for an adversary to make inferences about the underlying data.&lt;/p&gt;
&lt;h2 id=&quot;what-do-we-learn&quot;&gt;What do we learn?&lt;/h2&gt;
&lt;p&gt;Starting from the ROC curve in machine learning, we saw how differential privacy restricts the success of an adversary trying to infer whether a certain record was part of a differentially private data release.&lt;/p&gt;
&lt;p&gt;In the next post, we will see how these insights lead to the notions of functional and Gaussian differential privacy, which are more handy to work with for certain analyses of privacy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Kody Moodley, Erik Tjong Kim Sang and Lourens Veen for commenting on and discussing an earlier draft.&lt;/p&gt;</description><pubDate>Tue, 17 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Using statistics to think like a hacker, so we can avoid them!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;348&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-597dd224.B0jnjMFF_1md9I8.webp&quot; srcset=&quot;&quot;&gt;
Image from page 182 of “Elements of statistics” (1954). Licensed under creative commons.This post is the second in a series on evaluating privacy in machine learning models (see first episode &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;here&lt;/a&gt;). It explains the hypothesis testing interpretation of differential privacy by showing how differential privacy constrains the success of any attacker in finding out about the underlying data.&lt;/p&gt;
&lt;p&gt;The post assumes readers are familiar with differential privacy and some concepts in statistics and machine learning. In addition, it keeps concepts such as an “input database” and a “data release” abstract. If you are unfamiliar with either of these terms, you can have a look at the &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;previous post&lt;/a&gt;. It introduces differential privacy and has a specific example for an input database and a data release.&lt;/p&gt;
&lt;h2 id=&quot;differential-privacy-through-the-lens-of-hypothesis-testing&quot;&gt;Differential privacy through the lens of hypothesis testing&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://blog2.esciencecenter.nl/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;first blog post&lt;/a&gt; of this series showed that differential privacy has adversarial thinking built-in: Leaking sensitive information may allow a malevolent actor to use the information to the disadvantage of a person in the database. In a differentially private mechanism, the more noise is added, the less any adversary can learn about any particular record in the database.&lt;/p&gt;
&lt;h3 id=&quot;adversarial-inference-as-a-hypothesis-test&quot;&gt;Adversarial inference as a hypothesis test&lt;/h3&gt;
&lt;p&gt;This intuition was formalized by &lt;a href=&quot;https://arxiv.org/abs/0811.2501&quot;&gt;Wasserman &amp;#x26; Zou (2009)&lt;/a&gt;. Imagine an adversary has access to a differentially private data release &lt;code&gt;Y&lt;/code&gt; from a tabular database &lt;code&gt;db&lt;/code&gt;. And suppose the adversary wants to find out if a particular person &lt;code&gt;i&lt;/code&gt; was part of the database &lt;code&gt;db&lt;/code&gt;. Define the neighboring databases &lt;code&gt;db0&lt;/code&gt; and &lt;code&gt;db1&lt;/code&gt;, where &lt;code&gt;i&lt;/code&gt; is only in &lt;code&gt;db1&lt;/code&gt; but not in &lt;code&gt;db0&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Then, the adversary faces the following hypothesis testing problem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;H0: &lt;code&gt;Y&lt;/code&gt; was drawn from &lt;code&gt;db0&lt;/code&gt;, so that &lt;code&gt;i&lt;/code&gt; was not in the input data for &lt;code&gt;Y&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;H1: &lt;code&gt;Y&lt;/code&gt; was drawn from &lt;code&gt;db1&lt;/code&gt;, so that &lt;code&gt;i&lt;/code&gt; was in the input data for &lt;code&gt;Y&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When seeing the data, the adversary needs to make an inference about the true state of &lt;code&gt;db&lt;/code&gt; , having seen only &lt;code&gt;Y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are four possible scenarios.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The adversary correctly predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db0&lt;/code&gt;. This is a true negative.&lt;/li&gt;
&lt;li&gt;The adversary correctly predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db1&lt;/code&gt;. This is a true positive.&lt;/li&gt;
&lt;li&gt;The adversary predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db0&lt;/code&gt;, but in truth it was based on &lt;code&gt;db1&lt;/code&gt;. This is a false negative.&lt;/li&gt;
&lt;li&gt;The adversary predicts that &lt;code&gt;Y&lt;/code&gt; was based on &lt;code&gt;db1&lt;/code&gt;, but in truth it was based on &lt;code&gt;db0&lt;/code&gt;. This is a false positive.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;deriving-the-roc-curve&quot;&gt;Deriving the ROC curve&lt;/h3&gt;
&lt;p&gt;How does the adversary make their inference? They need a decision rule that takes the observed data &lt;code&gt;Y&lt;/code&gt; and returns an output that is &lt;code&gt;db0&lt;/code&gt; or &lt;code&gt;db1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In a future blog post, we will be more specific on what such a rule can look like and how one can derive it. For now, we assume the adversary has the following decision rule: First, they have a trained logistic regression model that takes &lt;code&gt;Y&lt;/code&gt; as input and returns a score. Second, the adversary decides on a threshold: if the score is above the threshold, the decision rule returns &lt;code&gt;db1&lt;/code&gt;, and &lt;code&gt;db0&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;p&gt;In other words, the adversary rejects H0 in favor of H1 if the score is above the threshold. Then, lowering the threshold means rejecting H0 more often, and so:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The adversary is more likely to detect cases when &lt;code&gt;Y&lt;/code&gt; is based on &lt;code&gt;db1&lt;/code&gt;. This means a higher true positive rate, which is good for the adversary.&lt;/li&gt;
&lt;li&gt;But the adversary is also more likely to predict that &lt;code&gt;Y&lt;/code&gt; is based on &lt;code&gt;db1&lt;/code&gt; when in truth it is based on &lt;code&gt;db0&lt;/code&gt;. This means a higher false positive rate, which is bad for the adversary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can visualize this trade-off with the &lt;a href=&quot;https://en.wikipedia.org/wiki/Receiver_operating_characteristic&quot;&gt;Receiver Operating Characteristic curve&lt;/a&gt;, or ROC curve:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;537&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-921b027b.XiBibI1p_ZysgiE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: The blue line is an ROC curve. The distinguishing between H0 and H1 becomes easier as the True Positive Rate increases and the False Positive Rate decreases, thus moving North-West n the figure.In the figure above, the blue line defines the trade-off between the False Positive Rate &lt;code&gt;FPR&lt;/code&gt; and the True Positive Rate &lt;code&gt;TPR&lt;/code&gt; for a given prediction model. Lowering the &lt;code&gt;FPR&lt;/code&gt; comes at the cost of a lower &lt;code&gt;TPR&lt;/code&gt;, and vice-versa.&lt;/p&gt;
&lt;p&gt;Moreover, the red arrow indicates the direction in which it becomes easier to distinguish between H0 and H1, meaning a lower &lt;code&gt;FPR&lt;/code&gt; and a higher &lt;code&gt;TPR&lt;/code&gt;: An ideal decision rule gives an &lt;code&gt;FPR&lt;/code&gt; of 0 and a &lt;code&gt;TPR&lt;/code&gt; of 1. On the other hand, the dotted line indicates the performance of a decision rule that randomly rejects or does not reject H0.&lt;/p&gt;
&lt;p&gt;The ROC curve is a standard tool in machine learning for binary classification — and from here it is only a few steps to visualizing how differential privacy restricts the amount of information an adversary can learn from a data release.&lt;/p&gt;
&lt;h3 id=&quot;flipping-the-roc-curve&quot;&gt;Flipping the ROC curve&lt;/h3&gt;
&lt;p&gt;To start, let’s flip the y-axis in the above figure, and recognize that &lt;code&gt;1-TPR&lt;/code&gt; is the False Negative Rate &lt;code&gt;FNR&lt;/code&gt;. Thus, we have a curve in the &lt;code&gt;FPR-FNR&lt;/code&gt; space:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;568&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-57b92446.C8NgN7dQ_ZPkyQT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: The blue line is an ROC’ curve, which is the ROC curve with a flipped y-axis. The hypothesis test gets easier as we move South-West.This figure shows the same information as the previous figure. Importantly, the hypothesis test is easier the closer the blue &lt;code&gt;ROC&lt;/code&gt; curve follows the two axes— in other words, the more convex the curve is.&lt;/p&gt;
&lt;h3 id=&quot;differential-privacy-puts-constraints-on-the-best-possible-roc-curve&quot;&gt;Differential privacy puts constraints on the best possible ROC curve**&lt;/h3&gt;
&lt;p&gt;Next, &lt;a href=&quot;https://arxiv.org/abs/1311.0776&quot;&gt;Kairouz et al (2015)&lt;/a&gt; show that if an algorithm satisfies &lt;code&gt;(epsilon, delta)&lt;/code&gt; differential privacy, then the adversary’s success in the hypothesis testing problem is bounded by a function of &lt;code&gt;epsilon&lt;/code&gt; and &lt;code&gt;delta&lt;/code&gt;. Specifically, this bound can be drawn in the &lt;code&gt;FPR-FNR&lt;/code&gt; space as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning II: Hypothesis testing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;540&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-281169dd.CpvFrWOn_Z2aqDrX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: The performance boundaries of a hypothesis test for two differentially private mechanisms: The blue is from a mechanism that is (epsilon1, delta) differentially private. The red is from a mechanism that is (epsilon2, delta) differentially private. The latter allows for a more convex ROC’ curve of the adversary, and therefore provides less privacy than the first mechanism.First, the blue line indicates the best possible performance any adversary can achieve in the hypothesis testing problem when the data satisfy &lt;code&gt;(epsilon1, delta)&lt;/code&gt; differential privacy. This means the &lt;code&gt;ROC&apos;&lt;/code&gt; curve from the previous figure, cannot cross the blue line — for any* adversarial decision rule. As before, the dotted line shows the performance of a decision rule that is completely random.&lt;/p&gt;
&lt;p&gt;Second, the figure illustrates that the parameter &lt;code&gt;delta&lt;/code&gt; defines the intercepts of the line on both the &lt;code&gt;FPR&lt;/code&gt; and &lt;code&gt;FNR&lt;/code&gt; axes. Intuitively, &lt;code&gt;delta&lt;/code&gt; defines an area where the adversary’s trade-off is not bounded — for instance, they can lower the &lt;code&gt;FNR&lt;/code&gt; without increasing the &lt;code&gt;FPR&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Lastly, the figure illustrates how &lt;code&gt;epsilon&lt;/code&gt; defines the slope of the constraint. Consider two mechanisms with equal &lt;code&gt;delta&lt;/code&gt; , but varying &lt;code&gt;epsilon&lt;/code&gt;parameters — denoted &lt;code&gt;epsilon1&lt;/code&gt; and &lt;code&gt;epsilon2&lt;/code&gt; with &lt;code&gt;epsilon1 &amp;#x26;lt; epsilon2&lt;/code&gt; . Then, we see that the constraint for &lt;code&gt;epsilon2&lt;/code&gt; is closer to the origin of the diagram — showing that a higher &lt;code&gt;epsilon&lt;/code&gt; means lower privacy and an easier business for an adversary to make inferences about the underlying data.&lt;/p&gt;
&lt;h2 id=&quot;what-do-we-learn&quot;&gt;What do we learn?&lt;/h2&gt;
&lt;p&gt;Starting from the ROC curve in machine learning, we saw how differential privacy restricts the success of an adversary trying to infer whether a certain record was part of a differentially private data release.&lt;/p&gt;
&lt;p&gt;In the next post, we will see how these insights lead to the notions of functional and Gaussian differential privacy, which are more handy to work with for certain analyses of privacy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Kody Moodley, Erik Tjong Kim Sang and Lourens Veen for commenting on and discussing an earlier draft.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-921b027b.XiBibI1p.jpeg" medium="image"/><author>Flavio Hafner</author></item><item><title>Empirically evaluating privacy in machine learning III: functional &amp;amp; gaussian differential privacy</title><link>https://blog2.esciencecenter.nl/posts/2025-06-17---empirically-evaluating-privacy-in-machine-learning-iii-funct</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-06-17---empirically-evaluating-privacy-in-machine-learning-iii-funct</guid><description>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;Using statistics to think like a hacker, so we can avoid them!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;204&quot; height=&quot;300&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-6832bdd1.GsqkO5bw_TCw62.webp&quot; srcset=&quot;&quot;&gt;
The Greek letter lambda, symbol of functional programming.This post is the third in a series on differential privacy and machine learning (see here episodes &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;I&lt;/a&gt; and &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;II&lt;/a&gt;). It takes a big step towards understanding how to assess privacy properties of machine learning algorithms: It introduces functional and gaussian differential privacy as defined by &lt;a href=&quot;https://academic.oup.com/jrsssb/article/84/1/3/7056089&quot;&gt;Dong et al. (2022)&lt;/a&gt;. This definition helps reasoning about differential privacy in some contexts, and in particular it has been useful for recent work in auditing machine learning algorithms with differential privacy.&lt;/p&gt;
&lt;p&gt;When reading this post, the reader should be familiar with &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;the previous post&lt;/a&gt; in this series. That post showed that differential privacy constrains the success of an attacker in inferring whether a particular record was included in a differentially private data release.&lt;/p&gt;
&lt;h2 id=&quot;functional-differential-privacy&quot;&gt;Functional Differential Privacy&lt;/h2&gt;
&lt;h3 id=&quot;trade-off-functions&quot;&gt;Trade-off functions&lt;/h3&gt;
&lt;p&gt;So far, we have derived the boundary for the best possible performance of any adversary in the original case of &lt;code&gt;(epsilon,delta)&lt;/code&gt; differential privacy. It turns out this function is an instance of what Dong et al. (2022) define as a &lt;em&gt;trade-off function.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Remember that a differentially private mechanism &lt;code&gt;M&lt;/code&gt; induces two different distributions of data under the two competing hypotheses H0 and H1. A trade-off function &lt;code&gt;T(P,Q)(alpha)&lt;/code&gt; defines the difficulty in distinguishing the two distributions: it is defined over any two probability distributions &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt;, and tells us the lowest achievable type-II error rate &lt;code&gt;beta&lt;/code&gt; (= False Negative Rate &lt;code&gt;FNR&lt;/code&gt;) an adversary can achieve with a type-I error rate (= False Positive Rate &lt;code&gt;FPR&lt;/code&gt;) of at most &lt;code&gt;alpha&lt;/code&gt;. The higher this function, the higher the lowest achievable type-II error rate for any &lt;code&gt;alpha&lt;/code&gt;, thus the harder it is to distinguish the two distributions &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a concrete example, a trade-off function &lt;code&gt;TP(P,Q)(0.05)=0.1&lt;/code&gt; tells us that distinguishing &lt;code&gt;P&lt;/code&gt; from &lt;code&gt;Q&lt;/code&gt; with a type-I error of at most 0.05 cannot have a type-II error of less than 0.1.&lt;/p&gt;
&lt;p&gt;A trade-off function has the following mathematical properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It takes inputs &lt;code&gt;alpha&lt;/code&gt; that range from 0 to 1.&lt;/li&gt;
&lt;li&gt;It has domain &lt;code&gt;beta&lt;/code&gt; that range from 0 to 1.&lt;/li&gt;
&lt;li&gt;It is convex, continuous, non-increasing.&lt;/li&gt;
&lt;li&gt;For all &lt;code&gt;alpha&lt;/code&gt;, &lt;code&gt;beta&lt;/code&gt; lies on or below the line &lt;code&gt;1-alpha&lt;/code&gt;. The dotted line in figure 2 of &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;the previous blog post&lt;/a&gt; represents the line &lt;code&gt;1-alpha&lt;/code&gt; , indicating that the distributions &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt; are indistinguishable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;functional-differential-privacy-1&quot;&gt;Functional Differential Privacy&lt;/h3&gt;
&lt;p&gt;Instead with parameters &lt;code&gt;(epsilon, delta)&lt;/code&gt;, it is now possible to define differential privacy in terms of a function — and is thus called functional differential privacy.&lt;/p&gt;
&lt;p&gt;According to the definition, a mechanism &lt;code&gt;M&lt;/code&gt; is &lt;code&gt;f&lt;/code&gt;-differentially private if it creates, for all neighboring databases &lt;code&gt;db0&lt;/code&gt; and &lt;code&gt;db1&lt;/code&gt;, a trade-off function over &lt;code&gt;M(db0)&lt;/code&gt; and &lt;code&gt;M(db1)&lt;/code&gt; that is bounded by the trade-off function &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The definition is best illustrated with this figure from Dong et al (2022):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;361&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-741bba85.Djav_Y5I_Z13jbdU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: Functional differential privacy. The solid line is a trade-off function for &lt;code&gt;f&lt;/code&gt; differential privacy. Only the dashed line above the solid line satisfies f-differential privacy. Source: Dong et al (2022).The figure has the same x- and y-axes as the figures in the previous blog post: On the x-axis is the false positive rate, or type I error; on the y-axis is the false negative rate, or type II error.&lt;/p&gt;
&lt;p&gt;The solid line is the trade-off function &lt;code&gt;f&lt;/code&gt;. The other lines represent trade-off functions from differentially private mechanisms. Among them, only the dashed line that never crosses the solid line is &lt;code&gt;f&lt;/code&gt;-DP; the other lines do not always lie above the line defined by &lt;code&gt;f&lt;/code&gt;, and thus do not satisfy &lt;code&gt;f&lt;/code&gt;-differential privacy. For reference, the kinked line could have come from an &lt;code&gt;(epsilon, delta)&lt;/code&gt; -differentially private mechanism we discussed in the previous post.&lt;/p&gt;
&lt;h3 id=&quot;analyzing-composition&quot;&gt;Analyzing composition&lt;/h3&gt;
&lt;p&gt;A first advantage of functional differential privacy is that it makes it easier to analyze properties such as composition. Composition handles the question of how sequentially querying a dataset with a private mechanism impacts the overall privacy of the original dataset, after all queries are applied. As an example, take an analyst that sequentially queries a private dataset: they query the data with a private mechanism, explore the result, and query the data in a way that depends on the result of the first query. The question arises: how does this sequential and adaptive querying of the data degrade overall privacy? If the person is adversarial, they may try to refine the queries step by step until they found the answer to their question.&lt;/p&gt;
&lt;p&gt;A key result in Dong et al (2022) is that the &lt;code&gt;n&lt;/code&gt;-fold composition of mechanisms that are &lt;code&gt;f_i&lt;/code&gt; differentially private is &lt;code&gt;f*&lt;/code&gt; -differentially private. The precise level of privacy &lt;code&gt;f*&lt;/code&gt; depends on the privacy of each individual mechanism &lt;code&gt;f_i&lt;/code&gt;, and details can be found in section 3 of the paper. Importantly, this privacy bound is &lt;em&gt;tight&lt;/em&gt;: &lt;code&gt;f*&lt;/code&gt; is the most precise bound possible, informally meaning that we cannot move the function &lt;code&gt;f*&lt;/code&gt; further away from the x-y origin without making the &lt;code&gt;f*&lt;/code&gt; function crossing the trade-off function of the composed mechanism.&lt;/p&gt;
&lt;p&gt;This contrasts with &lt;code&gt;(epsilon,delta)&lt;/code&gt; differential privacy, where composition cannot be bounded as tightly.&lt;/p&gt;
&lt;h2 id=&quot;gaussian-differential-privacy&quot;&gt;Gaussian differential privacy&lt;/h2&gt;
&lt;p&gt;A special case of &lt;code&gt;f&lt;/code&gt;-differential privacy is Gaussian differential privacy. In this definition, the trade-off function is defined over two unit-variance normal distributions — one with mean 0, the other with mean &lt;code&gt;mu&lt;/code&gt;. In other words, under H0, the private mechanism generates a standard normal distribution, and under H1, it generates a normal distribution with mean &lt;code&gt;mu&lt;/code&gt; and variance 1. This is shown in the following figure:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;342&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-4c7801e8.BaRsgnrn_1ojanv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: Two normal distributions. Under H0, X is generated with mean 0 and standard deviation 1. Under H1, X is generated with mean mu and standard deviation 1.While this definition makes assumptions about the functional form of the distribution, it is very useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It summarizes the adversary’s trade-off between false positives and false negatives with a single parameter, &lt;code&gt;mu&lt;/code&gt;. This makes it easy to describe and interpret privacy guarantees.&lt;/li&gt;
&lt;li&gt;It characterizes the &lt;a href=&quot;https://en.wikipedia.org/wiki/Additive_noise_differential_privacy_mechanisms&quot;&gt;Gaussian mechanism&lt;/a&gt;, one commonly used differentially private mechanism.&lt;/li&gt;
&lt;li&gt;As shown by Dong et al (2022), Gaussian differential privacy is the asymptotic limit when &lt;code&gt;f&lt;/code&gt;-differentially private mechanisms are applied repeatedly on the same dataset. This is useful for analyzing complex algorithms that consist of multiple, adaptive and individually private steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;relation-to-machine-learning-with-differential-privacy&quot;&gt;Relation to machine learning with differential privacy&lt;/h3&gt;
&lt;p&gt;It is this last result that has made Gaussian differential privacy an important tool for analyzing differentially private machine learning.&lt;/p&gt;
&lt;p&gt;While we discuss it in detail in a future blog post, a commonly-used algorithm in deep learning is Differentially Private Stochastic Gradient Descent (DP-SGD). It is a method for sequentially updating parameters in a complex neural network: Instead of directly updating parameters with the gradients in each batch, noise is added and the contribution of individual samples in the batch is constrained. This avoids that any individual sample contributes too much to the parameter update, and can be shown to satisfy differential privacy.&lt;/p&gt;
&lt;p&gt;Since each parameter update is differentially private, one can view the trained model that results after many iterations as an algorithm that composes multiple differentially-private queries on the training data. Therefore, one can use Gaussian differential privacy to derive tight privacy bounds of the DP-SGD algorithm, which was not possible before.&lt;/p&gt;
&lt;h3 id=&quot;trade-off-function-for-gaussian-differential-privacy&quot;&gt;Trade-off function for Gaussian differential privacy&lt;/h3&gt;
&lt;p&gt;Building on the previous figure, the following figure illustrates the trade-off between false positives and false negatives under Gaussian differential privacy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;485&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-5f7a6d2f.Cp7wH9vX_1lELbs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: The likelihood-ratio test with normal distributions. If &lt;code&gt;X&lt;/code&gt; is higher than t, H0 is rejected in favor of H1, and vice-versa. The blue and green areas show the false positive and false negative rates, respectively.*The red line indicates a decision threshold. In particular, when conducting a hypothesis test, the [Neyman-Pearson lemma](&lt;a href=&quot;https://en.wikipedia.org/wiki/Neyman%E2%80%93&quot;&gt;https://en.wikipedia.org/wiki/Neyman%E2%80%93&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pearson_lemma) says that the best test statistic is the likelihood ratio test: Given a sample &lt;code&gt;X&lt;/code&gt;, the likelihood ratio test compares the likelihood that the sample was generated under H1 vs H0. From the figure above, we see that because the likelihood ratio of H1 vs H0 is increasing in &lt;code&gt;X&lt;/code&gt;, the null hypothesis is rejected if &lt;code&gt;X&lt;/code&gt; is above some threshold &lt;code&gt;t&lt;/code&gt;, indicated in red.&lt;/p&gt;
&lt;p&gt;Given the decision threshold, we can derive the False Positive and the False Negative rates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The False Positive Rate is defined for cases when H0 is falsely rejected. This happens if &lt;code&gt;X&amp;#x26;gt;t&lt;/code&gt; but &lt;code&gt;X&lt;/code&gt; was generated under H0. This probability is shown by the blue area.&lt;/li&gt;
&lt;li&gt;The False Negative Rate is defined for cases when H0 is falsely not rejected. This happens if &lt;code&gt;X&amp;#x26;lt;t&lt;/code&gt; but &lt;code&gt;X&lt;/code&gt; was generated under H1. This probability is shown by the green area.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that we have an analytical expression for both &lt;code&gt;FPR&lt;/code&gt; and &lt;code&gt;FNR&lt;/code&gt;, we can derive the trade-off function — the &lt;code&gt;FNR&lt;/code&gt; as a function of the &lt;code&gt;FPR&lt;/code&gt; and &lt;code&gt;mu&lt;/code&gt;: We rearrange the equation for the &lt;code&gt;FPR&lt;/code&gt; for &lt;code&gt;t&lt;/code&gt; and then plug in &lt;code&gt;t&lt;/code&gt; to the equation for &lt;code&gt;FNR&lt;/code&gt;. This yields the following trade-off function:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;474&quot; height=&quot;81&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-6e7a313f.C4N7fx_t_ZOLAMu.webp&quot; srcset=&quot;&quot;&gt;
Again, an illustration makes this easier to understand:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;576&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-f52a391d.BgttE1A6_Z2pT1W1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4: The trade-off function for Gaussian differential privacy. Phi is the standard normal distribution. alpha is the false positive rate. beta is the false negative rate. a lower mu means more privacy.First, for a given false positive rate &lt;code&gt;alpha&lt;/code&gt;, the false negative rate is at least as large as the the green area. In line with the definition of a trade-off function, lowering the false positive rate makes the red area smaller, and pulls the boundary of the green area to the right, thus increasing the false negative rate.&lt;/p&gt;
&lt;p&gt;Second, a lower &lt;code&gt;mu&lt;/code&gt; is associated with more privacy: as &lt;code&gt;mu&lt;/code&gt; decreases, it pulls the boundaries either the false positive or false negative rate (or both) closer to the center, thereby making it harder to distinguish between the distributions generated by H0 and H1.&lt;/p&gt;
&lt;p&gt;Dong et al (2022) also illustrate the trade-off function for some values of &lt;code&gt;mu&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;390&quot; height=&quot;383&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-7dce8395.CfSk5ZTr_22BloS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 5: Example trade-off functions for different values of mu. Source: Dong et al (2022).Here, for instance &lt;code&gt;G_{0.5}&lt;/code&gt; is the trade-off function for Gaussian differential privacy with &lt;code&gt;mu=0.5&lt;/code&gt; . Reasonable privacy is given for &lt;code&gt;mu=0.5&lt;/code&gt;, whereas for &lt;code&gt;mu=6&lt;/code&gt; the trade-off function almost coincides with the x- and y-axis, thus giving virtually no privacy.&lt;/p&gt;
&lt;h3 id=&quot;connections-between-definitions-of-privacy&quot;&gt;Connections between definitions of privacy&lt;/h3&gt;
&lt;p&gt;Another insight from Dong et al (2022) is that one can convert between&lt;code&gt;(epsilon, delta)&lt;/code&gt; -differential privacy and &lt;code&gt;f&lt;/code&gt;-differential privacy, and thus also Gaussian differential privacy. This is useful for two reasons. First, it means existing results from &lt;code&gt;(epsilon, delta)&lt;/code&gt;-differential privacy apply also to the definitions here. Second, for certain analyses, it is more convenient to work with one definition than the other, but results derived from one hold for the other. For instance, one can analyze composition more easily with &lt;code&gt;f&lt;/code&gt;-differential privacy, but analyze the privacy properties of mechanisms with data sub-sampling (discussed in the paper) more easily with &lt;code&gt;(epsilon,delta)&lt;/code&gt;-differential privacy.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We saw that the hypothesis testing interpretation gives rise to new notions of privacy such as &lt;code&gt;f&lt;/code&gt;- and Gaussian differential privacy, which are more handy to work with for certain analyses of privacy.&lt;/p&gt;
&lt;p&gt;We now have the foundations to understand privacy testing in machine learning. Both the hypothesis testing interpretation and Gaussian differential privacy have been useful to empirically check the privacy-preserving properties of machine learning algorithms. This will be covered in a future article.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Kody Moodley, Erik Tjong Kim Sang and Lourens Veen for commenting on and discussing an earlier draft.&lt;/p&gt;</description><pubDate>Tue, 17 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;Using statistics to think like a hacker, so we can avoid them!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;204&quot; height=&quot;300&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-6832bdd1.GsqkO5bw_TCw62.webp&quot; srcset=&quot;&quot;&gt;
The Greek letter lambda, symbol of functional programming.This post is the third in a series on differential privacy and machine learning (see here episodes &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-i-introduction-de5fe808d186&quot;&gt;I&lt;/a&gt; and &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;II&lt;/a&gt;). It takes a big step towards understanding how to assess privacy properties of machine learning algorithms: It introduces functional and gaussian differential privacy as defined by &lt;a href=&quot;https://academic.oup.com/jrsssb/article/84/1/3/7056089&quot;&gt;Dong et al. (2022)&lt;/a&gt;. This definition helps reasoning about differential privacy in some contexts, and in particular it has been useful for recent work in auditing machine learning algorithms with differential privacy.&lt;/p&gt;
&lt;p&gt;When reading this post, the reader should be familiar with &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;the previous post&lt;/a&gt; in this series. That post showed that differential privacy constrains the success of an attacker in inferring whether a particular record was included in a differentially private data release.&lt;/p&gt;
&lt;h2 id=&quot;functional-differential-privacy&quot;&gt;Functional Differential Privacy&lt;/h2&gt;
&lt;h3 id=&quot;trade-off-functions&quot;&gt;Trade-off functions&lt;/h3&gt;
&lt;p&gt;So far, we have derived the boundary for the best possible performance of any adversary in the original case of &lt;code&gt;(epsilon,delta)&lt;/code&gt; differential privacy. It turns out this function is an instance of what Dong et al. (2022) define as a &lt;em&gt;trade-off function.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Remember that a differentially private mechanism &lt;code&gt;M&lt;/code&gt; induces two different distributions of data under the two competing hypotheses H0 and H1. A trade-off function &lt;code&gt;T(P,Q)(alpha)&lt;/code&gt; defines the difficulty in distinguishing the two distributions: it is defined over any two probability distributions &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt;, and tells us the lowest achievable type-II error rate &lt;code&gt;beta&lt;/code&gt; (= False Negative Rate &lt;code&gt;FNR&lt;/code&gt;) an adversary can achieve with a type-I error rate (= False Positive Rate &lt;code&gt;FPR&lt;/code&gt;) of at most &lt;code&gt;alpha&lt;/code&gt;. The higher this function, the higher the lowest achievable type-II error rate for any &lt;code&gt;alpha&lt;/code&gt;, thus the harder it is to distinguish the two distributions &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a concrete example, a trade-off function &lt;code&gt;TP(P,Q)(0.05)=0.1&lt;/code&gt; tells us that distinguishing &lt;code&gt;P&lt;/code&gt; from &lt;code&gt;Q&lt;/code&gt; with a type-I error of at most 0.05 cannot have a type-II error of less than 0.1.&lt;/p&gt;
&lt;p&gt;A trade-off function has the following mathematical properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It takes inputs &lt;code&gt;alpha&lt;/code&gt; that range from 0 to 1.&lt;/li&gt;
&lt;li&gt;It has domain &lt;code&gt;beta&lt;/code&gt; that range from 0 to 1.&lt;/li&gt;
&lt;li&gt;It is convex, continuous, non-increasing.&lt;/li&gt;
&lt;li&gt;For all &lt;code&gt;alpha&lt;/code&gt;, &lt;code&gt;beta&lt;/code&gt; lies on or below the line &lt;code&gt;1-alpha&lt;/code&gt;. The dotted line in figure 2 of &lt;a href=&quot;https://medium.com/escience-center/empirically-evaluating-privacy-in-machine-learning-ii-hypothesis-testing-647806e2985c&quot;&gt;the previous blog post&lt;/a&gt; represents the line &lt;code&gt;1-alpha&lt;/code&gt; , indicating that the distributions &lt;code&gt;P&lt;/code&gt; and &lt;code&gt;Q&lt;/code&gt; are indistinguishable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;functional-differential-privacy-1&quot;&gt;Functional Differential Privacy&lt;/h3&gt;
&lt;p&gt;Instead with parameters &lt;code&gt;(epsilon, delta)&lt;/code&gt;, it is now possible to define differential privacy in terms of a function — and is thus called functional differential privacy.&lt;/p&gt;
&lt;p&gt;According to the definition, a mechanism &lt;code&gt;M&lt;/code&gt; is &lt;code&gt;f&lt;/code&gt;-differentially private if it creates, for all neighboring databases &lt;code&gt;db0&lt;/code&gt; and &lt;code&gt;db1&lt;/code&gt;, a trade-off function over &lt;code&gt;M(db0)&lt;/code&gt; and &lt;code&gt;M(db1)&lt;/code&gt; that is bounded by the trade-off function &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The definition is best illustrated with this figure from Dong et al (2022):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;361&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-741bba85.Djav_Y5I_Z13jbdU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: Functional differential privacy. The solid line is a trade-off function for &lt;code&gt;f&lt;/code&gt; differential privacy. Only the dashed line above the solid line satisfies f-differential privacy. Source: Dong et al (2022).The figure has the same x- and y-axes as the figures in the previous blog post: On the x-axis is the false positive rate, or type I error; on the y-axis is the false negative rate, or type II error.&lt;/p&gt;
&lt;p&gt;The solid line is the trade-off function &lt;code&gt;f&lt;/code&gt;. The other lines represent trade-off functions from differentially private mechanisms. Among them, only the dashed line that never crosses the solid line is &lt;code&gt;f&lt;/code&gt;-DP; the other lines do not always lie above the line defined by &lt;code&gt;f&lt;/code&gt;, and thus do not satisfy &lt;code&gt;f&lt;/code&gt;-differential privacy. For reference, the kinked line could have come from an &lt;code&gt;(epsilon, delta)&lt;/code&gt; -differentially private mechanism we discussed in the previous post.&lt;/p&gt;
&lt;h3 id=&quot;analyzing-composition&quot;&gt;Analyzing composition&lt;/h3&gt;
&lt;p&gt;A first advantage of functional differential privacy is that it makes it easier to analyze properties such as composition. Composition handles the question of how sequentially querying a dataset with a private mechanism impacts the overall privacy of the original dataset, after all queries are applied. As an example, take an analyst that sequentially queries a private dataset: they query the data with a private mechanism, explore the result, and query the data in a way that depends on the result of the first query. The question arises: how does this sequential and adaptive querying of the data degrade overall privacy? If the person is adversarial, they may try to refine the queries step by step until they found the answer to their question.&lt;/p&gt;
&lt;p&gt;A key result in Dong et al (2022) is that the &lt;code&gt;n&lt;/code&gt;-fold composition of mechanisms that are &lt;code&gt;f_i&lt;/code&gt; differentially private is &lt;code&gt;f*&lt;/code&gt; -differentially private. The precise level of privacy &lt;code&gt;f*&lt;/code&gt; depends on the privacy of each individual mechanism &lt;code&gt;f_i&lt;/code&gt;, and details can be found in section 3 of the paper. Importantly, this privacy bound is &lt;em&gt;tight&lt;/em&gt;: &lt;code&gt;f*&lt;/code&gt; is the most precise bound possible, informally meaning that we cannot move the function &lt;code&gt;f*&lt;/code&gt; further away from the x-y origin without making the &lt;code&gt;f*&lt;/code&gt; function crossing the trade-off function of the composed mechanism.&lt;/p&gt;
&lt;p&gt;This contrasts with &lt;code&gt;(epsilon,delta)&lt;/code&gt; differential privacy, where composition cannot be bounded as tightly.&lt;/p&gt;
&lt;h2 id=&quot;gaussian-differential-privacy&quot;&gt;Gaussian differential privacy&lt;/h2&gt;
&lt;p&gt;A special case of &lt;code&gt;f&lt;/code&gt;-differential privacy is Gaussian differential privacy. In this definition, the trade-off function is defined over two unit-variance normal distributions — one with mean 0, the other with mean &lt;code&gt;mu&lt;/code&gt;. In other words, under H0, the private mechanism generates a standard normal distribution, and under H1, it generates a normal distribution with mean &lt;code&gt;mu&lt;/code&gt; and variance 1. This is shown in the following figure:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;342&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-4c7801e8.BaRsgnrn_1ojanv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: Two normal distributions. Under H0, X is generated with mean 0 and standard deviation 1. Under H1, X is generated with mean mu and standard deviation 1.While this definition makes assumptions about the functional form of the distribution, it is very useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It summarizes the adversary’s trade-off between false positives and false negatives with a single parameter, &lt;code&gt;mu&lt;/code&gt;. This makes it easy to describe and interpret privacy guarantees.&lt;/li&gt;
&lt;li&gt;It characterizes the &lt;a href=&quot;https://en.wikipedia.org/wiki/Additive_noise_differential_privacy_mechanisms&quot;&gt;Gaussian mechanism&lt;/a&gt;, one commonly used differentially private mechanism.&lt;/li&gt;
&lt;li&gt;As shown by Dong et al (2022), Gaussian differential privacy is the asymptotic limit when &lt;code&gt;f&lt;/code&gt;-differentially private mechanisms are applied repeatedly on the same dataset. This is useful for analyzing complex algorithms that consist of multiple, adaptive and individually private steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;relation-to-machine-learning-with-differential-privacy&quot;&gt;Relation to machine learning with differential privacy&lt;/h3&gt;
&lt;p&gt;It is this last result that has made Gaussian differential privacy an important tool for analyzing differentially private machine learning.&lt;/p&gt;
&lt;p&gt;While we discuss it in detail in a future blog post, a commonly-used algorithm in deep learning is Differentially Private Stochastic Gradient Descent (DP-SGD). It is a method for sequentially updating parameters in a complex neural network: Instead of directly updating parameters with the gradients in each batch, noise is added and the contribution of individual samples in the batch is constrained. This avoids that any individual sample contributes too much to the parameter update, and can be shown to satisfy differential privacy.&lt;/p&gt;
&lt;p&gt;Since each parameter update is differentially private, one can view the trained model that results after many iterations as an algorithm that composes multiple differentially-private queries on the training data. Therefore, one can use Gaussian differential privacy to derive tight privacy bounds of the DP-SGD algorithm, which was not possible before.&lt;/p&gt;
&lt;h3 id=&quot;trade-off-function-for-gaussian-differential-privacy&quot;&gt;Trade-off function for Gaussian differential privacy&lt;/h3&gt;
&lt;p&gt;Building on the previous figure, the following figure illustrates the trade-off between false positives and false negatives under Gaussian differential privacy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;485&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-5f7a6d2f.Cp7wH9vX_1lELbs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: The likelihood-ratio test with normal distributions. If &lt;code&gt;X&lt;/code&gt; is higher than t, H0 is rejected in favor of H1, and vice-versa. The blue and green areas show the false positive and false negative rates, respectively.*The red line indicates a decision threshold. In particular, when conducting a hypothesis test, the [Neyman-Pearson lemma](&lt;a href=&quot;https://en.wikipedia.org/wiki/Neyman%E2%80%93&quot;&gt;https://en.wikipedia.org/wiki/Neyman%E2%80%93&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pearson_lemma) says that the best test statistic is the likelihood ratio test: Given a sample &lt;code&gt;X&lt;/code&gt;, the likelihood ratio test compares the likelihood that the sample was generated under H1 vs H0. From the figure above, we see that because the likelihood ratio of H1 vs H0 is increasing in &lt;code&gt;X&lt;/code&gt;, the null hypothesis is rejected if &lt;code&gt;X&lt;/code&gt; is above some threshold &lt;code&gt;t&lt;/code&gt;, indicated in red.&lt;/p&gt;
&lt;p&gt;Given the decision threshold, we can derive the False Positive and the False Negative rates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The False Positive Rate is defined for cases when H0 is falsely rejected. This happens if &lt;code&gt;X&amp;#x26;gt;t&lt;/code&gt; but &lt;code&gt;X&lt;/code&gt; was generated under H0. This probability is shown by the blue area.&lt;/li&gt;
&lt;li&gt;The False Negative Rate is defined for cases when H0 is falsely not rejected. This happens if &lt;code&gt;X&amp;#x26;lt;t&lt;/code&gt; but &lt;code&gt;X&lt;/code&gt; was generated under H1. This probability is shown by the green area.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that we have an analytical expression for both &lt;code&gt;FPR&lt;/code&gt; and &lt;code&gt;FNR&lt;/code&gt;, we can derive the trade-off function — the &lt;code&gt;FNR&lt;/code&gt; as a function of the &lt;code&gt;FPR&lt;/code&gt; and &lt;code&gt;mu&lt;/code&gt;: We rearrange the equation for the &lt;code&gt;FPR&lt;/code&gt; for &lt;code&gt;t&lt;/code&gt; and then plug in &lt;code&gt;t&lt;/code&gt; to the equation for &lt;code&gt;FNR&lt;/code&gt;. This yields the following trade-off function:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;474&quot; height=&quot;81&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-6e7a313f.C4N7fx_t_ZOLAMu.webp&quot; srcset=&quot;&quot;&gt;
Again, an illustration makes this easier to understand:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;576&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-f52a391d.BgttE1A6_Z2pT1W1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4: The trade-off function for Gaussian differential privacy. Phi is the standard normal distribution. alpha is the false positive rate. beta is the false negative rate. a lower mu means more privacy.First, for a given false positive rate &lt;code&gt;alpha&lt;/code&gt;, the false negative rate is at least as large as the the green area. In line with the definition of a trade-off function, lowering the false positive rate makes the red area smaller, and pulls the boundary of the green area to the right, thus increasing the false negative rate.&lt;/p&gt;
&lt;p&gt;Second, a lower &lt;code&gt;mu&lt;/code&gt; is associated with more privacy: as &lt;code&gt;mu&lt;/code&gt; decreases, it pulls the boundaries either the false positive or false negative rate (or both) closer to the center, thereby making it harder to distinguish between the distributions generated by H0 and H1.&lt;/p&gt;
&lt;p&gt;Dong et al (2022) also illustrate the trade-off function for some values of &lt;code&gt;mu&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Empirically evaluating privacy in machine learning III: functional &amp;amp;#x26; gaussian differential privacy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;390&quot; height=&quot;383&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-7dce8395.CfSk5ZTr_22BloS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 5: Example trade-off functions for different values of mu. Source: Dong et al (2022).Here, for instance &lt;code&gt;G_{0.5}&lt;/code&gt; is the trade-off function for Gaussian differential privacy with &lt;code&gt;mu=0.5&lt;/code&gt; . Reasonable privacy is given for &lt;code&gt;mu=0.5&lt;/code&gt;, whereas for &lt;code&gt;mu=6&lt;/code&gt; the trade-off function almost coincides with the x- and y-axis, thus giving virtually no privacy.&lt;/p&gt;
&lt;h3 id=&quot;connections-between-definitions-of-privacy&quot;&gt;Connections between definitions of privacy&lt;/h3&gt;
&lt;p&gt;Another insight from Dong et al (2022) is that one can convert between&lt;code&gt;(epsilon, delta)&lt;/code&gt; -differential privacy and &lt;code&gt;f&lt;/code&gt;-differential privacy, and thus also Gaussian differential privacy. This is useful for two reasons. First, it means existing results from &lt;code&gt;(epsilon, delta)&lt;/code&gt;-differential privacy apply also to the definitions here. Second, for certain analyses, it is more convenient to work with one definition than the other, but results derived from one hold for the other. For instance, one can analyze composition more easily with &lt;code&gt;f&lt;/code&gt;-differential privacy, but analyze the privacy properties of mechanisms with data sub-sampling (discussed in the paper) more easily with &lt;code&gt;(epsilon,delta)&lt;/code&gt;-differential privacy.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We saw that the hypothesis testing interpretation gives rise to new notions of privacy such as &lt;code&gt;f&lt;/code&gt;- and Gaussian differential privacy, which are more handy to work with for certain analyses of privacy.&lt;/p&gt;
&lt;p&gt;We now have the foundations to understand privacy testing in machine learning. Both the hypothesis testing interpretation and Gaussian differential privacy have been useful to empirically check the privacy-preserving properties of machine learning algorithms. This will be covered in a future article.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Kody Moodley, Erik Tjong Kim Sang and Lourens Veen for commenting on and discussing an earlier draft.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/empirically-evaluating-privacy-in-machin-741bba85.Djav_Y5I.png" medium="image"/><author>Flavio Hafner</author></item><item><title>Scientific Community Building through Workshops: the NPLinker eScience experience</title><link>https://blog2.esciencecenter.nl/posts/2025-05-20---scientific-community-building-through-workshops-the-nplinker</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-05-20---scientific-community-building-through-workshops-the-nplinker</guid><description>&lt;p&gt;&lt;em&gt;This blog post is written by Wageningen University &amp;#x26; Research Assistant Professor &lt;em&gt;&lt;a href=&quot;https://www.linkedin.com/in/jjjvanderhooft/&quot;&gt;&lt;em&gt;Justin van der Hooft&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, who participates in the Open eScience Call 2021. His project “A community-supported workflow connecting microbial genes and organisms to their molecular products” aims to facilitate the finding of novel bio-active molecules from nature. It does so by enabling the integrated use of various omics data types.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Want to know more of what Justin’s team is doing?! Check his team’s &lt;em&gt;&lt;a href=&quot;https://vdhooftcompmet.github.io/&quot;&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-0741307b.Cd4Yi41s_Z2tvJya.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/pt-br/@vollkornapfel?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Adrian Lange&lt;/a&gt; on [Unsplash](&lt;a href=&quot;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&quot;&gt;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Text)&lt;/p&gt;
&lt;p&gt;Motivation for the workshop**&lt;/p&gt;
&lt;p&gt;Nature is still full of unknown chemistry with possible beneficial properties such as anti-inflammatory or antibiotic ones. Over the last decade, increasing numbers of genome sequences and metabolomics profiles have become available in public resources. Hence, the combination of genome mining and metabolome mining has gained traction in accelerating natural product discovery by linking biosynthetic genes to molecular scaffolds and structures, and associating producers with their products. However, effective integrative omics mining has proven challenging due to the various data types and tools involved. In 2021, &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008920&quot;&gt;NPLinker&lt;/a&gt; was proposed as a solution to streamline many aspects of integrative omics, so that researchers can focus on analyzing the possible matches between genes and molecules. Over the last years, the Open eScience Call project has further build on this solution to create &lt;a href=&quot;https://research-software-directory.org/software/nplinker&quot;&gt;a framework for paired omics analyses&lt;/a&gt;. To gain experience with the NPLinker framework and build an integrative omics mining community of talented, driven early-career researchers and knowledgeable instructors, Marnix Medema and I organized this second NPLinker-eScience workshop in Wageningen, the Netherlands.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Outline of the workshop&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;During this second workshop in a series of two, we again aimed to bring together researchers interested in integrative omics analysis, spanning various career stages, computational or the application-focused backgrounds, and diverse organisms they work on. Following a selection process, 38 participants were selected to come to Wageningen to learn about analyzing genomes and metabolomes, and to get an outlook towards the integration of the two. The general aims of &lt;a href=&quot;https://www.wur.nl/en/research-results/chair-groups/plant-sciences/bioinformatics/teaching/nplinker_workshop.htm&quot;&gt;the workshop&lt;/a&gt; were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce the NPLinker framework both conceptually and hands-on&lt;/li&gt;
&lt;li&gt;Educate and train natural product researchers and other interested scientists&lt;/li&gt;
&lt;li&gt;Extend the Integrative Omics Mining Community&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The workshop intended learning outcomes were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand the concepts of and motivations for paired omics analysis&lt;/li&gt;
&lt;li&gt;Apply NPLinker to a public paired omics dataset&lt;/li&gt;
&lt;li&gt;Understand the NPLinker scoring&lt;/li&gt;
&lt;li&gt;Evaluate NPLinker outcome in the web app&lt;/li&gt;
&lt;li&gt;Understand how to contribute to the NPLinker code base&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To stimulate networking amongst the participants and instructors, several measures were put in place: extended coffee and tea breaks, the opportunity to present a poster, and a social mixer at the start to get to know each other. Furthermore, Marnix and I organized a symposium on Wednesday to highlight exciting developments in genome mining, metabolome mining, integrative omics mining, and the reuse of public omics data. We are grateful for the financial support from the eScience Center, which helped to make the workshop affordable for participants from across the globe through a travel reimbursement scheme and enabled the participation of three international instructors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;669&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-0bf0eb4f.CUwTRxyS_Z85FHB.webp&quot; srcset=&quot;&quot;&gt;
All 38 participants from across the globe together with the instructors in front of the &lt;a href=&quot;https://www.wur.nl/en/location/omnia-2.htm&quot;&gt;Omnia building&lt;/a&gt; at the &lt;a href=&quot;https://www.wur.nl/en.htm&quot;&gt;Wageningen University &amp;#x26; Research&lt;/a&gt; campus.&lt;/p&gt;
&lt;p&gt;I am increasingly aware of how integrative omics mining brings together different disciplines — what’s in a name, one could say. Furthermore, the field connects both researchers using the omics tools and developers working on them. We intentionally invited participants from these two groups and various disciplines to foster connections and collectively gain experience with the latest developments in the field. One key insight is that the fields is moving rapidly: only two years ago, we explained the latest in genome mining and metabolome mining, and during this workshop, versions 2 of BiG-SCAPE and GNPS were on the menu, replacing the previous versions. From a user perspective, this means staying up-to-date with how to use these tools effectively is key to remain on top of the latest possibilities in omics mining. From a developer perspective, it is important to build integrative tools like NPLinker in a way that can keep pace with the fast-evolving omics landscape. Another key insight is that, given the diverse backgrounds of participants, it is challenging to fully cater everyone’s needs. Striking the right balance between fixed program components and more flexible ones may help–allowing the explanation and demonstration of concepts or tools to be targeted based on participants’ needs. A final key insight is that promoting the exchange of knowledge and expertise in between participants is crucial, as it accelerates the uptake of new skills and information and helps form the bonds that create a scientific community.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;679&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-ef101463.nn9ZIVYM_nutVJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;677&quot; height=&quot;510&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-fe492552.DR1a_7tq_2uqmG7.webp&quot; srcset=&quot;&quot;&gt;
Participants have been working hands-on with BiG-SCAPE, GNPS, and NPLinker during the workshop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Access Materials&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A tangible outcome of the workshop for the broader community is that the instructors all made as much as possible &lt;a href=&quot;https://doi.org/10.5281/zenodo.15281967&quot;&gt;the materials available under an open access license&lt;/a&gt;! I hope this initiative will help to further foster the teaching of the future generation of omics miners, support the development of educational resources for genome mining, metabolomics, and metabolome mining, and promote discussions and integration between the fields of genome mining and metabolome mining.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-a548f678.DscDT-pC_Z1pHYGC.webp&quot; srcset=&quot;&quot;&gt;
With huge thanks to all the NPLinker eScience Workshop instructors who came from across the globe to Wageningen to teach the participants many facets of integrative omics mining.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Personal reflection&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Altogether, I am happy that all participants and instructors enjoyed the workshop and gained something valuable from it. I am very pleased that everyone had a good time and that the location and catering was appreciated. Furthermore, it was great to organize the symposium with Marnix Medema that celebrated the work lustra of our teams in computational genomics (1o years) and metabolomics (5 years). Not only did we invite keynote speakers–Pieter Dorrestein, Tilmann Weber, and Margherita Sosio–but we also invited three workshop participants to showcase their work in a flash talk. In case you are curious, you can watch it back &lt;a href=&quot;https://wur.yuja.com/V/Video?v=885970&amp;#x26;node=4776818&amp;#x26;a=66183860&quot;&gt;here&lt;/a&gt;. I found it nice to read in the evaluations how the participants liked to see each others’ posters during the breaks, and how they liked the flash talks during the symposium.&lt;/p&gt;
&lt;p&gt;If there is one thing I would have changed looking back at the event, it would be to organize more structured parallel sessions to dive deeper into the application and development of NPLinker, for example by using two separate rooms and dividing participants and instructors accordingly. This would have allowed both groups (users and developers) to discuss their ideas and challenges in greater detail, without the feeling of disturbing each other.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-22f93410.DbJUW8l-_ZDPVU9.webp&quot; srcset=&quot;&quot;&gt;
Community building during the workshop dinner!&lt;/p&gt;
&lt;p&gt;What I really liked were the workshop keynotes–thanks again to Kate Duncan for setting the scene on Monday, to Margherita Sosio for showcasing how omics mining is applied in an industrial setting and how the Molecules Gateway operates, and to Kumar Saurabh Singh for sharing his perspective on multi-omics analyses. Further, thanks again to the eScience Center for supporting this workshop series, and to the Omnia and Orion teams for their support and efforts before and during the week. A big thank-you as well to Maria Augustijn and Marie-José van Iersel for their support in organizing various aspects of the workshop and symposium. Thanks to Marnix for your support and being co-organizer of this event. And finally, many thanks to all the participants for their open and constructive attitude during the workshop — much appreciated!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-a3b95cc3.C5BiktrF_ZyC2x6.webp&quot; srcset=&quot;&quot;&gt;
Marnix Medema (right) and myself (left) during the symposium we organized.&lt;/p&gt;
&lt;p&gt;Whilst this was the last workshop in a series of two, I hope to see the integrative omics community together on future occasions!&lt;/p&gt;</description><pubDate>Tue, 20 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This blog post is written by Wageningen University &amp;#x26; Research Assistant Professor &lt;em&gt;&lt;a href=&quot;https://www.linkedin.com/in/jjjvanderhooft/&quot;&gt;&lt;em&gt;Justin van der Hooft&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, who participates in the Open eScience Call 2021. His project “A community-supported workflow connecting microbial genes and organisms to their molecular products” aims to facilitate the finding of novel bio-active molecules from nature. It does so by enabling the integrated use of various omics data types.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Want to know more of what Justin’s team is doing?! Check his team’s &lt;em&gt;&lt;a href=&quot;https://vdhooftcompmet.github.io/&quot;&gt;&lt;em&gt;website&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-0741307b.Cd4Yi41s_Z2tvJya.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/pt-br/@vollkornapfel?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Adrian Lange&lt;/a&gt; on [Unsplash](&lt;a href=&quot;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&quot;&gt;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Text)&lt;/p&gt;
&lt;p&gt;Motivation for the workshop**&lt;/p&gt;
&lt;p&gt;Nature is still full of unknown chemistry with possible beneficial properties such as anti-inflammatory or antibiotic ones. Over the last decade, increasing numbers of genome sequences and metabolomics profiles have become available in public resources. Hence, the combination of genome mining and metabolome mining has gained traction in accelerating natural product discovery by linking biosynthetic genes to molecular scaffolds and structures, and associating producers with their products. However, effective integrative omics mining has proven challenging due to the various data types and tools involved. In 2021, &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008920&quot;&gt;NPLinker&lt;/a&gt; was proposed as a solution to streamline many aspects of integrative omics, so that researchers can focus on analyzing the possible matches between genes and molecules. Over the last years, the Open eScience Call project has further build on this solution to create &lt;a href=&quot;https://research-software-directory.org/software/nplinker&quot;&gt;a framework for paired omics analyses&lt;/a&gt;. To gain experience with the NPLinker framework and build an integrative omics mining community of talented, driven early-career researchers and knowledgeable instructors, Marnix Medema and I organized this second NPLinker-eScience workshop in Wageningen, the Netherlands.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Outline of the workshop&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;During this second workshop in a series of two, we again aimed to bring together researchers interested in integrative omics analysis, spanning various career stages, computational or the application-focused backgrounds, and diverse organisms they work on. Following a selection process, 38 participants were selected to come to Wageningen to learn about analyzing genomes and metabolomes, and to get an outlook towards the integration of the two. The general aims of &lt;a href=&quot;https://www.wur.nl/en/research-results/chair-groups/plant-sciences/bioinformatics/teaching/nplinker_workshop.htm&quot;&gt;the workshop&lt;/a&gt; were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduce the NPLinker framework both conceptually and hands-on&lt;/li&gt;
&lt;li&gt;Educate and train natural product researchers and other interested scientists&lt;/li&gt;
&lt;li&gt;Extend the Integrative Omics Mining Community&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The workshop intended learning outcomes were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand the concepts of and motivations for paired omics analysis&lt;/li&gt;
&lt;li&gt;Apply NPLinker to a public paired omics dataset&lt;/li&gt;
&lt;li&gt;Understand the NPLinker scoring&lt;/li&gt;
&lt;li&gt;Evaluate NPLinker outcome in the web app&lt;/li&gt;
&lt;li&gt;Understand how to contribute to the NPLinker code base&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To stimulate networking amongst the participants and instructors, several measures were put in place: extended coffee and tea breaks, the opportunity to present a poster, and a social mixer at the start to get to know each other. Furthermore, Marnix and I organized a symposium on Wednesday to highlight exciting developments in genome mining, metabolome mining, integrative omics mining, and the reuse of public omics data. We are grateful for the financial support from the eScience Center, which helped to make the workshop affordable for participants from across the globe through a travel reimbursement scheme and enabled the participation of three international instructors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;669&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-0bf0eb4f.CUwTRxyS_Z85FHB.webp&quot; srcset=&quot;&quot;&gt;
All 38 participants from across the globe together with the instructors in front of the &lt;a href=&quot;https://www.wur.nl/en/location/omnia-2.htm&quot;&gt;Omnia building&lt;/a&gt; at the &lt;a href=&quot;https://www.wur.nl/en.htm&quot;&gt;Wageningen University &amp;#x26; Research&lt;/a&gt; campus.&lt;/p&gt;
&lt;p&gt;I am increasingly aware of how integrative omics mining brings together different disciplines — what’s in a name, one could say. Furthermore, the field connects both researchers using the omics tools and developers working on them. We intentionally invited participants from these two groups and various disciplines to foster connections and collectively gain experience with the latest developments in the field. One key insight is that the fields is moving rapidly: only two years ago, we explained the latest in genome mining and metabolome mining, and during this workshop, versions 2 of BiG-SCAPE and GNPS were on the menu, replacing the previous versions. From a user perspective, this means staying up-to-date with how to use these tools effectively is key to remain on top of the latest possibilities in omics mining. From a developer perspective, it is important to build integrative tools like NPLinker in a way that can keep pace with the fast-evolving omics landscape. Another key insight is that, given the diverse backgrounds of participants, it is challenging to fully cater everyone’s needs. Striking the right balance between fixed program components and more flexible ones may help–allowing the explanation and demonstration of concepts or tools to be targeted based on participants’ needs. A final key insight is that promoting the exchange of knowledge and expertise in between participants is crucial, as it accelerates the uptake of new skills and information and helps form the bonds that create a scientific community.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;679&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-ef101463.nn9ZIVYM_nutVJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;677&quot; height=&quot;510&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-fe492552.DR1a_7tq_2uqmG7.webp&quot; srcset=&quot;&quot;&gt;
Participants have been working hands-on with BiG-SCAPE, GNPS, and NPLinker during the workshop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Access Materials&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A tangible outcome of the workshop for the broader community is that the instructors all made as much as possible &lt;a href=&quot;https://doi.org/10.5281/zenodo.15281967&quot;&gt;the materials available under an open access license&lt;/a&gt;! I hope this initiative will help to further foster the teaching of the future generation of omics miners, support the development of educational resources for genome mining, metabolomics, and metabolome mining, and promote discussions and integration between the fields of genome mining and metabolome mining.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-a548f678.DscDT-pC_Z1pHYGC.webp&quot; srcset=&quot;&quot;&gt;
With huge thanks to all the NPLinker eScience Workshop instructors who came from across the globe to Wageningen to teach the participants many facets of integrative omics mining.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Personal reflection&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Altogether, I am happy that all participants and instructors enjoyed the workshop and gained something valuable from it. I am very pleased that everyone had a good time and that the location and catering was appreciated. Furthermore, it was great to organize the symposium with Marnix Medema that celebrated the work lustra of our teams in computational genomics (1o years) and metabolomics (5 years). Not only did we invite keynote speakers–Pieter Dorrestein, Tilmann Weber, and Margherita Sosio–but we also invited three workshop participants to showcase their work in a flash talk. In case you are curious, you can watch it back &lt;a href=&quot;https://wur.yuja.com/V/Video?v=885970&amp;#x26;node=4776818&amp;#x26;a=66183860&quot;&gt;here&lt;/a&gt;. I found it nice to read in the evaluations how the participants liked to see each others’ posters during the breaks, and how they liked the flash talks during the symposium.&lt;/p&gt;
&lt;p&gt;If there is one thing I would have changed looking back at the event, it would be to organize more structured parallel sessions to dive deeper into the application and development of NPLinker, for example by using two separate rooms and dividing participants and instructors accordingly. This would have allowed both groups (users and developers) to discuss their ideas and challenges in greater detail, without the feeling of disturbing each other.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-22f93410.DbJUW8l-_ZDPVU9.webp&quot; srcset=&quot;&quot;&gt;
Community building during the workshop dinner!&lt;/p&gt;
&lt;p&gt;What I really liked were the workshop keynotes–thanks again to Kate Duncan for setting the scene on Monday, to Margherita Sosio for showcasing how omics mining is applied in an industrial setting and how the Molecules Gateway operates, and to Kumar Saurabh Singh for sharing his perspective on multi-omics analyses. Further, thanks again to the eScience Center for supporting this workshop series, and to the Omnia and Orion teams for their support and efforts before and during the week. A big thank-you as well to Maria Augustijn and Marie-José van Iersel for their support in organizing various aspects of the workshop and symposium. Thanks to Marnix for your support and being co-organizer of this event. And finally, many thanks to all the participants for their open and constructive attitude during the workshop — much appreciated!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Scientific Community Building through Workshops: the NPLinker eScience experience&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-a3b95cc3.C5BiktrF_ZyC2x6.webp&quot; srcset=&quot;&quot;&gt;
Marnix Medema (right) and myself (left) during the symposium we organized.&lt;/p&gt;
&lt;p&gt;Whilst this was the last workshop in a series of two, I hope to see the integrative omics community together on future occasions!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/scientific-community-building-through-wo-0741307b.Cd4Yi41s.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Benchmarking LLM fine-tuning on different HPC systems</title><link>https://blog2.esciencecenter.nl/posts/2025-05-06---benchmarking-llm-fine-tuning-on-different-hpc-systems</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-05-06---benchmarking-llm-fine-tuning-on-different-hpc-systems</guid><description>&lt;p&gt;43&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Authors: Flavio Hafner (Netherlands eScience center), Mattie Niznik (Princeton Research Computing), Malte Lüken (Netherlands eScience center), Alessandra Maranca (Princeton University), Matthew Salganik (Princeton University).&lt;/p&gt;
&lt;p&gt;We have developed a benchmark that compares the compute performance of fine-tuning LLMs on multiple high-performance computing (HPC) systems, including systems designed for working with sensitive data. In this blog post, we introduce the benchmark, describe the lessons learned developing it and make it &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&quot;&gt;open-source&lt;/a&gt; so that it can be used and improved by others.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Benchmarking LLM fine-tuning on different HPC systems&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-61f6f9dd.BB_OnOxS_P3heT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nanadua11?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Nana Dua&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;our-use-case&quot;&gt;Our use case&lt;/h3&gt;
&lt;p&gt;Our team researches how Large Language Models (LLMs) can be leveraged to predict social outcomes with large-scale social and survey data. We use the ODISSEI Secure Supercomputer (&lt;a href=&quot;https://servicedesk.surf.nl/wiki/spaces/WIKI/pages/17826074/ODISSEI+Secure+Supercomputer&quot;&gt;OSSC&lt;/a&gt;), which &lt;a href=&quot;https://www.surf.nl/&quot;&gt;SURF&lt;/a&gt; operates in the Netherlands. The OSSC is a virtual private cluster running on the hardware of Snellius, the Dutch national supercomputer. The OSSC makes it possible to use GPU and CPU nodes to analyze sensitive data from Statistics Netherlands. This makes the OSSC one among very few systems globally that bring the power of national computing clusters to large-scale social data.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/pdf/2103.14679&quot;&gt;Previous performance benchmarks for OSSC&lt;/a&gt; were entirely focused on CPUs, and the performance of OSSC for GPU-intensive tasks, such as fine-tuning LLMs, was unknown.&lt;/p&gt;
&lt;p&gt;Our benchmarking compares the performance of the OSSC to two different systems: 1) its parent system, &lt;a href=&quot;https://www.surf.nl/en/services/snellius-the-national-supercomputer&quot;&gt;Snellius&lt;/a&gt;, which is not connected to sensitive data and 2) &lt;a href=&quot;https://researchcomputing.princeton.edu/systems/della&quot;&gt;Della&lt;/a&gt;, an HPC system similar to Snellius, which is operated by Princeton University.&lt;/p&gt;
&lt;h3 id=&quot;beyond-our-use-case&quot;&gt;Beyond our use case&lt;/h3&gt;
&lt;p&gt;Our benchmark, &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&quot;&gt;openly available on GitHub&lt;/a&gt;, is also a starting point for the exploration of fine-tuning performance in other cases. For instance, one can compare the training performance within and across HPC systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Within a system, one may have to choose between different GPU models, and the cost and benefits of using one versus the other may vary depending on the task.&lt;/li&gt;
&lt;li&gt;Across systems, training performance does not only depend on the raw performance of GPUs–the number of floating point operations per second–, but also on factors such as the file system, how the computing hardware (processing cores and nodes) is connected through wires, and the exact version of GPU models used — as we will show.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-performance-benchmark&quot;&gt;The performance benchmark&lt;/h2&gt;
&lt;h3 id=&quot;the-specification&quot;&gt;The specification&lt;/h3&gt;
&lt;p&gt;We decided that our benchmark should satisfy the following requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is easy to run in many different computing environments.&lt;/li&gt;
&lt;li&gt;It tracks multiple measures of speed, such as tokens per second and wall time.&lt;/li&gt;
&lt;li&gt;It tracks anything useful to understand possible differences between the environments (GPU usage, CPU usage).&lt;/li&gt;
&lt;li&gt;It is fast to run.&lt;/li&gt;
&lt;li&gt;It is easy to improve over time: as our research evolves, we may need to re-assess the performance for new use cases.&lt;/li&gt;
&lt;li&gt;It is easy to understand and replicate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our compute conditions are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Environment: Della, Snellius, OSSC.&lt;/li&gt;
&lt;li&gt;GPUs: A100 (40/80GB VRAM), H100 (80/96GB VRAM).&lt;/li&gt;
&lt;li&gt;Single-node training, with GPUs per node: 1, 2, 4.&lt;/li&gt;
&lt;li&gt;As many CPUs as are necessary to keep the GPUs busy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-implementation&quot;&gt;The implementation&lt;/h3&gt;
&lt;p&gt;We found that &lt;a href=&quot;https://pytorch.org/torchtune/stable/index.html&quot;&gt;torchtune&lt;/a&gt; fits our requirements best. We fine-tune the &lt;a href=&quot;https://huggingface.co/meta-llama/Llama-3.2-1B-Instruct&quot;&gt;Llama-3.2–1B-Instruct&lt;/a&gt; model on the &lt;a href=&quot;https://huggingface.co/datasets/yahma/alpaca-cleaned&quot;&gt;alpaca-cleaned&lt;/a&gt; dataset. Our main hyperparameters are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A context length of 2048 on a packed dataset&lt;/li&gt;
&lt;li&gt;Low-Rank Adaptation (LoRA) for the attention layers as well as the output layers. We use a rank of 64, alpha of 128 and 0 dropout.&lt;/li&gt;
&lt;li&gt;A batch size of 6, which was the maximum we could fit into our least capable GPUs (A100)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-we-found&quot;&gt;What we found&lt;/h2&gt;
&lt;h3 id=&quot;performance-differences&quot;&gt;Performance differences&lt;/h3&gt;
&lt;p&gt;The figure below shows the results from our benchmarking runs:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Benchmarking LLM fine-tuning on different HPC systems&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;329&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-08fc9eed.N9GnHhKC_15W5Hg.webp&quot; srcset=&quot;&quot;&gt;
Tokens per second per GPU on a single node (higher is better). The colors refer to different systems (Della, Snellius, OSSC); the panels refer to different numbers of GPUs.In our experience, there was little variation in throughput across different runs on the same system, so we did not average over multiple runs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Della was about 15% faster than the Dutch systems, independent of the number and models of GPUs.&lt;/li&gt;
&lt;li&gt;The OSSC performed on par with Snellius.&lt;/li&gt;
&lt;li&gt;For our use case, H100s were between 1.7x and 2x faster than A100s.&lt;/li&gt;
&lt;li&gt;Throughput scales nearly linearly with the number of GPUs: The communication overhead from multiple GPUs was about 6–8% for going from 1 to 2 GPUs and 2% or less for going from 2 to 4 GPUs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many of these results made sense to us. Because Della and Snellius are broadly similar systems, we were surprised by the performance gap between the two. Thus, we decided to &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark/issues/10&quot;&gt;investigate&lt;/a&gt; further.&lt;/p&gt;
&lt;p&gt;First, we ruled out that the gap stems from differences in software. The precise way to install dependencies differs between Della and Snellius: Our environments use anaconda on Della and a Python virtual environment with pip on Snellius. We confirmed that the two environments use the same package versions.&lt;/p&gt;
&lt;p&gt;Second, we ruled out that the gap stems from differences in the file system. In particular, for high-performance machine learning, data I/O is often a bottleneck, and it can be reduced by using a fast file system. However, our experiments on Snellius showed no difference in speed between the &lt;a href=&quot;https://servicedesk.surf.nl/wiki/display/WIKI/Snellius+filesystems&quot;&gt;various file systems&lt;/a&gt; available.&lt;/p&gt;
&lt;p&gt;We then found that subtle hardware differences probably explain the gap — differences in memory clock speed of the GPUs:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Benchmarking LLM fine-tuning on different HPC systems&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;408&quot; height=&quot;163&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-0b239ae2.Dq9YkhP4_Z1gsdLp.webp&quot; srcset=&quot;&quot;&gt;
Memory clock speed for GPUs on the two systems (higher is better).For the A100s, the Snellius/OSSC GPUs have 40GB VRAM, while the Della GPUs have 80GB VRAM. The 80GB variant also comes with a higher memory clock speed than the 40GB variant, leading to the difference in fine-tuning speed on A100s between Della and Snellius.&lt;/p&gt;
&lt;p&gt;For the H100s, the difference is in the version of the cards, and specifically their memory: Della has cards with the faster HBM3 memory, while Snellius/OSSC has cards with HBM2e memory. This means that the calculations during model training have a memory speed bottleneck on Snellius/OSSC compared to Della.&lt;/p&gt;
&lt;h3 id=&quot;lessons-learned-from-bringing-llms-into-secure-computing-environments&quot;&gt;Lessons learned from bringing LLMs into secure computing environments&lt;/h3&gt;
&lt;p&gt;Running this test and bringing the Llama model into a secure environment created additional challenges.&lt;/p&gt;
&lt;p&gt;First, by default, torchtune downloads the specified dataset from the internet without the user noticing. But because the OSSC is cut off from the internet, we had to use the Alpaca dataset locally and adjust the code accordingly before deployment.&lt;/p&gt;
&lt;p&gt;Second, to import the model weights to the secure computing environment, we had to ensure that the contents of the files were not a security risk. Thus, we followed current best practices: First, we manually scanned the files with the virus scanner &lt;a href=&quot;https://docs.clamav.net/manual/Usage/Scanning.html&quot;&gt;ClamScan&lt;/a&gt;, similar to what Hugging Face does automatically for models hosted there. Second, we imported the model weights in &lt;a href=&quot;https://huggingface.co/docs/safetensors/en/index&quot;&gt;safetensors&lt;/a&gt; format, which is safer than the pickle format and prevents arbitrary code execution.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We introduce a benchmark for comparing throughput for LLM fine-tuning on different HPC systems. We found hardware-driven performance differences between two standard HPC systems. We also provide the first performance comparison of the OSSC compared to its parent system, Snellius. Lastly, our benchmark suggests little cost of scaling fine-tuning to multiple GPUs on a single node.&lt;/p&gt;
&lt;p&gt;The code for our benchmark is publicly available: &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&quot;&gt;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Patrick Bos for feedback on a draft.&lt;/p&gt;</description><pubDate>Tue, 06 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;43&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Authors: Flavio Hafner (Netherlands eScience center), Mattie Niznik (Princeton Research Computing), Malte Lüken (Netherlands eScience center), Alessandra Maranca (Princeton University), Matthew Salganik (Princeton University).&lt;/p&gt;
&lt;p&gt;We have developed a benchmark that compares the compute performance of fine-tuning LLMs on multiple high-performance computing (HPC) systems, including systems designed for working with sensitive data. In this blog post, we introduce the benchmark, describe the lessons learned developing it and make it &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&quot;&gt;open-source&lt;/a&gt; so that it can be used and improved by others.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Benchmarking LLM fine-tuning on different HPC systems&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-61f6f9dd.BB_OnOxS_P3heT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@nanadua11?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Nana Dua&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;our-use-case&quot;&gt;Our use case&lt;/h3&gt;
&lt;p&gt;Our team researches how Large Language Models (LLMs) can be leveraged to predict social outcomes with large-scale social and survey data. We use the ODISSEI Secure Supercomputer (&lt;a href=&quot;https://servicedesk.surf.nl/wiki/spaces/WIKI/pages/17826074/ODISSEI+Secure+Supercomputer&quot;&gt;OSSC&lt;/a&gt;), which &lt;a href=&quot;https://www.surf.nl/&quot;&gt;SURF&lt;/a&gt; operates in the Netherlands. The OSSC is a virtual private cluster running on the hardware of Snellius, the Dutch national supercomputer. The OSSC makes it possible to use GPU and CPU nodes to analyze sensitive data from Statistics Netherlands. This makes the OSSC one among very few systems globally that bring the power of national computing clusters to large-scale social data.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/pdf/2103.14679&quot;&gt;Previous performance benchmarks for OSSC&lt;/a&gt; were entirely focused on CPUs, and the performance of OSSC for GPU-intensive tasks, such as fine-tuning LLMs, was unknown.&lt;/p&gt;
&lt;p&gt;Our benchmarking compares the performance of the OSSC to two different systems: 1) its parent system, &lt;a href=&quot;https://www.surf.nl/en/services/snellius-the-national-supercomputer&quot;&gt;Snellius&lt;/a&gt;, which is not connected to sensitive data and 2) &lt;a href=&quot;https://researchcomputing.princeton.edu/systems/della&quot;&gt;Della&lt;/a&gt;, an HPC system similar to Snellius, which is operated by Princeton University.&lt;/p&gt;
&lt;h3 id=&quot;beyond-our-use-case&quot;&gt;Beyond our use case&lt;/h3&gt;
&lt;p&gt;Our benchmark, &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&quot;&gt;openly available on GitHub&lt;/a&gt;, is also a starting point for the exploration of fine-tuning performance in other cases. For instance, one can compare the training performance within and across HPC systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Within a system, one may have to choose between different GPU models, and the cost and benefits of using one versus the other may vary depending on the task.&lt;/li&gt;
&lt;li&gt;Across systems, training performance does not only depend on the raw performance of GPUs–the number of floating point operations per second–, but also on factors such as the file system, how the computing hardware (processing cores and nodes) is connected through wires, and the exact version of GPU models used — as we will show.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-performance-benchmark&quot;&gt;The performance benchmark&lt;/h2&gt;
&lt;h3 id=&quot;the-specification&quot;&gt;The specification&lt;/h3&gt;
&lt;p&gt;We decided that our benchmark should satisfy the following requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is easy to run in many different computing environments.&lt;/li&gt;
&lt;li&gt;It tracks multiple measures of speed, such as tokens per second and wall time.&lt;/li&gt;
&lt;li&gt;It tracks anything useful to understand possible differences between the environments (GPU usage, CPU usage).&lt;/li&gt;
&lt;li&gt;It is fast to run.&lt;/li&gt;
&lt;li&gt;It is easy to improve over time: as our research evolves, we may need to re-assess the performance for new use cases.&lt;/li&gt;
&lt;li&gt;It is easy to understand and replicate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our compute conditions are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Environment: Della, Snellius, OSSC.&lt;/li&gt;
&lt;li&gt;GPUs: A100 (40/80GB VRAM), H100 (80/96GB VRAM).&lt;/li&gt;
&lt;li&gt;Single-node training, with GPUs per node: 1, 2, 4.&lt;/li&gt;
&lt;li&gt;As many CPUs as are necessary to keep the GPUs busy.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-implementation&quot;&gt;The implementation&lt;/h3&gt;
&lt;p&gt;We found that &lt;a href=&quot;https://pytorch.org/torchtune/stable/index.html&quot;&gt;torchtune&lt;/a&gt; fits our requirements best. We fine-tune the &lt;a href=&quot;https://huggingface.co/meta-llama/Llama-3.2-1B-Instruct&quot;&gt;Llama-3.2–1B-Instruct&lt;/a&gt; model on the &lt;a href=&quot;https://huggingface.co/datasets/yahma/alpaca-cleaned&quot;&gt;alpaca-cleaned&lt;/a&gt; dataset. Our main hyperparameters are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A context length of 2048 on a packed dataset&lt;/li&gt;
&lt;li&gt;Low-Rank Adaptation (LoRA) for the attention layers as well as the output layers. We use a rank of 64, alpha of 128 and 0 dropout.&lt;/li&gt;
&lt;li&gt;A batch size of 6, which was the maximum we could fit into our least capable GPUs (A100)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-we-found&quot;&gt;What we found&lt;/h2&gt;
&lt;h3 id=&quot;performance-differences&quot;&gt;Performance differences&lt;/h3&gt;
&lt;p&gt;The figure below shows the results from our benchmarking runs:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Benchmarking LLM fine-tuning on different HPC systems&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;329&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-08fc9eed.N9GnHhKC_15W5Hg.webp&quot; srcset=&quot;&quot;&gt;
Tokens per second per GPU on a single node (higher is better). The colors refer to different systems (Della, Snellius, OSSC); the panels refer to different numbers of GPUs.In our experience, there was little variation in throughput across different runs on the same system, so we did not average over multiple runs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Della was about 15% faster than the Dutch systems, independent of the number and models of GPUs.&lt;/li&gt;
&lt;li&gt;The OSSC performed on par with Snellius.&lt;/li&gt;
&lt;li&gt;For our use case, H100s were between 1.7x and 2x faster than A100s.&lt;/li&gt;
&lt;li&gt;Throughput scales nearly linearly with the number of GPUs: The communication overhead from multiple GPUs was about 6–8% for going from 1 to 2 GPUs and 2% or less for going from 2 to 4 GPUs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many of these results made sense to us. Because Della and Snellius are broadly similar systems, we were surprised by the performance gap between the two. Thus, we decided to &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark/issues/10&quot;&gt;investigate&lt;/a&gt; further.&lt;/p&gt;
&lt;p&gt;First, we ruled out that the gap stems from differences in software. The precise way to install dependencies differs between Della and Snellius: Our environments use anaconda on Della and a Python virtual environment with pip on Snellius. We confirmed that the two environments use the same package versions.&lt;/p&gt;
&lt;p&gt;Second, we ruled out that the gap stems from differences in the file system. In particular, for high-performance machine learning, data I/O is often a bottleneck, and it can be reduced by using a fast file system. However, our experiments on Snellius showed no difference in speed between the &lt;a href=&quot;https://servicedesk.surf.nl/wiki/display/WIKI/Snellius+filesystems&quot;&gt;various file systems&lt;/a&gt; available.&lt;/p&gt;
&lt;p&gt;We then found that subtle hardware differences probably explain the gap — differences in memory clock speed of the GPUs:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Benchmarking LLM fine-tuning on different HPC systems&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;408&quot; height=&quot;163&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-0b239ae2.Dq9YkhP4_Z1gsdLp.webp&quot; srcset=&quot;&quot;&gt;
Memory clock speed for GPUs on the two systems (higher is better).For the A100s, the Snellius/OSSC GPUs have 40GB VRAM, while the Della GPUs have 80GB VRAM. The 80GB variant also comes with a higher memory clock speed than the 40GB variant, leading to the difference in fine-tuning speed on A100s between Della and Snellius.&lt;/p&gt;
&lt;p&gt;For the H100s, the difference is in the version of the cards, and specifically their memory: Della has cards with the faster HBM3 memory, while Snellius/OSSC has cards with HBM2e memory. This means that the calculations during model training have a memory speed bottleneck on Snellius/OSSC compared to Della.&lt;/p&gt;
&lt;h3 id=&quot;lessons-learned-from-bringing-llms-into-secure-computing-environments&quot;&gt;Lessons learned from bringing LLMs into secure computing environments&lt;/h3&gt;
&lt;p&gt;Running this test and bringing the Llama model into a secure environment created additional challenges.&lt;/p&gt;
&lt;p&gt;First, by default, torchtune downloads the specified dataset from the internet without the user noticing. But because the OSSC is cut off from the internet, we had to use the Alpaca dataset locally and adjust the code accordingly before deployment.&lt;/p&gt;
&lt;p&gt;Second, to import the model weights to the secure computing environment, we had to ensure that the contents of the files were not a security risk. Thus, we followed current best practices: First, we manually scanned the files with the virus scanner &lt;a href=&quot;https://docs.clamav.net/manual/Usage/Scanning.html&quot;&gt;ClamScan&lt;/a&gt;, similar to what Hugging Face does automatically for models hosted there. Second, we imported the model weights in &lt;a href=&quot;https://huggingface.co/docs/safetensors/en/index&quot;&gt;safetensors&lt;/a&gt; format, which is safer than the pickle format and prevents arbitrary code execution.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We introduce a benchmark for comparing throughput for LLM fine-tuning on different HPC systems. We found hardware-driven performance differences between two standard HPC systems. We also provide the first performance comparison of the OSSC compared to its parent system, Snellius. Lastly, our benchmark suggests little cost of scaling fine-tuning to multiple GPUs on a single node.&lt;/p&gt;
&lt;p&gt;The code for our benchmark is publicly available: &lt;a href=&quot;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&quot;&gt;https://github.com/odissei-benchmarks/torchtune-gpu-benchmark&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thanks to Patrick Bos for feedback on a draft.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/benchmarking-llm-fine-tuning-on-differen-61f6f9dd.BB_OnOxS.jpg" medium="image"/><author>Flavio Hafner</author></item><item><title>Keeping your scientific data files small</title><link>https://blog2.esciencecenter.nl/posts/2025-04-22---keeping-your-scientific-data-files-small</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-04-22---keeping-your-scientific-data-files-small</guid><description>&lt;h1 id=&quot;keeping-your-scientific-data-files-small&quot;&gt;&lt;strong&gt;Keeping your scientific data files small&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;an-rses-guide-to-netcdf-compression&quot;&gt;An RSE’s guide to NetCDF compression&lt;/h2&gt;
&lt;p&gt;If you’ve ever watched a crawling progress bar while transferring research data, or received a dreaded ‘storage quota exceeded’ message, you’re not alone. Researchers across disciplines face a common challenge: the size of collected data can outpace storage and processing capabilities. This blog explores how compression techniques for NetCDF (Network Common Data Form) files — a format commonly used for multidimensional scientific data — can reduce storage requirements while maintaining data integrity. Whether you’re handling climate models, GIS data, or sensor networks, these approaches can change how you manage and access multidimensional data, such as data with both time and spatial coordinates.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;247&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-98bdacab.BAgZz0KS_Z1jIqyL.webp&quot; srcset=&quot;&quot;&gt;
Simplified structure of a netCDF file (from the &lt;a href=&quot;https://docs.xarray.dev/en/latest/user-guide/data-structures.html#dataset&quot;&gt;xarray documentation&lt;/a&gt;); created by Stephan Hoyer, Apache 2.0 license).If you have multidimensional data, the file sizes can get big quite fast. Take output from the &lt;a href=&quot;https://www.ecmwf.int/en/forecasts/dataset/ecmwf-reanalysis-v5&quot;&gt;ERA5 global weather reanalysis&lt;/a&gt; product:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It has a resolution of 0.25 degrees, at an hourly frequency.&lt;/li&gt;
&lt;li&gt;This means that there are 720x1440x365x24 = 9 billion data points per variable per year.&lt;/li&gt;
&lt;li&gt;This type of data is usually represented as &lt;a href=&quot;https://en.wikipedia.org/wiki/Single-precision_floating-point_format&quot;&gt;32-bit floating points numbers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;32 bits equals 4 bytes, times 9 billion; approximately 36 GB/year. Per variable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As soon as you want to analyze multiple years, for multiple variables, your required storage can quickly reach dozens of terabytes. Storing all this data can not only be prohibitively difficult or expensive, it also significantly increases your carbon footprint. Luckily, there are multiple ways to reduce the file size of netCDF files, with various up- and downsides.&lt;/p&gt;
&lt;h3 id=&quot;lossless-compression&quot;&gt;Lossless compression**&lt;/h3&gt;
&lt;p&gt;You are probably familiar with putting files on your computer in a zip folder. This can significantly reduce their size (if the data is not already compressed yet):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;627&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-b8c718e0.DGm5X3sc_lkybk.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Lossless compression of a simple 19 kB python code file&lt;/em&gt;You can then retrieve the exact files from the zip folder, without any loss of information. This is called “lossless” compression. Many files on your computer are compressed in this way already (for example, Microsoft Office files, or PDF documents).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lossy compression&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A different compression method you probably have encountered before is lossy compression. Lossy compression is often applied to audio, images and video to dramatically reduce their size (~10x for audio or still images, 100x for video), with little &lt;em&gt;perceived&lt;/em&gt; quality loss.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;200&quot; height=&quot;200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-74813b92.BawBpZT5_ZYuTqU.webp&quot; srcset=&quot;&quot;&gt;
*Very lossy JPEG compression versus lossless PNG. Source: *&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Comparison_of_JPEG_and_PNG.png&quot;&gt;&lt;em&gt;Wikimedia&lt;/em&gt;&lt;/a&gt;A downside of lossy compression is that each time you open the data and would write it away lossily again, additional compression artifacts are introduced. This will cause a gradual degradation in data quality.&lt;/p&gt;
&lt;h2 id=&quot;compressing-netcdf-files&quot;&gt;Compressing netCDF files&lt;/h2&gt;
&lt;p&gt;As a quick refresher, we need to discuss how netCDF files are structured.&lt;/p&gt;
&lt;p&gt;NetCDF files organize the data per variable. Each variable in turn is split up in different “chunks”. These chunks correspond to subsets of the full array. For example, data can be chunked only in time, where each chunk represents the entire physical domain (latitude &amp;#x26; longitude) for a single time coordinate.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;211&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-16368190.DhbsZa2l_ZXGA1a.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Graphical representation of chunks in the xarray python package, using Dask&lt;/em&gt;These chunks are read into memory one at a time, so for any operations it is important that the chunks fit your analysis for efficiency.&lt;/p&gt;
&lt;p&gt;The actual underlying data can be stored as 32-bit floating point numbers on disk, but there are a few options for compression.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lossless netCDF compression&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just like with text files or other documents, lossless compression is possible for netCDF files. The more repetitious your data is, the easier it is for lossless compression algorithms to compress your data.&lt;/p&gt;
&lt;p&gt;cdo -z zip 4 … # where 4 is the compression level (1 - 9)In Python, with the popular ‘xarray’ package, you can instead do:&lt;/p&gt;
&lt;p&gt;import xarray as xr&lt;/p&gt;
&lt;p&gt;ds = xr.open_dataset(“my_dataset.nc”)
encoding = {“my_variable”: {“zlib”: True, “complevel”: 4}}
ds.to_netcdf(“compressed_dataset.nc”, encoding=encoding)In many cases applying lossless compression to your data can reduce the size on disk by 20–50%. This comes at a cost of slightly more CPU use, while disk I/O usage is lower.&lt;/p&gt;
&lt;p&gt;The exact impact on your analysis speed will depend on your system, but unless you have a slow CPU and a blazingly fast disk your further analyses will likely be faster when you compress your data. Therefore it’s best to default to using some form of lossless compression on your netCDF files, unless you have a specific reason not to.&lt;/p&gt;
&lt;p&gt;Lossy netCDF compression**&lt;/p&gt;
&lt;p&gt;As stated earlier, unlike lossless compression, lossy compression does not preserve the full original data. Some of the original resolution can be lost, while offering a much smaller file size as well as a faster read speed.&lt;/p&gt;
&lt;p&gt;Often some loss of resolution is not a problem, as 32-bit floating point numbers offer more precision than many measurements or model data realistically have.&lt;/p&gt;
&lt;p&gt;One way of lossy compression which is well supported by netCDF is encoding floating point numbers to integers. This is usually done with 16-bit unsigned integers: whole numbers ranging from 0 to 65,535. The floating point numbers can then be mapped to this range.&lt;/p&gt;
&lt;p&gt;For example; as the lowest ambient air temperature ever recorded on earth is 184 K, and the highest 330 K, giving a range of 146 K. To convert the temperature, you take the integer value, multiply it with a ‘scale factor’, and add the offset. The temperature range can thus be divided over 65,535 discrete values, translating into a maximum resolution of ~2.23 mK, which is a much higher resolution than most scientific air temperature sensors. Your offset here would be 184 K.&lt;/p&gt;
&lt;p&gt;Integer encoding works very well for climate data as the range of values that you can expect should be very well constrained. This allows you to make informed estimates of what sufficient precision is for these variables, while still significantly reducing the size of the data on disk.&lt;/p&gt;
&lt;p&gt;When using integer encoding in xarray you can specify the encoding as such:&lt;/p&gt;
&lt;p&gt;import xarray as xr**
ds = xr.open_dataset(“my_dataset.nc”)&lt;/p&gt;
&lt;p&gt;fvalue = 65535  # fill value for missing values
scale = 0.005  # store temperature in 5 mK increments
offset = 0  # Kelvin is abolute: no offset required&lt;/p&gt;
&lt;p&gt;encoding = {
“my_temperature_variable”:
{
‘_FillValue’: fvalue, ‘scale_factor’: scale, ‘add_offset’: offset, ‘dtype’: ‘int16’,
“zlib”: True, “complevel”: 4,  # you can still use lossless compression!
},
}&lt;/p&gt;
&lt;p&gt;ds.to_netcdf(“compressed_dataset.nc”, encoding=encoding)For Climate Data Operators users, the &lt;a href=&quot;https://code.mpimet.mpg.de/projects/cdo/embedded/index.html#x1-1130002.2.4&quot;&gt;“pack” operator&lt;/a&gt; is available for this purpose.&lt;/p&gt;
&lt;p&gt;Compression ‘filters’**&lt;/p&gt;
&lt;p&gt;Lastly, HDF5; the underlying data format of netCDF4 files, has “filter plugins” available. These plugins allow you to use other lossy compression algorithms for your netCDF data. These filters are a more advanced use case and not as easy to set up as the other compression methods.&lt;/p&gt;
&lt;p&gt;Some publications (e.g., &lt;a href=&quot;https://gmd.copernicus.org/articles/17/8909/2024/&quot;&gt;Prims, 2024&lt;/a&gt;, and &lt;a href=&quot;https://gmd.copernicus.org/articles/12/4099/2019/#section14&quot;&gt;Delauney, 2019&lt;/a&gt;)) have studied the effect of these on netCDF and numerical weather prediction data specifically.&lt;/p&gt;
&lt;p&gt;Depending on the variables, these compression algorithms can reduce the data size on disk by a factor of 5–150. However, unlike integer compression, the effects of these compression algorithms on your data is not as easily predictable, and you might need to do a sensitivity study for your own application.&lt;/p&gt;
&lt;p&gt;However, there are use cases such as many climate model ensembles where compressing the data lossily could be a way to store data that would otherwise be too large to store.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Compression and chunks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As the underlying data of each variable in a netCDF file is organized in “chunks”, the compression algorithm is applied per chunk. *This allows you to still load individual chunks of data without requiring to load and decompress the entire file.&lt;/p&gt;
&lt;p&gt;Therefore it is important to organize these chunks in a way that aligns well with your intended usage; for example, either looking at the full time series for a single location, or the entire world at a single point in time. This will enable you to read parts of your full netCDF file very quickly and store them efficiently.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Compressing your netCDF data can reduce your disk usage significantly, which allows you to store or share data more easily. For most users lossless compression is the most straightforward and should be applied by default.&lt;/p&gt;
&lt;p&gt;For many others, where storage space is a constraint, storing your floating point numbers as 16-bit integers is a predictable way of compressing your data further. Other lossy algorithms are available, but are generally too complex to use for most users.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-e8dca7c8.DvWanidn_1mq1og.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@jasonpofahlphotography?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Jason Pofahl&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;keeping-your-scientific-data-files-small&quot;&gt;&lt;strong&gt;Keeping your scientific data files small&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;an-rses-guide-to-netcdf-compression&quot;&gt;An RSE’s guide to NetCDF compression&lt;/h2&gt;
&lt;p&gt;If you’ve ever watched a crawling progress bar while transferring research data, or received a dreaded ‘storage quota exceeded’ message, you’re not alone. Researchers across disciplines face a common challenge: the size of collected data can outpace storage and processing capabilities. This blog explores how compression techniques for NetCDF (Network Common Data Form) files — a format commonly used for multidimensional scientific data — can reduce storage requirements while maintaining data integrity. Whether you’re handling climate models, GIS data, or sensor networks, these approaches can change how you manage and access multidimensional data, such as data with both time and spatial coordinates.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;247&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-98bdacab.BAgZz0KS_Z1jIqyL.webp&quot; srcset=&quot;&quot;&gt;
Simplified structure of a netCDF file (from the &lt;a href=&quot;https://docs.xarray.dev/en/latest/user-guide/data-structures.html#dataset&quot;&gt;xarray documentation&lt;/a&gt;); created by Stephan Hoyer, Apache 2.0 license).If you have multidimensional data, the file sizes can get big quite fast. Take output from the &lt;a href=&quot;https://www.ecmwf.int/en/forecasts/dataset/ecmwf-reanalysis-v5&quot;&gt;ERA5 global weather reanalysis&lt;/a&gt; product:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It has a resolution of 0.25 degrees, at an hourly frequency.&lt;/li&gt;
&lt;li&gt;This means that there are 720x1440x365x24 = 9 billion data points per variable per year.&lt;/li&gt;
&lt;li&gt;This type of data is usually represented as &lt;a href=&quot;https://en.wikipedia.org/wiki/Single-precision_floating-point_format&quot;&gt;32-bit floating points numbers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;32 bits equals 4 bytes, times 9 billion; approximately 36 GB/year. Per variable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As soon as you want to analyze multiple years, for multiple variables, your required storage can quickly reach dozens of terabytes. Storing all this data can not only be prohibitively difficult or expensive, it also significantly increases your carbon footprint. Luckily, there are multiple ways to reduce the file size of netCDF files, with various up- and downsides.&lt;/p&gt;
&lt;h3 id=&quot;lossless-compression&quot;&gt;Lossless compression**&lt;/h3&gt;
&lt;p&gt;You are probably familiar with putting files on your computer in a zip folder. This can significantly reduce their size (if the data is not already compressed yet):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;627&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-b8c718e0.DGm5X3sc_lkybk.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Lossless compression of a simple 19 kB python code file&lt;/em&gt;You can then retrieve the exact files from the zip folder, without any loss of information. This is called “lossless” compression. Many files on your computer are compressed in this way already (for example, Microsoft Office files, or PDF documents).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lossy compression&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A different compression method you probably have encountered before is lossy compression. Lossy compression is often applied to audio, images and video to dramatically reduce their size (~10x for audio or still images, 100x for video), with little &lt;em&gt;perceived&lt;/em&gt; quality loss.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;200&quot; height=&quot;200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-74813b92.BawBpZT5_ZYuTqU.webp&quot; srcset=&quot;&quot;&gt;
*Very lossy JPEG compression versus lossless PNG. Source: *&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Comparison_of_JPEG_and_PNG.png&quot;&gt;&lt;em&gt;Wikimedia&lt;/em&gt;&lt;/a&gt;A downside of lossy compression is that each time you open the data and would write it away lossily again, additional compression artifacts are introduced. This will cause a gradual degradation in data quality.&lt;/p&gt;
&lt;h2 id=&quot;compressing-netcdf-files&quot;&gt;Compressing netCDF files&lt;/h2&gt;
&lt;p&gt;As a quick refresher, we need to discuss how netCDF files are structured.&lt;/p&gt;
&lt;p&gt;NetCDF files organize the data per variable. Each variable in turn is split up in different “chunks”. These chunks correspond to subsets of the full array. For example, data can be chunked only in time, where each chunk represents the entire physical domain (latitude &amp;#x26; longitude) for a single time coordinate.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;211&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-16368190.DhbsZa2l_ZXGA1a.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Graphical representation of chunks in the xarray python package, using Dask&lt;/em&gt;These chunks are read into memory one at a time, so for any operations it is important that the chunks fit your analysis for efficiency.&lt;/p&gt;
&lt;p&gt;The actual underlying data can be stored as 32-bit floating point numbers on disk, but there are a few options for compression.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lossless netCDF compression&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just like with text files or other documents, lossless compression is possible for netCDF files. The more repetitious your data is, the easier it is for lossless compression algorithms to compress your data.&lt;/p&gt;
&lt;p&gt;cdo -z zip 4 … # where 4 is the compression level (1 - 9)In Python, with the popular ‘xarray’ package, you can instead do:&lt;/p&gt;
&lt;p&gt;import xarray as xr&lt;/p&gt;
&lt;p&gt;ds = xr.open_dataset(“my_dataset.nc”)
encoding = {“my_variable”: {“zlib”: True, “complevel”: 4}}
ds.to_netcdf(“compressed_dataset.nc”, encoding=encoding)In many cases applying lossless compression to your data can reduce the size on disk by 20–50%. This comes at a cost of slightly more CPU use, while disk I/O usage is lower.&lt;/p&gt;
&lt;p&gt;The exact impact on your analysis speed will depend on your system, but unless you have a slow CPU and a blazingly fast disk your further analyses will likely be faster when you compress your data. Therefore it’s best to default to using some form of lossless compression on your netCDF files, unless you have a specific reason not to.&lt;/p&gt;
&lt;p&gt;Lossy netCDF compression**&lt;/p&gt;
&lt;p&gt;As stated earlier, unlike lossless compression, lossy compression does not preserve the full original data. Some of the original resolution can be lost, while offering a much smaller file size as well as a faster read speed.&lt;/p&gt;
&lt;p&gt;Often some loss of resolution is not a problem, as 32-bit floating point numbers offer more precision than many measurements or model data realistically have.&lt;/p&gt;
&lt;p&gt;One way of lossy compression which is well supported by netCDF is encoding floating point numbers to integers. This is usually done with 16-bit unsigned integers: whole numbers ranging from 0 to 65,535. The floating point numbers can then be mapped to this range.&lt;/p&gt;
&lt;p&gt;For example; as the lowest ambient air temperature ever recorded on earth is 184 K, and the highest 330 K, giving a range of 146 K. To convert the temperature, you take the integer value, multiply it with a ‘scale factor’, and add the offset. The temperature range can thus be divided over 65,535 discrete values, translating into a maximum resolution of ~2.23 mK, which is a much higher resolution than most scientific air temperature sensors. Your offset here would be 184 K.&lt;/p&gt;
&lt;p&gt;Integer encoding works very well for climate data as the range of values that you can expect should be very well constrained. This allows you to make informed estimates of what sufficient precision is for these variables, while still significantly reducing the size of the data on disk.&lt;/p&gt;
&lt;p&gt;When using integer encoding in xarray you can specify the encoding as such:&lt;/p&gt;
&lt;p&gt;import xarray as xr**
ds = xr.open_dataset(“my_dataset.nc”)&lt;/p&gt;
&lt;p&gt;fvalue = 65535  # fill value for missing values
scale = 0.005  # store temperature in 5 mK increments
offset = 0  # Kelvin is abolute: no offset required&lt;/p&gt;
&lt;p&gt;encoding = {
“my_temperature_variable”:
{
‘_FillValue’: fvalue, ‘scale_factor’: scale, ‘add_offset’: offset, ‘dtype’: ‘int16’,
“zlib”: True, “complevel”: 4,  # you can still use lossless compression!
},
}&lt;/p&gt;
&lt;p&gt;ds.to_netcdf(“compressed_dataset.nc”, encoding=encoding)For Climate Data Operators users, the &lt;a href=&quot;https://code.mpimet.mpg.de/projects/cdo/embedded/index.html#x1-1130002.2.4&quot;&gt;“pack” operator&lt;/a&gt; is available for this purpose.&lt;/p&gt;
&lt;p&gt;Compression ‘filters’**&lt;/p&gt;
&lt;p&gt;Lastly, HDF5; the underlying data format of netCDF4 files, has “filter plugins” available. These plugins allow you to use other lossy compression algorithms for your netCDF data. These filters are a more advanced use case and not as easy to set up as the other compression methods.&lt;/p&gt;
&lt;p&gt;Some publications (e.g., &lt;a href=&quot;https://gmd.copernicus.org/articles/17/8909/2024/&quot;&gt;Prims, 2024&lt;/a&gt;, and &lt;a href=&quot;https://gmd.copernicus.org/articles/12/4099/2019/#section14&quot;&gt;Delauney, 2019&lt;/a&gt;)) have studied the effect of these on netCDF and numerical weather prediction data specifically.&lt;/p&gt;
&lt;p&gt;Depending on the variables, these compression algorithms can reduce the data size on disk by a factor of 5–150. However, unlike integer compression, the effects of these compression algorithms on your data is not as easily predictable, and you might need to do a sensitivity study for your own application.&lt;/p&gt;
&lt;p&gt;However, there are use cases such as many climate model ensembles where compressing the data lossily could be a way to store data that would otherwise be too large to store.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Compression and chunks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As the underlying data of each variable in a netCDF file is organized in “chunks”, the compression algorithm is applied per chunk. *This allows you to still load individual chunks of data without requiring to load and decompress the entire file.&lt;/p&gt;
&lt;p&gt;Therefore it is important to organize these chunks in a way that aligns well with your intended usage; for example, either looking at the full time series for a single location, or the entire world at a single point in time. This will enable you to read parts of your full netCDF file very quickly and store them efficiently.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Compressing your netCDF data can reduce your disk usage significantly, which allows you to store or share data more easily. For most users lossless compression is the most straightforward and should be applied by default.&lt;/p&gt;
&lt;p&gt;For many others, where storage space is a constraint, storing your floating point numbers as 16-bit integers is a predictable way of compressing your data further. Other lossy algorithms are available, but are generally too complex to use for most users.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Keeping your scientific data files small&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-e8dca7c8.DvWanidn_1mq1og.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@jasonpofahlphotography?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Jason Pofahl&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/keeping-your-scientific-data-files-small-98bdacab.BAgZz0KS.jpeg" medium="image"/><author>Bart Schilperoort</author></item><item><title>Solving the mystery of the missing symbols! (part II)</title><link>https://blog2.esciencecenter.nl/posts/2025-04-22---solving-the-mystery-of-the-missing-symbols-part-ii</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-04-22---solving-the-mystery-of-the-missing-symbols-part-ii</guid><description>&lt;h2 id=&quot;this-is-the-conclusion-to-the-story-i-wrote-about-earlier&quot;&gt;&lt;em&gt;This is the conclusion to the story I &lt;em&gt;&lt;a href=&quot;https://medium.com/escience-center/a-debugging-journey-into-the-unknown-a2fa291bfb35&quot;&gt;&lt;em&gt;wrote about&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; earlier.&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;In that earlier post, we were investigating why the MingW-w64 build of DuckDB fails to export the C-API symbols in the final DLL. We identified that the issue was introduced by the commit &lt;a href=&quot;https://github.com/duckdb/duckdb/commit/d1ea1538c9217fb536485f1500f04a0b55b1e584&quot;&gt;d1ea1538&lt;/a&gt;. However, we could not ascertain the underlying reason for the problem. To take this further, let us try to isolate which part of the change was the cause.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Solving the mystery of the missing symbols! (part II)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/solving-the-mystery-of-the-missing-symbo-41382a82.CPSPwa2V_Z2ldSdg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@tomasmartinez?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Tomas Martinez&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-dead-end&quot;&gt;A dead-end&lt;/h2&gt;
&lt;p&gt;To identify the source file responsible for the bug, we can start by inspecting the different build artifacts and checking for the C-API symbols. But first, we need to log all the build commands. It is much easier to do this with Make than Ninja (default generator for DuckDB). We can choose our generator by calling CMake as:&lt;/p&gt;
&lt;p&gt;$ cmake -G “Unix Makefiles” …We can then log all the build commands by starting a verbose build with Make:&lt;/p&gt;
&lt;p&gt;$ VERBOSE=1 make -j6 |&amp;#x26; tee build.logWith all the build commands recorded to a log file, I searched for commands that create the shared library &lt;code&gt;libduckdb.dll&lt;/code&gt; and narrowed it down to the following set of build commands:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;/usr/bin/cmake -E rm -f CMakeFiles/duckdb.dir/objects.a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;sr&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;mak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;bj&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /usr/bin/x86_64-w64-mingw32-ar qc CMakeFiles/duckdb.dir/objects.a @CMakeFiles/duckdb.dir/objects1.rsp
$ /usr/lib64/ccache/x86_64-w64-mingw32-g++ -O3 -DNDEBUG -shared -o libduckdb.dll &lt;br&gt;
-Wl,—out-implib,libduckdb.dll.a -Wl,—major-image-version,0,—minor-image-version,0 -Wl,—whole-archive &lt;br&gt;
CMakeFiles/duckdb.dir/objects.a -Wl,—no-whole-archive @CMakeFiles/duckdb.dir/linkLibs.rspGoing through the steps individually, we will see that even though the symbols are present in the earlier steps, the final library creation step drops them.&lt;/p&gt;
&lt;h2 id=&quot;tracing-through-the-build-steps&quot;&gt;Tracing through the build steps&lt;/h2&gt;
&lt;p&gt;Let us first look for the object file that has the C-API symbols.&lt;/p&gt;
&lt;p&gt;$ tr ’ ’ ‘\n’ &amp;#x3C;CMakeFiles/duckdb.dir/objects1.rsp | grep capi.cpp
main/capi/CMakeFiles/duckdb_main_capi.dir/ub_duckdb_main_capi.cpp.objWe can then check for the C-API symbols in the object, and confirm that the object file is included in the objects archive.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;0000000000004&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;60&lt;/mn&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;nm -C main/capi/CMakeFiles/duckdb_main_capi.dir/ub_duckdb_main_capi.cpp.obj | grep duckdb_vector_size
0000000000004f60 T duckdb_vector_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nm&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;pp&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;bj&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0000000000004&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /usr/bin/x86_64-w64-mingw32-ar t CMakeFiles/duckdb.dir/objects.a | grep capi.cpp
ub_duckdb_main_capi.cpp.objIf we check for the C-API symbols again in the archive file, we see they are present and publicly visible (exported).&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;0000000000004&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;60&lt;/mn&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;nm -C CMakeFiles/duckdb.dir/objects.a | grep duckdb_vector_size
0000000000004f60 T duckdb_vector_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nm&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;bj&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0000000000004&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; winedump -j export CMakeFiles/duckdb.dir/objects.a | grep duckdb_vector_size
31a0ae4 duckdb_vector_sizeFinally, we can create the shared library by calling the linker.&lt;/p&gt;
&lt;p&gt;$ /usr/lib64/ccache/x86_64-w64-mingw32-g++ -O3 -DNDEBUG -shared -o libduckdb.dll &lt;br&gt;
-Wl,—out-implib,libduckdb.dll.a -Wl,—major-image-version,0,—minor-image-version,0 -Wl,—whole-archive &lt;br&gt;
CMakeFiles/duckdb.dir/objects.a -Wl,—no-whole-archive @CMakeFiles/duckdb.dir/linkLibs.rspWe see that while the C-API symbols are present, they are not exported!&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;00000001&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mn&gt;116&lt;/mn&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;nm -C libduckdb.dll | grep duckdb_vector_size
00000001f3d116e0 T duckdb_vector_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nm&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ib&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;00000001&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;116&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; winedump -j export libduckdb.dll | grep duckdb_vector_size # no match&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While not helpful on its own, the observation that symbols are not exported in the final linking step that creates the DLL will make sense later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;a-clue&quot;&gt;A clue&lt;/h2&gt;
&lt;p&gt;Since we could not already isolate the issue to a source file, next, I decided to “bisect” the contents of the problem commit. As the issue is with C-API symbols, I started with the files that have these symbols:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/include/duckdb.h&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/main/capi/aggregate_function-c.cpp&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test/api/capi/capi_aggregate_functions.cpp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I commented out parts of the above files, while ensuring the build still succeeds, and checking for the C-API symbols in the final DLL in the usual way with &lt;code&gt;nm&lt;/code&gt; and &lt;code&gt;winedump&lt;/code&gt;. This led me to discover that the &lt;em&gt;problem disappears if we reorder the include headers&lt;/em&gt; in &lt;code&gt;src/main/capi/aggregate_function-c.cpp&lt;/code&gt;. You can see the change in this PR: &lt;a href=&quot;https://github.com/duckdb/duckdb/pull/16396/files&quot;&gt;duckdb/duckdb#16396&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;diff —git a/src/main/capi/aggregate_function-c.cpp b/src/main/capi/aggregate_function-c.cpp
index 43ddfdbc074a..1379f652d669 100644
--- a/src/main/capi/aggregate_function-c.cpp
+++ b/src/main/capi/aggregate_function-c.cpp
@@ -1,9 +1,11 @@
+// clang-format off
+#include “duckdb/main/capi/capi_internal.hpp”
+// clang-format on
#include “duckdb/catalog/catalog.hpp”
#include “duckdb/common/type_visitor.hpp”
#include “duckdb/common/types.hpp”
#include “duckdb/function/function.hpp”
#include “duckdb/function/scalar_function.hpp”
-#include “duckdb/main/capi/capi_internal.hpp”
#include “duckdb/main/client_context.hpp”
#include “duckdb/parser/parsed_data/create_aggregate_function_info.hpp”
#include “duckdb/planner/expression/bound_function_expression.hpp”This is, of course, not the correct solution since there should not be any dependence on the order in which we include headers. It is indicative of an underlying bug. This means some definition in the headers is being overridden silently. This can only happen for preprocessor macros; anything else would trigger a compilation error.&lt;/p&gt;
&lt;h2 id=&quot;solution-to-the-mystery&quot;&gt;Solution to the mystery!&lt;/h2&gt;
&lt;p&gt;After further investigation from DuckDB core developer Mark Raasveldt, the issue was resolved in this PR: &lt;a href=&quot;https://github.com/duckdb/duckdb/pull/16397&quot;&gt;duckdb/duckdb#13697&lt;/a&gt;. So, what was the issue?&lt;/p&gt;
&lt;p&gt;When building shared libraries for Windows, the public API has to be marked for export. This is done by adding the &lt;code&gt;__declspec(dllexport)&lt;/code&gt; &lt;a href=&quot;https://github.com/suvayu/suvayu/blob/master/blog/2025-02-15-duckdb-julia-windows.md#symbol-visibility-in-windows-dlls&quot;&gt;attribute&lt;/a&gt; to the relevant symbols. In the DuckDB codebase this is done by defining a macro &lt;code&gt;DUCKDB_API&lt;/code&gt; that expands to that attribute. However, there were two such definitions, they were in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/include/duckdb.h&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/include/duckdb/common/winapi.hpp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Superficially, they seem equivalent, however, they are actually used in slightly different contexts. The macro defined in &lt;code&gt;duckdb.h&lt;/code&gt; is used to annotate symbols that are part of the C-API*. Whereas the macro defined in &lt;code&gt;winapi.hpp&lt;/code&gt; is used to mark symbols that comprise the &lt;em&gt;C++ API&lt;/em&gt;. In an earlier commit (&lt;a href=&quot;https://github.com/duckdb/duckdb/commit/367595af51b459d07121647bc2de1beabc836e0c&quot;&gt;367595af&lt;/a&gt;), the macro defined in &lt;code&gt;winapi.hpp&lt;/code&gt; was changed to exclude MingW builds.&lt;/p&gt;
&lt;p&gt;diff —git a/src/include/duckdb/common/winapi.hpp b/src/include/duckdb/common/winapi.hpp
index 2cff5d12d4..65dd89975e 100644
--- a/src/include/duckdb/common/winapi.hpp
+++ b/src/include/duckdb/common/winapi.hpp
@@ -9,7 +9,7 @@
#pragma once&lt;/p&gt;
&lt;p&gt;#ifndef DUCKDB_API
-#ifdef _WIN32
+#if defined(_WIN32) &amp;#x26;&amp;#x26; !defined(&lt;strong&gt;MINGW32&lt;/strong&gt;)
#if defined(DUCKDB_BUILD_LIBRARY) &amp;#x26;&amp;#x26; !defined(DUCKDB_BUILD_LOADABLE_EXTENSION)
#define DUCKDB_API __declspec(dllexport)
#else&lt;/p&gt;
&lt;h2 id=&quot;the-reason--the-fix&quot;&gt;The reason &amp;#x26; the fix&lt;/h2&gt;
&lt;p&gt;When exporting symbols, MingW normally excludes inline functions (see &lt;code&gt;man x86_64-w64-mingw32-g++&lt;/code&gt; and search for &lt;code&gt;-fkeep-inline-functions&lt;/code&gt;). The macro redefinition handles this case by excluding symbol export for MingW.&lt;/p&gt;
&lt;p&gt;Now, in the DuckDB source, depending on which definition is seen first, symbols may or may not be exported. This, of course, depends on the order of the include headers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;duckdb.h&lt;/code&gt; is seen first, symbols are exported correctly, on the other hand&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;winapi.hpp&lt;/code&gt; is seen first, symbols are not exported.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The final fix was to rename one of the macros to make the two definitions distinct so that they do not interfere with each other; i.e.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;duckdb.h&lt;/code&gt; was renamed to &lt;code&gt;DUCKDB_C_API&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;winapi.hpp&lt;/code&gt; remains unchanged.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-did-we-learn&quot;&gt;What did we learn?&lt;/h2&gt;
&lt;p&gt;After this resolution, any project reliant on this build can update to the latest version of DuckDB starting from version 1.2.1. In our case that is the Julia binding for DuckDB, &lt;code&gt;DuckDB.jl&lt;/code&gt;. If we look at the original issue: &lt;a href=&quot;https://github.com/duckdb/duckdb/issues/13911&quot;&gt;duckdb/duckdb#13911&lt;/a&gt;, there are many different projects reliant on it, so the impact of this fix is quite broad!&lt;/p&gt;
&lt;p&gt;During this investigation, we also learnt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bisection is an incredibly effective idea that can be used in many different contexts, and&lt;/li&gt;
&lt;li&gt;macro hygiene is important in C/C++ code bases.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;this-is-the-conclusion-to-the-story-i-wrote-about-earlier&quot;&gt;&lt;em&gt;This is the conclusion to the story I &lt;em&gt;&lt;a href=&quot;https://medium.com/escience-center/a-debugging-journey-into-the-unknown-a2fa291bfb35&quot;&gt;&lt;em&gt;wrote about&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; earlier.&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;In that earlier post, we were investigating why the MingW-w64 build of DuckDB fails to export the C-API symbols in the final DLL. We identified that the issue was introduced by the commit &lt;a href=&quot;https://github.com/duckdb/duckdb/commit/d1ea1538c9217fb536485f1500f04a0b55b1e584&quot;&gt;d1ea1538&lt;/a&gt;. However, we could not ascertain the underlying reason for the problem. To take this further, let us try to isolate which part of the change was the cause.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Solving the mystery of the missing symbols! (part II)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/solving-the-mystery-of-the-missing-symbo-41382a82.CPSPwa2V_Z2ldSdg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@tomasmartinez?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Tomas Martinez&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-dead-end&quot;&gt;A dead-end&lt;/h2&gt;
&lt;p&gt;To identify the source file responsible for the bug, we can start by inspecting the different build artifacts and checking for the C-API symbols. But first, we need to log all the build commands. It is much easier to do this with Make than Ninja (default generator for DuckDB). We can choose our generator by calling CMake as:&lt;/p&gt;
&lt;p&gt;$ cmake -G “Unix Makefiles” …We can then log all the build commands by starting a verbose build with Make:&lt;/p&gt;
&lt;p&gt;$ VERBOSE=1 make -j6 |&amp;#x26; tee build.logWith all the build commands recorded to a log file, I searched for commands that create the shared library &lt;code&gt;libduckdb.dll&lt;/code&gt; and narrowed it down to the following set of build commands:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;/usr/bin/cmake -E rm -f CMakeFiles/duckdb.dir/objects.a&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;sr&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;mak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;bj&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /usr/bin/x86_64-w64-mingw32-ar qc CMakeFiles/duckdb.dir/objects.a @CMakeFiles/duckdb.dir/objects1.rsp
$ /usr/lib64/ccache/x86_64-w64-mingw32-g++ -O3 -DNDEBUG -shared -o libduckdb.dll &lt;br&gt;
-Wl,—out-implib,libduckdb.dll.a -Wl,—major-image-version,0,—minor-image-version,0 -Wl,—whole-archive &lt;br&gt;
CMakeFiles/duckdb.dir/objects.a -Wl,—no-whole-archive @CMakeFiles/duckdb.dir/linkLibs.rspGoing through the steps individually, we will see that even though the symbols are present in the earlier steps, the final library creation step drops them.&lt;/p&gt;
&lt;h2 id=&quot;tracing-through-the-build-steps&quot;&gt;Tracing through the build steps&lt;/h2&gt;
&lt;p&gt;Let us first look for the object file that has the C-API symbols.&lt;/p&gt;
&lt;p&gt;$ tr ’ ’ ‘\n’ &amp;#x3C;CMakeFiles/duckdb.dir/objects1.rsp | grep capi.cpp
main/capi/CMakeFiles/duckdb_main_capi.dir/ub_duckdb_main_capi.cpp.objWe can then check for the C-API symbols in the object, and confirm that the object file is included in the objects archive.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;0000000000004&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;60&lt;/mn&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;nm -C main/capi/CMakeFiles/duckdb_main_capi.dir/ub_duckdb_main_capi.cpp.obj | grep duckdb_vector_size
0000000000004f60 T duckdb_vector_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nm&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3361em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;m&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ai&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;pp&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;bj&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0000000000004&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /usr/bin/x86_64-w64-mingw32-ar t CMakeFiles/duckdb.dir/objects.a | grep capi.cpp
ub_duckdb_main_capi.cpp.objIf we check for the C-API symbols again in the archive file, we see they are present and publicly visible (exported).&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;0000000000004&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;60&lt;/mn&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;nm -C CMakeFiles/duckdb.dir/objects.a | grep duckdb_vector_size
0000000000004f60 T duckdb_vector_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nm&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;ak&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;bj&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0000000000004&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; winedump -j export CMakeFiles/duckdb.dir/objects.a | grep duckdb_vector_size
31a0ae4 duckdb_vector_sizeFinally, we can create the shared library by calling the linker.&lt;/p&gt;
&lt;p&gt;$ /usr/lib64/ccache/x86_64-w64-mingw32-g++ -O3 -DNDEBUG -shared -o libduckdb.dll &lt;br&gt;
-Wl,—out-implib,libduckdb.dll.a -Wl,—major-image-version,0,—minor-image-version,0 -Wl,—whole-archive &lt;br&gt;
CMakeFiles/duckdb.dir/objects.a -Wl,—no-whole-archive @CMakeFiles/duckdb.dir/linkLibs.rspWe see that while the C-API symbols are present, they are not exported!&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∣&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;00000001&lt;/mn&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mn&gt;116&lt;/mn&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;nm -C libduckdb.dll | grep duckdb_vector_size
00000001f3d116e0 T duckdb_vector_size&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nm&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ib&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∣&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;00000001&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;116&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot;&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; winedump -j export libduckdb.dll | grep duckdb_vector_size # no match&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While not helpful on its own, the observation that symbols are not exported in the final linking step that creates the DLL will make sense later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;a-clue&quot;&gt;A clue&lt;/h2&gt;
&lt;p&gt;Since we could not already isolate the issue to a source file, next, I decided to “bisect” the contents of the problem commit. As the issue is with C-API symbols, I started with the files that have these symbols:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/include/duckdb.h&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/main/capi/aggregate_function-c.cpp&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;test/api/capi/capi_aggregate_functions.cpp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I commented out parts of the above files, while ensuring the build still succeeds, and checking for the C-API symbols in the final DLL in the usual way with &lt;code&gt;nm&lt;/code&gt; and &lt;code&gt;winedump&lt;/code&gt;. This led me to discover that the &lt;em&gt;problem disappears if we reorder the include headers&lt;/em&gt; in &lt;code&gt;src/main/capi/aggregate_function-c.cpp&lt;/code&gt;. You can see the change in this PR: &lt;a href=&quot;https://github.com/duckdb/duckdb/pull/16396/files&quot;&gt;duckdb/duckdb#16396&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;diff —git a/src/main/capi/aggregate_function-c.cpp b/src/main/capi/aggregate_function-c.cpp
index 43ddfdbc074a..1379f652d669 100644
--- a/src/main/capi/aggregate_function-c.cpp
+++ b/src/main/capi/aggregate_function-c.cpp
@@ -1,9 +1,11 @@
+// clang-format off
+#include “duckdb/main/capi/capi_internal.hpp”
+// clang-format on
#include “duckdb/catalog/catalog.hpp”
#include “duckdb/common/type_visitor.hpp”
#include “duckdb/common/types.hpp”
#include “duckdb/function/function.hpp”
#include “duckdb/function/scalar_function.hpp”
-#include “duckdb/main/capi/capi_internal.hpp”
#include “duckdb/main/client_context.hpp”
#include “duckdb/parser/parsed_data/create_aggregate_function_info.hpp”
#include “duckdb/planner/expression/bound_function_expression.hpp”This is, of course, not the correct solution since there should not be any dependence on the order in which we include headers. It is indicative of an underlying bug. This means some definition in the headers is being overridden silently. This can only happen for preprocessor macros; anything else would trigger a compilation error.&lt;/p&gt;
&lt;h2 id=&quot;solution-to-the-mystery&quot;&gt;Solution to the mystery!&lt;/h2&gt;
&lt;p&gt;After further investigation from DuckDB core developer Mark Raasveldt, the issue was resolved in this PR: &lt;a href=&quot;https://github.com/duckdb/duckdb/pull/16397&quot;&gt;duckdb/duckdb#13697&lt;/a&gt;. So, what was the issue?&lt;/p&gt;
&lt;p&gt;When building shared libraries for Windows, the public API has to be marked for export. This is done by adding the &lt;code&gt;__declspec(dllexport)&lt;/code&gt; &lt;a href=&quot;https://github.com/suvayu/suvayu/blob/master/blog/2025-02-15-duckdb-julia-windows.md#symbol-visibility-in-windows-dlls&quot;&gt;attribute&lt;/a&gt; to the relevant symbols. In the DuckDB codebase this is done by defining a macro &lt;code&gt;DUCKDB_API&lt;/code&gt; that expands to that attribute. However, there were two such definitions, they were in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/include/duckdb.h&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/include/duckdb/common/winapi.hpp&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Superficially, they seem equivalent, however, they are actually used in slightly different contexts. The macro defined in &lt;code&gt;duckdb.h&lt;/code&gt; is used to annotate symbols that are part of the C-API*. Whereas the macro defined in &lt;code&gt;winapi.hpp&lt;/code&gt; is used to mark symbols that comprise the &lt;em&gt;C++ API&lt;/em&gt;. In an earlier commit (&lt;a href=&quot;https://github.com/duckdb/duckdb/commit/367595af51b459d07121647bc2de1beabc836e0c&quot;&gt;367595af&lt;/a&gt;), the macro defined in &lt;code&gt;winapi.hpp&lt;/code&gt; was changed to exclude MingW builds.&lt;/p&gt;
&lt;p&gt;diff —git a/src/include/duckdb/common/winapi.hpp b/src/include/duckdb/common/winapi.hpp
index 2cff5d12d4..65dd89975e 100644
--- a/src/include/duckdb/common/winapi.hpp
+++ b/src/include/duckdb/common/winapi.hpp
@@ -9,7 +9,7 @@
#pragma once&lt;/p&gt;
&lt;p&gt;#ifndef DUCKDB_API
-#ifdef _WIN32
+#if defined(_WIN32) &amp;#x26;&amp;#x26; !defined(&lt;strong&gt;MINGW32&lt;/strong&gt;)
#if defined(DUCKDB_BUILD_LIBRARY) &amp;#x26;&amp;#x26; !defined(DUCKDB_BUILD_LOADABLE_EXTENSION)
#define DUCKDB_API __declspec(dllexport)
#else&lt;/p&gt;
&lt;h2 id=&quot;the-reason--the-fix&quot;&gt;The reason &amp;#x26; the fix&lt;/h2&gt;
&lt;p&gt;When exporting symbols, MingW normally excludes inline functions (see &lt;code&gt;man x86_64-w64-mingw32-g++&lt;/code&gt; and search for &lt;code&gt;-fkeep-inline-functions&lt;/code&gt;). The macro redefinition handles this case by excluding symbol export for MingW.&lt;/p&gt;
&lt;p&gt;Now, in the DuckDB source, depending on which definition is seen first, symbols may or may not be exported. This, of course, depends on the order of the include headers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;duckdb.h&lt;/code&gt; is seen first, symbols are exported correctly, on the other hand&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;winapi.hpp&lt;/code&gt; is seen first, symbols are not exported.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The final fix was to rename one of the macros to make the two definitions distinct so that they do not interfere with each other; i.e.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;duckdb.h&lt;/code&gt; was renamed to &lt;code&gt;DUCKDB_C_API&lt;/code&gt;, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DUCKDB_API&lt;/code&gt; in &lt;code&gt;winapi.hpp&lt;/code&gt; remains unchanged.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-did-we-learn&quot;&gt;What did we learn?&lt;/h2&gt;
&lt;p&gt;After this resolution, any project reliant on this build can update to the latest version of DuckDB starting from version 1.2.1. In our case that is the Julia binding for DuckDB, &lt;code&gt;DuckDB.jl&lt;/code&gt;. If we look at the original issue: &lt;a href=&quot;https://github.com/duckdb/duckdb/issues/13911&quot;&gt;duckdb/duckdb#13911&lt;/a&gt;, there are many different projects reliant on it, so the impact of this fix is quite broad!&lt;/p&gt;
&lt;p&gt;During this investigation, we also learnt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bisection is an incredibly effective idea that can be used in many different contexts, and&lt;/li&gt;
&lt;li&gt;macro hygiene is important in C/C++ code bases.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/solving-the-mystery-of-the-missing-symbo-41382a82.CPSPwa2V.jpg" medium="image"/><author>Suvayu</author></item><item><title>Introduction to Deep Learning with Python</title><link>https://blog2.esciencecenter.nl/posts/2025-03-25---introduction-to-deep-learning-with-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-03-25---introduction-to-deep-learning-with-python</guid><description>&lt;h2 id=&quot;written-by-sven-van-der-burg-carsten-schnober-sarah-m-brown-and-toby-hodges&quot;&gt;Written by &lt;a href=&quot;https://www.esciencecenter.nl/team/sven-van-der-burg/&quot;&gt;Sven van der Burg&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/carsten-schnober/&quot;&gt;Carsten Schnober&lt;/a&gt;, &lt;a href=&quot;https://carpentries.org/blog/author/sarah-m-brown/&quot;&gt;Sarah M. Brown&lt;/a&gt; and &lt;a href=&quot;https://carpentries.org/blog/author/toby-hodges/&quot;&gt;Toby Hodges&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Engineers and instructors at the eScience Center have developed lots of open source lesson materials for the workshops we teach. One example is the lesson material for &lt;a href=&quot;https://carpentries-lab.github.io/deep-learning-intro/&quot;&gt;&lt;em&gt;Introduction to Deep Learning&lt;/em&gt;&lt;/a&gt;*, *which was recently accepted into the peer-reviewed lesson material collection in the &lt;a href=&quot;https://carpentries-lab.org/&quot;&gt;Carpentries Lab&lt;/a&gt;. In this post you can read more about the lesson and its development.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Introduction to Deep Learning with Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/introduction-to-deep-learning-with-pytho-6c0721f9.BkgMA3vv_239jHH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@scottwebb?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Scott Webb&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Carpentries Lab was set up as a space for peer-reviewed lessons developed by &lt;a href=&quot;https://carpentries.org/about-us/&quot;&gt;the Carpentries community&lt;/a&gt;. Designed to complement &lt;a href=&quot;https://carpentries-incubator.org/&quot;&gt;The Carpentries Incubator&lt;/a&gt;, where the community collaborates on the development of new lessons on a wide range of topics, the Lab is a platform for open peer-review of community-developed lessons and for hosting the lessons that have passed through that review process.&lt;/p&gt;
&lt;p&gt;The text below was originally published on &lt;a href=&quot;https://carpentries.org/blog/2025/03/carpentries-lab-introduction-to-deep-learning-with-python/&quot;&gt;the Carpentries blog&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;about-the-curriculum&quot;&gt;About the curriculum&lt;/h2&gt;
&lt;p&gt;The use of deep learning has seen a sharp increase in popularity and applicability over the last decade. While deep learning can be a useful tool for researchers from a wide range of domains, taking the first steps in the world of deep learning can be somewhat intimidating.&lt;/p&gt;
&lt;p&gt;Introduction to Deep Learning covers the fundamentals of deep learning in a practical and hands-on manner, for researchers who want to apply deep learning in their research. By the end of the course, students will be able to train their first neural network and understand the subsequent steps needed to improve the model.&lt;/p&gt;
&lt;p&gt;The lesson can be taught in a 2-day or 4 half-day workshop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Introduction to Deep Learning with Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;425&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/introduction-to-deep-learning-with-pytho-01ca30a5.BRpGGPlp_Z4xKIB.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Part of the &lt;em&gt;&lt;a href=&quot;https://carpentries-lab.github.io/deep-learning-intro/3-monitor-the-model.html&quot;&gt;&lt;em&gt;Monitor the training Process&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; episode of the lesson.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-brief-history-of-the-development-of-this-lesson&quot;&gt;A brief history of the development of this lesson&lt;/h2&gt;
&lt;p&gt;What follows is a year-by-year history of the main contributors to the lesson. Of course, GitHub keeps the score, and all contributions to the commit history, big and, especially, small, can be better tracked &lt;a href=&quot;https://github.com/carpentries-lab/deep-learning-intro/graphs/contributors&quot;&gt;in this interactive contributor graph&lt;/a&gt;. Over the years 30 people contributed to this lesson!&lt;/p&gt;
&lt;p&gt;The development of the lesson started in 2020 in a collaboration between &lt;a href=&quot;https://github.com/bpmweel&quot;&gt;Berend Weel&lt;/a&gt; and &lt;a href=&quot;https://github.com/florian-huber&quot;&gt;Florian Huber&lt;/a&gt; (both at the Netherlands eScience Center at the time), &lt;a href=&quot;https://github.com/psteinb&quot;&gt;Peter Steinbach&lt;/a&gt;, &lt;a href=&quot;https://github.com/colinsauze&quot;&gt;Colin Sauze&lt;/a&gt;, &lt;a href=&quot;https://github.com/samumantha&quot;&gt;Samantha Wittke&lt;/a&gt;, and &lt;a href=&quot;https://github.com/tobyhodges&quot;&gt;Toby Hodges&lt;/a&gt;. During this period the main design of the lesson was drafted and the first pilot workshops were given.&lt;/p&gt;
&lt;p&gt;During the year of 2021, Dafne van Kuppevelt, Djura Smits, and Sven van der Burg from the Netherlands eScience Center became involved and by the year 2022 Sven and Djura were the main contributors. In this period the lesson was taught a lot by various organisations and all feedback went into an ever-improving lesson.&lt;/p&gt;
&lt;p&gt;In the period from 2023 till now the lesson was really polished towards its final shape, thanks to contributions from fresh team members Carsten Schnober and Pranav Chandramouli from the Netherlands eScience Center. This is the period that the lesson was transitioned to The Carpentries Workbench and went through The Carpentries Lab review process.&lt;/p&gt;
&lt;h2 id=&quot;about-the-review-process&quot;&gt;About the review process&lt;/h2&gt;
&lt;p&gt;The curriculum was reviewed in &lt;a href=&quot;https://github.com/carpentries-lab/reviews/issues/25&quot;&gt;a public issue thread on The Carpentries Lab reviews repository&lt;/a&gt;. This was a slightly unusual case because one of the authors is a member of The Carpentries Curriculum Team and was the sole Editor of the Lab at the time of submission. (Three other community members have joined as Editors since.) &lt;a href=&quot;https://github.com/brownsarahm&quot;&gt;Sarah M Brown&lt;/a&gt;, formerly a long-standing member of the Trainers Leadership Committee, accepted an invitation to act as Guest Editor for this review. The authors and Carpentries team are enormously grateful to Sarah for the effort she put in and the diligence she displayed throughout the process. She made several essential contributions as Editor, in particular by encouraging the authors to more deeply explore the choice of example datasets used in the lesson (read more about this below).&lt;/p&gt;
&lt;p&gt;After the authors had responded to Sarah’s initial editorial checks, the curriculum was reviewed in detail by two volunteers from The Carpentries community: &lt;a href=&quot;https://github.com/PaulaNietoG&quot;&gt;Johanna Bayer&lt;/a&gt; and &lt;a href=&quot;https://github.com/mike-ivs&quot;&gt;Mike Laverick&lt;/a&gt; (thanks to Erin Becker for helping to connect Sarah with these reviewers). These reviewers were invited based on their expertise as Carpentries Instructors and their domain knowledge in machine learning and related fields.&lt;/p&gt;
&lt;p&gt;The peer-review process led to a number of improvements to the accessibility of the lesson, with better alternative text descriptions for images and various adjustments to make language clearer and more beginner-friendly. The lesson was made easier to teach by other instructors through the addition and improvement of Instructor Notes, and the explanations of a number of important deep learning concepts were expanded.&lt;/p&gt;
&lt;p&gt;Perhaps most importantly, the Editor highlighted that one of the datasets used as an example in the lesson, the CIFAR-10 dataset, is not available under a clearly-defined license. On closer inspection, the authors were surprised to find that CIFAR-10, a dataset very commonly used for benchmarking in machine learning research, was created with image files scraped from the internet without permission from their original owners.&lt;/p&gt;
&lt;p&gt;Sven van der Burg, one of the leading authors of the lesson, created &lt;a href=&quot;https://zenodo.org/records/10970014&quot;&gt;the “Dollar Street 10” dataset&lt;/a&gt; as an alternative to replace CIFAR-10 in the lesson. Dollar Street 10 is derived from the CC-BY-4.0 licensed Dollar Street Dataset from the Gapminder Project: a collection of images that has been more ethically assembled with an emphasis on ensuring that the data is representative of global diversity and accompanied by accurate metadata. The authors added a callout to the lesson to comment on this change, as they felt it represented a great entry point for a discussion of ethics in data and deep learning during a workshop.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;The development team will of course keep on teaching this lesson at their institutes and keep on improving the lesson. We will have to, since deep learning is such a rapidly moving field. But our main goal is to help as many others as possible to adopt this lesson so that it can be taught around the world!&lt;/p&gt;
&lt;p&gt;The lesson has been submitted to &lt;a href=&quot;https://jose.theoj.org/&quot;&gt;The Journal of Open Source Education&lt;/a&gt; for publication.&lt;/p&gt;
&lt;p&gt;The wider Carpentries community can now &lt;a href=&quot;https://carpentries-lab.github.io/deep-learning-intro/&quot;&gt;find the lesson in The Carpentries Lab&lt;/a&gt;, use and adapt it to teach their own workshops, contribute feedback, and suggest improvements. We hope you find it a helpful resource!&lt;/p&gt;
&lt;h2 id=&quot;become-a-reviewer&quot;&gt;Become a Reviewer&lt;/h2&gt;
&lt;p&gt;The Carpentries Lab is looking for reviewers!** To volunteer to review a lesson in the Lab, please read &lt;a href=&quot;https://github.com/carpentries-lab/reviews/blob/main/docs/reviewer_guide.md&quot;&gt;our Guide for Reviewers&lt;/a&gt;, and &lt;a href=&quot;https://forms.gle/cFD4nVjstTtVYoxg8&quot;&gt;register as a reviewer&lt;/a&gt; so we can contact you when relevant lessons are ready for review.&lt;/p&gt;
&lt;p&gt;Lessons in the Incubator can be submitted for review in the Lab by &lt;a href=&quot;https://github.com/carpentries-lab/reviews/issues/new?assignees=tobyhodges&amp;#x26;labels=review&amp;#x26;template=review_submission.yml&amp;#x26;title=%5BReview%5D%3A+&quot;&gt;opening an issue on the reviews repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;We would like to thank all instructors and helpers that taught the course, and the community of people that left contributions to the project, no matter how big or small.&lt;/p&gt;
&lt;p&gt;We thank The Carpentries for providing such a great framework for developing this lesson material.&lt;/p&gt;
&lt;p&gt;We thank all students enrolled in the workshops that were taught using this lesson material for providing us with feedback.&lt;/p&gt;
&lt;p&gt;Congratulations to the authors for creating an excellent lesson that will prove a useful resource to so many people:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/svenvanderburg&quot;&gt;Sven van der Burg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/florian-huber/&quot;&gt;Florian Huber&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/psteinb/&quot;&gt;Peter Steinbach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/colinsauze/&quot;&gt;Colin Sauze&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/carschno/&quot;&gt;Carsten Schnober&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dsmits/&quot;&gt;Djura Smits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tobyhodges/&quot;&gt;Toby Hodges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bpmweel&quot;&gt;Berend Weel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/cpranav93/&quot;&gt;Pranav Chandramouli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wikfeldt/&quot;&gt;Thor Wikfeldt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/CunliangGeng/&quot;&gt;Cunliang Geng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/qualiaMachine/&quot;&gt;Chris Endemann&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wmotion/&quot;&gt;Giordano Lipari&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/samumantha&quot;&gt;Samantha Wittke&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ashwinvis&quot;&gt;Ashwin V. Mohanan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sstevens2&quot;&gt;Sarah Stevens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/axdy-a&quot;&gt;axdy-a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/code4yonglei&quot;&gt;YL Wang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Morrizzzzz&quot;&gt;Maurice de Kleijn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/laurasootes&quot;&gt;Laura Ootes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/k-dominik&quot;&gt;Dominik Kutra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sunyi000&quot;&gt;Yi Sun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/esclapez&quot;&gt;Lucas Esclapez&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/unode&quot;&gt;Renato Alves&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/miguel-mx&quot;&gt;Miguel A Magaña&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/FenneRiemslagh&quot;&gt;Fenne Riemslagh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dafnevk&quot;&gt;Dafne van Kuppevelt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/annefou&quot;&gt;Anne Fouilloux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And huge thanks again to &lt;a href=&quot;https://github.com/brownsarahm&quot;&gt;Sarah M Brown&lt;/a&gt; for acting as Guest Editor, and to the reviewers, &lt;a href=&quot;https://github.com/likeajumprope&quot;&gt;Johanna Bayer&lt;/a&gt; and &lt;a href=&quot;https://github.com/mike-ivs&quot;&gt;Mike Laverick&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Tue, 25 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;written-by-sven-van-der-burg-carsten-schnober-sarah-m-brown-and-toby-hodges&quot;&gt;Written by &lt;a href=&quot;https://www.esciencecenter.nl/team/sven-van-der-burg/&quot;&gt;Sven van der Burg&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/carsten-schnober/&quot;&gt;Carsten Schnober&lt;/a&gt;, &lt;a href=&quot;https://carpentries.org/blog/author/sarah-m-brown/&quot;&gt;Sarah M. Brown&lt;/a&gt; and &lt;a href=&quot;https://carpentries.org/blog/author/toby-hodges/&quot;&gt;Toby Hodges&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Engineers and instructors at the eScience Center have developed lots of open source lesson materials for the workshops we teach. One example is the lesson material for &lt;a href=&quot;https://carpentries-lab.github.io/deep-learning-intro/&quot;&gt;&lt;em&gt;Introduction to Deep Learning&lt;/em&gt;&lt;/a&gt;*, *which was recently accepted into the peer-reviewed lesson material collection in the &lt;a href=&quot;https://carpentries-lab.org/&quot;&gt;Carpentries Lab&lt;/a&gt;. In this post you can read more about the lesson and its development.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Introduction to Deep Learning with Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/introduction-to-deep-learning-with-pytho-6c0721f9.BkgMA3vv_239jHH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@scottwebb?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Scott Webb&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Carpentries Lab was set up as a space for peer-reviewed lessons developed by &lt;a href=&quot;https://carpentries.org/about-us/&quot;&gt;the Carpentries community&lt;/a&gt;. Designed to complement &lt;a href=&quot;https://carpentries-incubator.org/&quot;&gt;The Carpentries Incubator&lt;/a&gt;, where the community collaborates on the development of new lessons on a wide range of topics, the Lab is a platform for open peer-review of community-developed lessons and for hosting the lessons that have passed through that review process.&lt;/p&gt;
&lt;p&gt;The text below was originally published on &lt;a href=&quot;https://carpentries.org/blog/2025/03/carpentries-lab-introduction-to-deep-learning-with-python/&quot;&gt;the Carpentries blog&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;about-the-curriculum&quot;&gt;About the curriculum&lt;/h2&gt;
&lt;p&gt;The use of deep learning has seen a sharp increase in popularity and applicability over the last decade. While deep learning can be a useful tool for researchers from a wide range of domains, taking the first steps in the world of deep learning can be somewhat intimidating.&lt;/p&gt;
&lt;p&gt;Introduction to Deep Learning covers the fundamentals of deep learning in a practical and hands-on manner, for researchers who want to apply deep learning in their research. By the end of the course, students will be able to train their first neural network and understand the subsequent steps needed to improve the model.&lt;/p&gt;
&lt;p&gt;The lesson can be taught in a 2-day or 4 half-day workshop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Introduction to Deep Learning with Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;425&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/introduction-to-deep-learning-with-pytho-01ca30a5.BRpGGPlp_Z4xKIB.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Part of the &lt;em&gt;&lt;a href=&quot;https://carpentries-lab.github.io/deep-learning-intro/3-monitor-the-model.html&quot;&gt;&lt;em&gt;Monitor the training Process&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; episode of the lesson.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-brief-history-of-the-development-of-this-lesson&quot;&gt;A brief history of the development of this lesson&lt;/h2&gt;
&lt;p&gt;What follows is a year-by-year history of the main contributors to the lesson. Of course, GitHub keeps the score, and all contributions to the commit history, big and, especially, small, can be better tracked &lt;a href=&quot;https://github.com/carpentries-lab/deep-learning-intro/graphs/contributors&quot;&gt;in this interactive contributor graph&lt;/a&gt;. Over the years 30 people contributed to this lesson!&lt;/p&gt;
&lt;p&gt;The development of the lesson started in 2020 in a collaboration between &lt;a href=&quot;https://github.com/bpmweel&quot;&gt;Berend Weel&lt;/a&gt; and &lt;a href=&quot;https://github.com/florian-huber&quot;&gt;Florian Huber&lt;/a&gt; (both at the Netherlands eScience Center at the time), &lt;a href=&quot;https://github.com/psteinb&quot;&gt;Peter Steinbach&lt;/a&gt;, &lt;a href=&quot;https://github.com/colinsauze&quot;&gt;Colin Sauze&lt;/a&gt;, &lt;a href=&quot;https://github.com/samumantha&quot;&gt;Samantha Wittke&lt;/a&gt;, and &lt;a href=&quot;https://github.com/tobyhodges&quot;&gt;Toby Hodges&lt;/a&gt;. During this period the main design of the lesson was drafted and the first pilot workshops were given.&lt;/p&gt;
&lt;p&gt;During the year of 2021, Dafne van Kuppevelt, Djura Smits, and Sven van der Burg from the Netherlands eScience Center became involved and by the year 2022 Sven and Djura were the main contributors. In this period the lesson was taught a lot by various organisations and all feedback went into an ever-improving lesson.&lt;/p&gt;
&lt;p&gt;In the period from 2023 till now the lesson was really polished towards its final shape, thanks to contributions from fresh team members Carsten Schnober and Pranav Chandramouli from the Netherlands eScience Center. This is the period that the lesson was transitioned to The Carpentries Workbench and went through The Carpentries Lab review process.&lt;/p&gt;
&lt;h2 id=&quot;about-the-review-process&quot;&gt;About the review process&lt;/h2&gt;
&lt;p&gt;The curriculum was reviewed in &lt;a href=&quot;https://github.com/carpentries-lab/reviews/issues/25&quot;&gt;a public issue thread on The Carpentries Lab reviews repository&lt;/a&gt;. This was a slightly unusual case because one of the authors is a member of The Carpentries Curriculum Team and was the sole Editor of the Lab at the time of submission. (Three other community members have joined as Editors since.) &lt;a href=&quot;https://github.com/brownsarahm&quot;&gt;Sarah M Brown&lt;/a&gt;, formerly a long-standing member of the Trainers Leadership Committee, accepted an invitation to act as Guest Editor for this review. The authors and Carpentries team are enormously grateful to Sarah for the effort she put in and the diligence she displayed throughout the process. She made several essential contributions as Editor, in particular by encouraging the authors to more deeply explore the choice of example datasets used in the lesson (read more about this below).&lt;/p&gt;
&lt;p&gt;After the authors had responded to Sarah’s initial editorial checks, the curriculum was reviewed in detail by two volunteers from The Carpentries community: &lt;a href=&quot;https://github.com/PaulaNietoG&quot;&gt;Johanna Bayer&lt;/a&gt; and &lt;a href=&quot;https://github.com/mike-ivs&quot;&gt;Mike Laverick&lt;/a&gt; (thanks to Erin Becker for helping to connect Sarah with these reviewers). These reviewers were invited based on their expertise as Carpentries Instructors and their domain knowledge in machine learning and related fields.&lt;/p&gt;
&lt;p&gt;The peer-review process led to a number of improvements to the accessibility of the lesson, with better alternative text descriptions for images and various adjustments to make language clearer and more beginner-friendly. The lesson was made easier to teach by other instructors through the addition and improvement of Instructor Notes, and the explanations of a number of important deep learning concepts were expanded.&lt;/p&gt;
&lt;p&gt;Perhaps most importantly, the Editor highlighted that one of the datasets used as an example in the lesson, the CIFAR-10 dataset, is not available under a clearly-defined license. On closer inspection, the authors were surprised to find that CIFAR-10, a dataset very commonly used for benchmarking in machine learning research, was created with image files scraped from the internet without permission from their original owners.&lt;/p&gt;
&lt;p&gt;Sven van der Burg, one of the leading authors of the lesson, created &lt;a href=&quot;https://zenodo.org/records/10970014&quot;&gt;the “Dollar Street 10” dataset&lt;/a&gt; as an alternative to replace CIFAR-10 in the lesson. Dollar Street 10 is derived from the CC-BY-4.0 licensed Dollar Street Dataset from the Gapminder Project: a collection of images that has been more ethically assembled with an emphasis on ensuring that the data is representative of global diversity and accompanied by accurate metadata. The authors added a callout to the lesson to comment on this change, as they felt it represented a great entry point for a discussion of ethics in data and deep learning during a workshop.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;The development team will of course keep on teaching this lesson at their institutes and keep on improving the lesson. We will have to, since deep learning is such a rapidly moving field. But our main goal is to help as many others as possible to adopt this lesson so that it can be taught around the world!&lt;/p&gt;
&lt;p&gt;The lesson has been submitted to &lt;a href=&quot;https://jose.theoj.org/&quot;&gt;The Journal of Open Source Education&lt;/a&gt; for publication.&lt;/p&gt;
&lt;p&gt;The wider Carpentries community can now &lt;a href=&quot;https://carpentries-lab.github.io/deep-learning-intro/&quot;&gt;find the lesson in The Carpentries Lab&lt;/a&gt;, use and adapt it to teach their own workshops, contribute feedback, and suggest improvements. We hope you find it a helpful resource!&lt;/p&gt;
&lt;h2 id=&quot;become-a-reviewer&quot;&gt;Become a Reviewer&lt;/h2&gt;
&lt;p&gt;The Carpentries Lab is looking for reviewers!** To volunteer to review a lesson in the Lab, please read &lt;a href=&quot;https://github.com/carpentries-lab/reviews/blob/main/docs/reviewer_guide.md&quot;&gt;our Guide for Reviewers&lt;/a&gt;, and &lt;a href=&quot;https://forms.gle/cFD4nVjstTtVYoxg8&quot;&gt;register as a reviewer&lt;/a&gt; so we can contact you when relevant lessons are ready for review.&lt;/p&gt;
&lt;p&gt;Lessons in the Incubator can be submitted for review in the Lab by &lt;a href=&quot;https://github.com/carpentries-lab/reviews/issues/new?assignees=tobyhodges&amp;#x26;labels=review&amp;#x26;template=review_submission.yml&amp;#x26;title=%5BReview%5D%3A+&quot;&gt;opening an issue on the reviews repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;We would like to thank all instructors and helpers that taught the course, and the community of people that left contributions to the project, no matter how big or small.&lt;/p&gt;
&lt;p&gt;We thank The Carpentries for providing such a great framework for developing this lesson material.&lt;/p&gt;
&lt;p&gt;We thank all students enrolled in the workshops that were taught using this lesson material for providing us with feedback.&lt;/p&gt;
&lt;p&gt;Congratulations to the authors for creating an excellent lesson that will prove a useful resource to so many people:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/svenvanderburg&quot;&gt;Sven van der Burg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/florian-huber/&quot;&gt;Florian Huber&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/psteinb/&quot;&gt;Peter Steinbach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/colinsauze/&quot;&gt;Colin Sauze&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/carschno/&quot;&gt;Carsten Schnober&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dsmits/&quot;&gt;Djura Smits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tobyhodges/&quot;&gt;Toby Hodges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/bpmweel&quot;&gt;Berend Weel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/cpranav93/&quot;&gt;Pranav Chandramouli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wikfeldt/&quot;&gt;Thor Wikfeldt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/CunliangGeng/&quot;&gt;Cunliang Geng&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/qualiaMachine/&quot;&gt;Chris Endemann&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wmotion/&quot;&gt;Giordano Lipari&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/samumantha&quot;&gt;Samantha Wittke&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ashwinvis&quot;&gt;Ashwin V. Mohanan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sstevens2&quot;&gt;Sarah Stevens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/axdy-a&quot;&gt;axdy-a&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/code4yonglei&quot;&gt;YL Wang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Morrizzzzz&quot;&gt;Maurice de Kleijn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/laurasootes&quot;&gt;Laura Ootes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/k-dominik&quot;&gt;Dominik Kutra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sunyi000&quot;&gt;Yi Sun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/esclapez&quot;&gt;Lucas Esclapez&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/unode&quot;&gt;Renato Alves&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/miguel-mx&quot;&gt;Miguel A Magaña&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/FenneRiemslagh&quot;&gt;Fenne Riemslagh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dafnevk&quot;&gt;Dafne van Kuppevelt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/annefou&quot;&gt;Anne Fouilloux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And huge thanks again to &lt;a href=&quot;https://github.com/brownsarahm&quot;&gt;Sarah M Brown&lt;/a&gt; for acting as Guest Editor, and to the reviewers, &lt;a href=&quot;https://github.com/likeajumprope&quot;&gt;Johanna Bayer&lt;/a&gt; and &lt;a href=&quot;https://github.com/mike-ivs&quot;&gt;Mike Laverick&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/introduction-to-deep-learning-with-pytho-6c0721f9.BkgMA3vv.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>A debugging journey into the unknown (part I)</title><link>https://blog2.esciencecenter.nl/posts/2025-03-13---a-debugging-journey-into-the-unknown-part-i</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-03-13---a-debugging-journey-into-the-unknown-part-i</guid><description>&lt;p&gt;&lt;em&gt;Faced with a buggy library, most people will just give up and wait for a patch to be released. Certainly not our engineers.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A debugging journey into the unknown (part I)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-debugging-journey-into-the-unknown-par-feee515a.cLSBS6f2_Z1TJWjC.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://science.nasa.gov/image-detail/pia17049-hires/&quot;&gt;&lt;em&gt;NASA/JPL-Caltech&lt;/em&gt;&lt;/a&gt;It all started with a colleague trying to update their Julia environment for one of &lt;a href=&quot;https://github.com/TulipaEnergy&quot;&gt;our projects&lt;/a&gt;. They could not update because a dependency, the Julia bindings for DuckDB, was failing to compile. For the moment we decided to deal with it later, and pinned &lt;code&gt;DuckDB.jl&lt;/code&gt; to the working version. We also filed an issue upstream: &lt;a href=&quot;https://github.com/duckdb/duckdb/issues/13911&quot;&gt;duckdb/duckdb#13911&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since there was no significant progress on the issue for a few months, I decided to dive in once and for all — this is that story.&lt;/p&gt;
&lt;h2 id=&quot;the-issue&quot;&gt;The issue&lt;/h2&gt;
&lt;p&gt;On Windows, trying to install any version of &lt;code&gt;DuckDB.jl&lt;/code&gt; later than &lt;code&gt;1.0.0&lt;/code&gt; was failing with the error:&lt;/p&gt;
&lt;p&gt;ERROR: LoadError: could not load symbol “duckdb_vector_size”:
The specified procedure could not be found.Some Julia packages, like &lt;code&gt;DuckDB.jl&lt;/code&gt; depend on a native library. The native library is an internal dependency, and typically named &lt;code&gt;MyPackage_jll.jl&lt;/code&gt;; in the case of DuckDB, it is &lt;code&gt;DuckDB_jll.jl&lt;/code&gt;. The error above tells us that during the compilation step, Julia tries to load a symbol from the native library, but cannot find it. A “symbol” here refers to a DuckDB C-API function provided by the native DuckDB library.&lt;/p&gt;
&lt;p&gt;So as a first step, I wanted to check: can we actually install this library, and load that symbol? To get the call syntax correct, I looked at the source code of &lt;code&gt;[DuckDB.jl](https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/tools/juliapkg/src/api.jl#L1285-L1297)&lt;/code&gt;&lt;a href=&quot;https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/tools/juliapkg/src/api.jl#L1285-L1297&quot;&gt; &lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;function duckdb_vector_size()
return ccall((:duckdb_vector_size, libduckdb), idx_t, ())
endThe variable &lt;code&gt;idx_t&lt;/code&gt; above is defined in &lt;code&gt;ctypes.jl&lt;/code&gt; as:&lt;/p&gt;
&lt;p&gt;const idx_t = UInt64 # DuckDB index typeSo we can test loading the native library like this:&lt;/p&gt;
&lt;p&gt;pkg&gt; add DuckDB_jll
julia&gt; using DuckDB_jll
julia&gt; ccall((:duckdb_vector_size, libduckdb), UInt64, ())The above recipe replicates the error for any version newer than &lt;code&gt;1.0.0&lt;/code&gt;! Hurray! Now that we have confirmation that the problem is in the native library, we have to understand: &lt;em&gt;Why is the symbol not visible to Julia?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;symbol-visibility-in-windows-dlls&quot;&gt;Symbol visibility in Windows DLLs&lt;/h2&gt;
&lt;p&gt;My first hurdle was to find a way to get both versions of the library and compare. I decided to install different versions of the native library &lt;code&gt;DuckDB_jll&lt;/code&gt;in different directories; after loading the library, the &lt;code&gt;libduckdb&lt;/code&gt; variable points to the correct path of the shared library. We can then use other tools to inspect the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;dynamic-link libraries&lt;/a&gt; (DLLs) and check if the symbols actually exist. If we can compare the working version of the native library with a version that does not maybe we can find out what is wrong.&lt;/p&gt;
&lt;p&gt;On Linux, we can use &lt;code&gt;nm&lt;/code&gt; from &lt;code&gt;binutils&lt;/code&gt; to look at the symbols present in the library. Thanks to the &lt;code&gt;-C&lt;/code&gt; flag, &lt;code&gt;nm&lt;/code&gt; can even &lt;a href=&quot;https://en.wikipedia.org/wiki/Name_mangling&quot;&gt;“demangle”&lt;/a&gt; symbol names if necessary. So for the moment we can copy over DLLs from Windows to Linux, and inspect.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;#&amp;#x27; at position 48: …b_vector_size  #̲ working versio…&quot; style=&quot;color:#cc0000&quot;&gt;nm -C libduckdb.dll | grep duckdb_vector_size  # working version: v1.0.0
000000036a271d00 T duckdb_vector_size&lt;/span&gt; nm -C libduckdb.dll | grep duckdb_vector_size  # not working version: e.g. v1.1.2
000000036a36e0e0 T duckdb_vector_size
000000036be998d0 r .rdata$.refptr.duckdb_vector_size
000000036be998d0 R .refptr.duckdb_vector_sizeNo luck 😦, seems that the symbols exist for both versions of the native library. I was puzzled. Searching around I found while building Windows DLLs, you have to explicitly &lt;a href=&quot;https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport&quot;&gt;export symbol names&lt;/a&gt; using the &lt;code&gt;__declspec(dllexport)&lt;/code&gt; attribute. Besides signalling which names are available, it also serves as a mechanism to optimise DLL load times. So I went looking for these attributes in the DuckDB &lt;a href=&quot;https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/src/include/duckdb.h#L17-L31&quot;&gt;source code&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;#ifndef DUCKDB_API
#ifdef _WIN32
#ifdef DUCKDB_STATIC_BUILD
#define DUCKDB_API
#else
#if defined(DUCKDB_BUILD_LIBRARY) &amp;#x26;&amp;#x26; !defined(DUCKDB_BUILD_LOADABLE_EXTENSION)
#define DUCKDB_API __declspec(dllexport)
#else
#define DUCKDB_API __declspec(dllimport)
#endif
#endif
#else
#define DUCKDB_API
#endif
#endifYou can see, the &lt;code&gt;#ifdef&lt;/code&gt; directives conditionally defines the macro &lt;code&gt;DUCKDB_API&lt;/code&gt; which expands to &lt;code&gt;__declspec(dllexport)&lt;/code&gt; when building a Windows DLL. Later in the header file, this macro is used to &lt;a href=&quot;https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/src/include/duckdb.h#L1289-L1295&quot;&gt;mark every C-API function for export&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;DUCKDB_API idx_t duckdb_vector_size();Now that we know the C-API function name symbols are marked for export correctly, we should check if they are indeed exported. After some searching, I learnt Windows development tools includes the program &lt;code&gt;dumpbin.exe&lt;/code&gt; that can show the exported symbol names. So I can search for exported symbols in the output.&lt;/p&gt;
&lt;p&gt;Working version of &lt;code&gt;libduckdb.dll&lt;/code&gt; :&lt;/p&gt;
&lt;p&gt;&gt; dumpbin.exe /EXPORTS .\bin\libduckdb.dll | findstr duckdb_vector_size
335  14E 0078D1B0 duckdb_vector_sizeFaulty version of &lt;code&gt;libduckdb.dll&lt;/code&gt; :&lt;/p&gt;
&lt;p&gt;&gt; dumpbin.exe /EXPORTS .\bin\libduckdb.dll | findstr duckdb_vector_size&lt;/p&gt;
&lt;h1 id=&quot;empty-output-since-nothing-was-foundso-it-is-confirmed-that-the-symbol-export-is-not-working-for-the-faulty-version-however-we-still-do-not-know-which-commit-introduced-the-issue-let-us-try-to-find-that-&quot;&gt;empty output, since nothing was foundSo it is confirmed that the symbol export is not working for the faulty version. However we still do not know which commit introduced the issue. Let us try to find that 🙂.&lt;/h1&gt;
&lt;h2 id=&quot;hunt-for-the-first-bad-commit&quot;&gt;Hunt for the first “bad” commit&lt;/h2&gt;
&lt;p&gt;To be able to find the first bad commit, we need to be able to compile the library. Julia has a whole other infrastructure called &lt;code&gt;[BinaryBuilder](https://binarybuilder.org/)&lt;/code&gt;. It cross-compiles native binaries for all platforms on Linux. This is a whole another rabbit hole, and let us shelve this for another time. The only relevant bit is, the builds are done only* on Linux. This presents a different problem, &lt;code&gt;dumpbin.exe&lt;/code&gt;, the tool to check if the symbol export is correct is available only on Windows. If we are to find the bad commit, we need to automate the build &amp;#x26; check steps and run it with &lt;code&gt;git-bisect&lt;/code&gt;. How can we do that if parts of our toolchain runs on different platforms‽&lt;/p&gt;
&lt;p&gt;So I went searching again for an alternative. Unsurprisingly, Wine (the Windows compatibility layer for Linux) ships with the tool &lt;code&gt;[winedump](https://gitlab.winehq.org/wine/wine/-/wikis/Man-Pages/winedump)&lt;/code&gt;, which is an equivalent to the Windows tool &lt;code&gt;dumpbin.exe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To build with Windows DLL, we need to cross-compile DuckDB on Linux using the MingW-w64 toolchain. Combined with the &lt;code&gt;winedump&lt;/code&gt; tool, I wrote the following script that we can use to test a successful build.&lt;/p&gt;
&lt;p&gt;#!/bin/bash&lt;/p&gt;
&lt;p&gt;rm -rf build
cmake -B build &lt;br&gt;
-DCMAKE_BUILD_TYPE=Release &lt;br&gt;
-DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86_64.cmake &lt;br&gt;
-DBUILD_EXTENSIONS=‘autocomplete;icu;parquet;json;fts;tpcds;tpch’ &lt;br&gt;
-DENABLE_EXTENSION_AUTOLOADING=1 &lt;br&gt;
-DENABLE_EXTENSION_AUTOINSTALL=1 &lt;br&gt;
-DBUILD_UNITTESTS=FALSE &lt;br&gt;
-DBUILD_SHELL=TRUE &lt;br&gt;
-DDUCKDB_EXPLICIT_PLATFORM=x86_64-w64-mingw32-cxx11 .
cmake —build build&lt;/p&gt;
&lt;p&gt;[[ $? -ne 0 ]] &amp;#x26;&amp;#x26; &lt;br&gt;
{
echo “build failed, cannot test”
exit 125
}&lt;/p&gt;
&lt;p&gt;if [[ -f build/src/libduckdb.dll ]]; then
winedump -j export build/src/libduckdb.dll | grep -q duckdb_vector_size
if [[ $? -eq 0 ]]; then
exit 0
else
exit 1
fi
else
echo “cannot find DLL, cannot test”
exit 125
fiThe script builds DuckDB, and checks whether the generated DLL file export the C-API symbols correctly. It also handles a few corner cases of build failures. Note that the build command uses the following toolchain file (thanks to this &lt;a href=&quot;https://gist.github.com/peterspackman/8cf73f7f12ba270aa8192d6911972fe8/&quot;&gt;gist&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)&lt;/p&gt;
&lt;h1 id=&quot;cross-compilers-to-use-for-c-c-and-fortran&quot;&gt;cross compilers to use for C, C++ and Fortran&lt;/h1&gt;
&lt;p&gt;set(CMAKE_C_COMPILER &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.109em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cc&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;{TOOLCHAIN_PREFIX}-g++)
set(CMAKE_Fortran_COMPILER &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;/msub&gt;&lt;msub&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{TOOLCHAIN_PREFIX}-gfortran)
set(CMAKE_RC_COMPILER &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.109em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;{TOOLCHAIN_PREFIX}-windres)&lt;/p&gt;
&lt;h1 id=&quot;target-environment-on-the-build-host-system&quot;&gt;target environment on the build host system&lt;/h1&gt;
&lt;p&gt;set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})&lt;/p&gt;
&lt;h1 id=&quot;modify-default-behavior-of-find_xxx-commands&quot;&gt;modify default behavior of FIND_XXX() commands&lt;/h1&gt;
&lt;p&gt;set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)Now we can use this script with &lt;code&gt;git-bisect&lt;/code&gt; to find the first bad commit, like this:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;git bisect start&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;bi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; git bisect bad v1.1.2
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1.0.0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;git bisect good v1.0.0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;bi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1.0.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; git bisect run ./bisect-script.bash
&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;#&amp;#x27; at position 22: …sect visualize #̲ shows a nice s…&quot; style=&quot;color:#cc0000&quot;&gt;git bisect visualize # shows a nice summary&lt;/span&gt; git bisect resetThe bisection led me to this commit: &lt;a href=&quot;https://github.com/duckdb/duckdb/commit/d1ea1538c9217fb536485f1500f04a0b55b1e584&quot;&gt;d1ea1538&lt;/a&gt;. Unfortunately it is not clear how that commit would lead to symbol export failure, it only adds 11 new functions to the C-API (so 11 new symbols). So for now, this debugging journey has to stop here, without a clear resolution. But we did learn a lot of new concepts, and used a wide variety of tools to investigate.&lt;/p&gt;
&lt;h2 id=&quot;what-did-we-learn&quot;&gt;What did we learn?&lt;/h2&gt;
&lt;p&gt;To summarise, the issue is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All releases of &lt;code&gt;DuckDB.jl&lt;/code&gt; after &lt;code&gt;v1.0.0&lt;/code&gt; on Windows are broken.&lt;/li&gt;
&lt;li&gt;We recreate the issue without Julia, which shows the the DuckDB build using the MingW-w64 toolchain is broken for all releases after &lt;code&gt;v1.0.0&lt;/code&gt; .&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And in the process of debugging this, we learnt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows has a separate mechanism to export symbol names in its shared libraries (DLL).&lt;/li&gt;
&lt;li&gt;We learnt about tools to inspect symbols in native libraries; namely &lt;code&gt;nm&lt;/code&gt;, &lt;code&gt;dumpbin.exe&lt;/code&gt;, and &lt;code&gt;winedump&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We learnt about the Julia build system for native libraries (a topic for a future post).&lt;/li&gt;
&lt;li&gt;We learnt to write a script that we can use with &lt;code&gt;git-bisect&lt;/code&gt; to run automatic bisections (a potential topic for a future post).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The story isn’t complete. There will be a concluding part when I actually fix the problem.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;*Cross post from: *&lt;a href=&quot;https://github.com/suvayu/suvayu/blob/master/blog/2025-02-15-duckdb-julia-windows.md&quot;&gt;&lt;em&gt;https://github.com/suvayu/suvayu/blob/master/blog/2025-02-15-duckdb-julia-windows.md&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 13 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Faced with a buggy library, most people will just give up and wait for a patch to be released. Certainly not our engineers.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A debugging journey into the unknown (part I)&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-debugging-journey-into-the-unknown-par-feee515a.cLSBS6f2_Z1TJWjC.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://science.nasa.gov/image-detail/pia17049-hires/&quot;&gt;&lt;em&gt;NASA/JPL-Caltech&lt;/em&gt;&lt;/a&gt;It all started with a colleague trying to update their Julia environment for one of &lt;a href=&quot;https://github.com/TulipaEnergy&quot;&gt;our projects&lt;/a&gt;. They could not update because a dependency, the Julia bindings for DuckDB, was failing to compile. For the moment we decided to deal with it later, and pinned &lt;code&gt;DuckDB.jl&lt;/code&gt; to the working version. We also filed an issue upstream: &lt;a href=&quot;https://github.com/duckdb/duckdb/issues/13911&quot;&gt;duckdb/duckdb#13911&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since there was no significant progress on the issue for a few months, I decided to dive in once and for all — this is that story.&lt;/p&gt;
&lt;h2 id=&quot;the-issue&quot;&gt;The issue&lt;/h2&gt;
&lt;p&gt;On Windows, trying to install any version of &lt;code&gt;DuckDB.jl&lt;/code&gt; later than &lt;code&gt;1.0.0&lt;/code&gt; was failing with the error:&lt;/p&gt;
&lt;p&gt;ERROR: LoadError: could not load symbol “duckdb_vector_size”:
The specified procedure could not be found.Some Julia packages, like &lt;code&gt;DuckDB.jl&lt;/code&gt; depend on a native library. The native library is an internal dependency, and typically named &lt;code&gt;MyPackage_jll.jl&lt;/code&gt;; in the case of DuckDB, it is &lt;code&gt;DuckDB_jll.jl&lt;/code&gt;. The error above tells us that during the compilation step, Julia tries to load a symbol from the native library, but cannot find it. A “symbol” here refers to a DuckDB C-API function provided by the native DuckDB library.&lt;/p&gt;
&lt;p&gt;So as a first step, I wanted to check: can we actually install this library, and load that symbol? To get the call syntax correct, I looked at the source code of &lt;code&gt;[DuckDB.jl](https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/tools/juliapkg/src/api.jl#L1285-L1297)&lt;/code&gt;&lt;a href=&quot;https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/tools/juliapkg/src/api.jl#L1285-L1297&quot;&gt; &lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;function duckdb_vector_size()
return ccall((:duckdb_vector_size, libduckdb), idx_t, ())
endThe variable &lt;code&gt;idx_t&lt;/code&gt; above is defined in &lt;code&gt;ctypes.jl&lt;/code&gt; as:&lt;/p&gt;
&lt;p&gt;const idx_t = UInt64 # DuckDB index typeSo we can test loading the native library like this:&lt;/p&gt;
&lt;p&gt;pkg&gt; add DuckDB_jll
julia&gt; using DuckDB_jll
julia&gt; ccall((:duckdb_vector_size, libduckdb), UInt64, ())The above recipe replicates the error for any version newer than &lt;code&gt;1.0.0&lt;/code&gt;! Hurray! Now that we have confirmation that the problem is in the native library, we have to understand: &lt;em&gt;Why is the symbol not visible to Julia?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;symbol-visibility-in-windows-dlls&quot;&gt;Symbol visibility in Windows DLLs&lt;/h2&gt;
&lt;p&gt;My first hurdle was to find a way to get both versions of the library and compare. I decided to install different versions of the native library &lt;code&gt;DuckDB_jll&lt;/code&gt;in different directories; after loading the library, the &lt;code&gt;libduckdb&lt;/code&gt; variable points to the correct path of the shared library. We can then use other tools to inspect the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;dynamic-link libraries&lt;/a&gt; (DLLs) and check if the symbols actually exist. If we can compare the working version of the native library with a version that does not maybe we can find out what is wrong.&lt;/p&gt;
&lt;p&gt;On Linux, we can use &lt;code&gt;nm&lt;/code&gt; from &lt;code&gt;binutils&lt;/code&gt; to look at the symbols present in the library. Thanks to the &lt;code&gt;-C&lt;/code&gt; flag, &lt;code&gt;nm&lt;/code&gt; can even &lt;a href=&quot;https://en.wikipedia.org/wiki/Name_mangling&quot;&gt;“demangle”&lt;/a&gt; symbol names if necessary. So for the moment we can copy over DLLs from Windows to Linux, and inspect.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;#&amp;#x27; at position 48: …b_vector_size  #̲ working versio…&quot; style=&quot;color:#cc0000&quot;&gt;nm -C libduckdb.dll | grep duckdb_vector_size  # working version: v1.0.0
000000036a271d00 T duckdb_vector_size&lt;/span&gt; nm -C libduckdb.dll | grep duckdb_vector_size  # not working version: e.g. v1.1.2
000000036a36e0e0 T duckdb_vector_size
000000036be998d0 r .rdata$.refptr.duckdb_vector_size
000000036be998d0 R .refptr.duckdb_vector_sizeNo luck 😦, seems that the symbols exist for both versions of the native library. I was puzzled. Searching around I found while building Windows DLLs, you have to explicitly &lt;a href=&quot;https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport&quot;&gt;export symbol names&lt;/a&gt; using the &lt;code&gt;__declspec(dllexport)&lt;/code&gt; attribute. Besides signalling which names are available, it also serves as a mechanism to optimise DLL load times. So I went looking for these attributes in the DuckDB &lt;a href=&quot;https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/src/include/duckdb.h#L17-L31&quot;&gt;source code&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;#ifndef DUCKDB_API
#ifdef _WIN32
#ifdef DUCKDB_STATIC_BUILD
#define DUCKDB_API
#else
#if defined(DUCKDB_BUILD_LIBRARY) &amp;#x26;&amp;#x26; !defined(DUCKDB_BUILD_LOADABLE_EXTENSION)
#define DUCKDB_API __declspec(dllexport)
#else
#define DUCKDB_API __declspec(dllimport)
#endif
#endif
#else
#define DUCKDB_API
#endif
#endifYou can see, the &lt;code&gt;#ifdef&lt;/code&gt; directives conditionally defines the macro &lt;code&gt;DUCKDB_API&lt;/code&gt; which expands to &lt;code&gt;__declspec(dllexport)&lt;/code&gt; when building a Windows DLL. Later in the header file, this macro is used to &lt;a href=&quot;https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/src/include/duckdb.h#L1289-L1295&quot;&gt;mark every C-API function for export&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;DUCKDB_API idx_t duckdb_vector_size();Now that we know the C-API function name symbols are marked for export correctly, we should check if they are indeed exported. After some searching, I learnt Windows development tools includes the program &lt;code&gt;dumpbin.exe&lt;/code&gt; that can show the exported symbol names. So I can search for exported symbols in the output.&lt;/p&gt;
&lt;p&gt;Working version of &lt;code&gt;libduckdb.dll&lt;/code&gt; :&lt;/p&gt;
&lt;p&gt;&gt; dumpbin.exe /EXPORTS .\bin\libduckdb.dll | findstr duckdb_vector_size
335  14E 0078D1B0 duckdb_vector_sizeFaulty version of &lt;code&gt;libduckdb.dll&lt;/code&gt; :&lt;/p&gt;
&lt;p&gt;&gt; dumpbin.exe /EXPORTS .\bin\libduckdb.dll | findstr duckdb_vector_size&lt;/p&gt;
&lt;h1 id=&quot;empty-output-since-nothing-was-foundso-it-is-confirmed-that-the-symbol-export-is-not-working-for-the-faulty-version-however-we-still-do-not-know-which-commit-introduced-the-issue-let-us-try-to-find-that-&quot;&gt;empty output, since nothing was foundSo it is confirmed that the symbol export is not working for the faulty version. However we still do not know which commit introduced the issue. Let us try to find that 🙂.&lt;/h1&gt;
&lt;h2 id=&quot;hunt-for-the-first-bad-commit&quot;&gt;Hunt for the first “bad” commit&lt;/h2&gt;
&lt;p&gt;To be able to find the first bad commit, we need to be able to compile the library. Julia has a whole other infrastructure called &lt;code&gt;[BinaryBuilder](https://binarybuilder.org/)&lt;/code&gt;. It cross-compiles native binaries for all platforms on Linux. This is a whole another rabbit hole, and let us shelve this for another time. The only relevant bit is, the builds are done only* on Linux. This presents a different problem, &lt;code&gt;dumpbin.exe&lt;/code&gt;, the tool to check if the symbol export is correct is available only on Windows. If we are to find the bad commit, we need to automate the build &amp;#x26; check steps and run it with &lt;code&gt;git-bisect&lt;/code&gt;. How can we do that if parts of our toolchain runs on different platforms‽&lt;/p&gt;
&lt;p&gt;So I went searching again for an alternative. Unsurprisingly, Wine (the Windows compatibility layer for Linux) ships with the tool &lt;code&gt;[winedump](https://gitlab.winehq.org/wine/wine/-/wikis/Man-Pages/winedump)&lt;/code&gt;, which is an equivalent to the Windows tool &lt;code&gt;dumpbin.exe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To build with Windows DLL, we need to cross-compile DuckDB on Linux using the MingW-w64 toolchain. Combined with the &lt;code&gt;winedump&lt;/code&gt; tool, I wrote the following script that we can use to test a successful build.&lt;/p&gt;
&lt;p&gt;#!/bin/bash&lt;/p&gt;
&lt;p&gt;rm -rf build
cmake -B build &lt;br&gt;
-DCMAKE_BUILD_TYPE=Release &lt;br&gt;
-DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86_64.cmake &lt;br&gt;
-DBUILD_EXTENSIONS=‘autocomplete;icu;parquet;json;fts;tpcds;tpch’ &lt;br&gt;
-DENABLE_EXTENSION_AUTOLOADING=1 &lt;br&gt;
-DENABLE_EXTENSION_AUTOINSTALL=1 &lt;br&gt;
-DBUILD_UNITTESTS=FALSE &lt;br&gt;
-DBUILD_SHELL=TRUE &lt;br&gt;
-DDUCKDB_EXPLICIT_PLATFORM=x86_64-w64-mingw32-cxx11 .
cmake —build build&lt;/p&gt;
&lt;p&gt;[[ $? -ne 0 ]] &amp;#x26;&amp;#x26; &lt;br&gt;
{
echo “build failed, cannot test”
exit 125
}&lt;/p&gt;
&lt;p&gt;if [[ -f build/src/libduckdb.dll ]]; then
winedump -j export build/src/libduckdb.dll | grep -q duckdb_vector_size
if [[ $? -eq 0 ]]; then
exit 0
else
exit 1
fi
else
echo “cannot find DLL, cannot test”
exit 125
fiThe script builds DuckDB, and checks whether the generated DLL file export the C-API symbols correctly. It also handles a few corner cases of build failures. Note that the build command uses the following toolchain file (thanks to this &lt;a href=&quot;https://gist.github.com/peterspackman/8cf73f7f12ba270aa8192d6911972fe8/&quot;&gt;gist&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)&lt;/p&gt;
&lt;h1 id=&quot;cross-compilers-to-use-for-c-c-and-fortran&quot;&gt;cross compilers to use for C, C++ and Fortran&lt;/h1&gt;
&lt;p&gt;set(CMAKE_C_COMPILER &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.109em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cc&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;{TOOLCHAIN_PREFIX}-g++)
set(CMAKE_Fortran_COMPILER &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;/mrow&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;K&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;/msub&gt;&lt;msub&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{TOOLCHAIN_PREFIX}-gfortran)
set(CMAKE_RC_COMPILER &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8333em;vertical-align:-0.15em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.109em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;{TOOLCHAIN_PREFIX}-windres)&lt;/p&gt;
&lt;h1 id=&quot;target-environment-on-the-build-host-system&quot;&gt;target environment on the build host system&lt;/h1&gt;
&lt;p&gt;set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})&lt;/p&gt;
&lt;h1 id=&quot;modify-default-behavior-of-find_xxx-commands&quot;&gt;modify default behavior of FIND_XXX() commands&lt;/h1&gt;
&lt;p&gt;set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)Now we can use this script with &lt;code&gt;git-bisect&lt;/code&gt; to find the first bad commit, like this:&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;git bisect start&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;bi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; git bisect bad v1.1.2
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;1.0.0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;git bisect good v1.0.0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;bi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1.0.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; git bisect run ./bisect-script.bash
&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;#&amp;#x27; at position 22: …sect visualize #̲ shows a nice s…&quot; style=&quot;color:#cc0000&quot;&gt;git bisect visualize # shows a nice summary&lt;/span&gt; git bisect resetThe bisection led me to this commit: &lt;a href=&quot;https://github.com/duckdb/duckdb/commit/d1ea1538c9217fb536485f1500f04a0b55b1e584&quot;&gt;d1ea1538&lt;/a&gt;. Unfortunately it is not clear how that commit would lead to symbol export failure, it only adds 11 new functions to the C-API (so 11 new symbols). So for now, this debugging journey has to stop here, without a clear resolution. But we did learn a lot of new concepts, and used a wide variety of tools to investigate.&lt;/p&gt;
&lt;h2 id=&quot;what-did-we-learn&quot;&gt;What did we learn?&lt;/h2&gt;
&lt;p&gt;To summarise, the issue is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All releases of &lt;code&gt;DuckDB.jl&lt;/code&gt; after &lt;code&gt;v1.0.0&lt;/code&gt; on Windows are broken.&lt;/li&gt;
&lt;li&gt;We recreate the issue without Julia, which shows the the DuckDB build using the MingW-w64 toolchain is broken for all releases after &lt;code&gt;v1.0.0&lt;/code&gt; .&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And in the process of debugging this, we learnt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows has a separate mechanism to export symbol names in its shared libraries (DLL).&lt;/li&gt;
&lt;li&gt;We learnt about tools to inspect symbols in native libraries; namely &lt;code&gt;nm&lt;/code&gt;, &lt;code&gt;dumpbin.exe&lt;/code&gt;, and &lt;code&gt;winedump&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We learnt about the Julia build system for native libraries (a topic for a future post).&lt;/li&gt;
&lt;li&gt;We learnt to write a script that we can use with &lt;code&gt;git-bisect&lt;/code&gt; to run automatic bisections (a potential topic for a future post).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The story isn’t complete. There will be a concluding part when I actually fix the problem.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;*Cross post from: *&lt;a href=&quot;https://github.com/suvayu/suvayu/blob/master/blog/2025-02-15-duckdb-julia-windows.md&quot;&gt;&lt;em&gt;https://github.com/suvayu/suvayu/blob/master/blog/2025-02-15-duckdb-julia-windows.md&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/a-debugging-journey-into-the-unknown-par-feee515a.cLSBS6f2.jpeg" medium="image"/><author>Suvayu</author></item><item><title>Sharing MATLAB models with everyone</title><link>https://blog2.esciencecenter.nl/posts/2025-03-12---sharing-matlab-models-with-everyone</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-03-12---sharing-matlab-models-with-everyone</guid><description>&lt;p&gt;MATLAB is still commonly used in many scientific fields, despite its closed-source nature. While many (technical) universities used to teach coding using MATLAB, more and more are moving away from it, preferring open-source and free alternatives such as Python or Julia. O&lt;a href=&quot;https://julialang.org/blog/2012/02/why-we-created-julia/&quot;&gt;ne of the main reasons Julia was developed&lt;/a&gt; was because of MATLAB’s proprietary and closed software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sharing MATLAB models with everyone&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-e5b6ed0c.DWmPeRbD_1MP8vq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ivvndiaz?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Iván Díaz&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;However, for those with a vested interest in the language, such as a large legacy code base, &lt;a href=&quot;https://medium.com/escience-center/how-to-ensure-that-others-can-run-your-code-4c7672524a69&quot;&gt;it is still important to be able to share your models&lt;/a&gt;. Just sharing MATLAB code is not that useful as it requires the users to have a MATLAB license. For &lt;a href=&quot;https://research-software-directory.org/projects/ecoextreml&quot;&gt;a project&lt;/a&gt; with the University of Twente, we work on [a MATLAB land-surface model](&lt;a href=&quot;https://github.com/Eco&quot;&gt;https://github.com/Eco&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ExtreML/STEMMUS_SCOPE/). We wanted to make the model open-source and available for anyone to run, as well as allow interaction with the model through a &lt;a href=&quot;https://bmi.readthedocs.io&quot;&gt;Basic Model Interface&lt;/a&gt;, a standardized interface for numerical models.&lt;/p&gt;
&lt;p&gt;One option would be to try GNU Octave, a language that is mostly compatible with MATLAB. The key word being &lt;em&gt;mostly&lt;/em&gt;*. For us, the difference in execution time was too large. The second option is to make use of MATLAB Runtime.&lt;/p&gt;
&lt;h2 id=&quot;matlab-runtime&quot;&gt;MATLAB Runtime&lt;/h2&gt;
&lt;p&gt;With &lt;a href=&quot;https://nl.mathworks.com/products/compiler/matlab-runtime.html&quot;&gt;MATLAB Runtime&lt;/a&gt; anyone can run MATLAB applications or components without installing MATLAB. You generate an executable file on a system &lt;em&gt;with&lt;/em&gt; a MATLAB license, which you can then run on a system &lt;em&gt;without&lt;/em&gt; a license. This does require that the target system has the same operating system and architecture as the system that generated the executable file.&lt;/p&gt;
&lt;h2 id=&quot;docker&quot;&gt;Docker&lt;/h2&gt;
&lt;p&gt;This is where Docker comes into play. Docker allows you to package your application together with a minimal operating system and any dependencies, such that it can run as a standalone application. Note that you can also use Apptainer, an open-source alternative.&lt;/p&gt;
&lt;p&gt;Lucky for us, &lt;a href=&quot;https://github.com/demartis/MATLAB_runtime_docker&quot;&gt;someone already did the work of containerizing MATLAB Runtime&lt;/a&gt;. Thanks Riccardo De Martis! A quick example is in the following Dockerfile:&lt;/p&gt;
&lt;h1 id=&quot;we-start-from-the-already-existing-matlab-runtime-container&quot;&gt;We start from the already-existing MATLAB Runtime container:&lt;/h1&gt;
&lt;p&gt;FROM demartis/matlab-runtime:R2023a&lt;/p&gt;
&lt;h1 id=&quot;put-the-executable-in-the-container-for-example-from-github&quot;&gt;Put the executable in the container, for example from GitHub:&lt;/h1&gt;
&lt;p&gt;RUN wget &lt;a href=&quot;https://github.com/MyOrganization/MyRepo/raw/main/exe/MATLAB_MODEL&quot;&gt;https://github.com/MyOrganization/MyRepo/raw/main/exe/MATLAB_MODEL&lt;/a&gt; - no-check-certificate&lt;/p&gt;
&lt;h1 id=&quot;make-sure-the-file-is-executable&quot;&gt;Make sure the file is executable&lt;/h1&gt;
&lt;p&gt;RUN chmod +x ./MATLAB_MODEL&lt;/p&gt;
&lt;h1 id=&quot;allow-mcr-to-have-a-cache-directory-which-all-users-can-access&quot;&gt;Allow MCR to have a cache directory which all users can access&lt;/h1&gt;
&lt;h1 id=&quot;this-allows-for-executing-the-model-as-a-different-user&quot;&gt;this allows for executing the model as a different user.&lt;/h1&gt;
&lt;p&gt;RUN mkdir /temp/
RUN chmod 777 /temp/
ENV MCR_CACHE_ROOT /temp/&lt;/p&gt;
&lt;h1 id=&quot;run-the-model&quot;&gt;Run the model:&lt;/h1&gt;
&lt;p&gt;CMD ./MATLAB_MODELNotice that the MATLAB Runtime container is based on Debian, so you need to generate your executable file on a Linux system as well. On the flip side, once the container is built, it will be easy to run it on different systems, as well as in parallel (such as scaling up your analysis on HPC, where more computational power and data is available).&lt;/p&gt;
&lt;h2 id=&quot;interacting-with-the-containerized-model&quot;&gt;Interacting with the containerized model&lt;/h2&gt;
&lt;p&gt;For many users, this will be good enough: you simply run the model once, passing a config file as an argument, and you’re done. If the model needs access to data, you can attach those directories to the container. The model’s output will be written to a file.&lt;/p&gt;
&lt;p&gt;A more advanced use case is when you want to interact with the model while* it is running, such as with the Basic Model Interface mentioned earlier. For this, you will need to communicate with the running MATLAB code.&lt;/p&gt;
&lt;p&gt;Communicating with the model inside the directory &lt;em&gt;can&lt;/em&gt; be done using the terminal, but more ideal would be a proper interface. If you set up &lt;a href=&quot;https://www.mathworks.com/matlabcentral/fileexchange/29027-web-server&quot;&gt;a MATLAB HTTP server&lt;/a&gt;, you can expose the server’s port inside the container. This then allows you to start the HTTP server and execute the MATLAB code from outside the container.&lt;/p&gt;
&lt;h3 id=&quot;data-exchange&quot;&gt;Data exchange&lt;/h3&gt;
&lt;p&gt;While telling the model to run certain routines is straightforward using an HTTP server, data exchange is a bit more complex. A simpler way is to write the model’s state or parameters of interest to file.&lt;/p&gt;
&lt;p&gt;MATLAB’s default file format is HDF5 nowadays, which is supported by most other languages (for example, Julia with HDF5.jl, or Python with h5py). Scripts or programs written in these other languages can then interact with this file, which can be loaded again in MATLAB if two-way communication is required.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sharing MATLAB models with everyone&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;453&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-3dd8c2ff.Cb2yxATD_PpHsa.webp&quot; srcset=&quot;&quot;&gt;
Communicating with a containerized MATLAB model through Python&lt;/p&gt;
&lt;h2 id=&quot;example-stemmus_scope-basic-model-interface&quot;&gt;Example: STEMMUS_SCOPE Basic Model Interface&lt;/h2&gt;
&lt;p&gt;A working example of a containerized MATLAB model is &lt;a href=&quot;https://github.com/EcoExtreML/STEMMUS_SCOPE&quot;&gt;STEMMUS_SCOPE&lt;/a&gt;, a land surface model. We wanted to write a &lt;a href=&quot;https://csdms.colorado.edu/wiki/BMI&quot;&gt;Basic Model Interface&lt;/a&gt; (BMI), to allow for coupling the model to other models such as the groundwater model MODFLOW.&lt;/p&gt;
&lt;p&gt;However, coupling a MATLAB model to models written in a different language is challenging, so we &lt;a href=&quot;https://github.com/EcoExtreML/STEMMUS_SCOPE_Processing/tree/v0.4.0/PyStemmusScope/bmi&quot;&gt;connected a Python BMI to the containerized model&lt;/a&gt;, as Python excels at being a “glue” language. This allows us to couple the STEMMUS_SCOPE model with other models implementing a BMI.&lt;/p&gt;
&lt;p&gt;One detail here is that we did not have access to a full MATLAB IDE, so it was too challenging to actually go the proper route and implement an HTTP server for STEMMUS_SCOPE. Instead, we communicate to the MATLAB processing using stdin/stdout.&lt;/p&gt;
&lt;h2 id=&quot;sharing-is-caring&quot;&gt;Sharing is caring&lt;/h2&gt;
&lt;p&gt;While it’s certainly more difficult than with many other programming languages, sharing easily (re-)usable MATLAB code with others is still possible. Not only that, but it can also make your own life easier by being able to run your code on other platforms and allowing you to run it in a single command.&lt;/p&gt;
&lt;p&gt;If you enjoyed this story, have a look at the blogpost “&lt;a href=&quot;https://medium.com/escience-center/how-to-ensure-that-others-can-run-your-code-4c7672524a69&quot;&gt;How to ensure that others can run your code&lt;/a&gt;” by Julian Gonggrijp, which touches on many reasons why* *you would want to make sure others can run your code (and how).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sharing MATLAB models with everyone&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-c9e37c82.CatIam-l_ZFm20b.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@j0shuadcampbell?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Josh Campbell&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;*** Octave does not support all MATLAB functions, so the code will have to be modified to support both MATLAB and Octave. Octave can also be an order of magnitude slower than MATLAB, which can be problematic.&lt;/p&gt;</description><pubDate>Wed, 12 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;MATLAB is still commonly used in many scientific fields, despite its closed-source nature. While many (technical) universities used to teach coding using MATLAB, more and more are moving away from it, preferring open-source and free alternatives such as Python or Julia. O&lt;a href=&quot;https://julialang.org/blog/2012/02/why-we-created-julia/&quot;&gt;ne of the main reasons Julia was developed&lt;/a&gt; was because of MATLAB’s proprietary and closed software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sharing MATLAB models with everyone&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-e5b6ed0c.DWmPeRbD_1MP8vq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ivvndiaz?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Iván Díaz&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;However, for those with a vested interest in the language, such as a large legacy code base, &lt;a href=&quot;https://medium.com/escience-center/how-to-ensure-that-others-can-run-your-code-4c7672524a69&quot;&gt;it is still important to be able to share your models&lt;/a&gt;. Just sharing MATLAB code is not that useful as it requires the users to have a MATLAB license. For &lt;a href=&quot;https://research-software-directory.org/projects/ecoextreml&quot;&gt;a project&lt;/a&gt; with the University of Twente, we work on [a MATLAB land-surface model](&lt;a href=&quot;https://github.com/Eco&quot;&gt;https://github.com/Eco&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ExtreML/STEMMUS_SCOPE/). We wanted to make the model open-source and available for anyone to run, as well as allow interaction with the model through a &lt;a href=&quot;https://bmi.readthedocs.io&quot;&gt;Basic Model Interface&lt;/a&gt;, a standardized interface for numerical models.&lt;/p&gt;
&lt;p&gt;One option would be to try GNU Octave, a language that is mostly compatible with MATLAB. The key word being &lt;em&gt;mostly&lt;/em&gt;*. For us, the difference in execution time was too large. The second option is to make use of MATLAB Runtime.&lt;/p&gt;
&lt;h2 id=&quot;matlab-runtime&quot;&gt;MATLAB Runtime&lt;/h2&gt;
&lt;p&gt;With &lt;a href=&quot;https://nl.mathworks.com/products/compiler/matlab-runtime.html&quot;&gt;MATLAB Runtime&lt;/a&gt; anyone can run MATLAB applications or components without installing MATLAB. You generate an executable file on a system &lt;em&gt;with&lt;/em&gt; a MATLAB license, which you can then run on a system &lt;em&gt;without&lt;/em&gt; a license. This does require that the target system has the same operating system and architecture as the system that generated the executable file.&lt;/p&gt;
&lt;h2 id=&quot;docker&quot;&gt;Docker&lt;/h2&gt;
&lt;p&gt;This is where Docker comes into play. Docker allows you to package your application together with a minimal operating system and any dependencies, such that it can run as a standalone application. Note that you can also use Apptainer, an open-source alternative.&lt;/p&gt;
&lt;p&gt;Lucky for us, &lt;a href=&quot;https://github.com/demartis/MATLAB_runtime_docker&quot;&gt;someone already did the work of containerizing MATLAB Runtime&lt;/a&gt;. Thanks Riccardo De Martis! A quick example is in the following Dockerfile:&lt;/p&gt;
&lt;h1 id=&quot;we-start-from-the-already-existing-matlab-runtime-container&quot;&gt;We start from the already-existing MATLAB Runtime container:&lt;/h1&gt;
&lt;p&gt;FROM demartis/matlab-runtime:R2023a&lt;/p&gt;
&lt;h1 id=&quot;put-the-executable-in-the-container-for-example-from-github&quot;&gt;Put the executable in the container, for example from GitHub:&lt;/h1&gt;
&lt;p&gt;RUN wget &lt;a href=&quot;https://github.com/MyOrganization/MyRepo/raw/main/exe/MATLAB_MODEL&quot;&gt;https://github.com/MyOrganization/MyRepo/raw/main/exe/MATLAB_MODEL&lt;/a&gt; - no-check-certificate&lt;/p&gt;
&lt;h1 id=&quot;make-sure-the-file-is-executable&quot;&gt;Make sure the file is executable&lt;/h1&gt;
&lt;p&gt;RUN chmod +x ./MATLAB_MODEL&lt;/p&gt;
&lt;h1 id=&quot;allow-mcr-to-have-a-cache-directory-which-all-users-can-access&quot;&gt;Allow MCR to have a cache directory which all users can access&lt;/h1&gt;
&lt;h1 id=&quot;this-allows-for-executing-the-model-as-a-different-user&quot;&gt;this allows for executing the model as a different user.&lt;/h1&gt;
&lt;p&gt;RUN mkdir /temp/
RUN chmod 777 /temp/
ENV MCR_CACHE_ROOT /temp/&lt;/p&gt;
&lt;h1 id=&quot;run-the-model&quot;&gt;Run the model:&lt;/h1&gt;
&lt;p&gt;CMD ./MATLAB_MODELNotice that the MATLAB Runtime container is based on Debian, so you need to generate your executable file on a Linux system as well. On the flip side, once the container is built, it will be easy to run it on different systems, as well as in parallel (such as scaling up your analysis on HPC, where more computational power and data is available).&lt;/p&gt;
&lt;h2 id=&quot;interacting-with-the-containerized-model&quot;&gt;Interacting with the containerized model&lt;/h2&gt;
&lt;p&gt;For many users, this will be good enough: you simply run the model once, passing a config file as an argument, and you’re done. If the model needs access to data, you can attach those directories to the container. The model’s output will be written to a file.&lt;/p&gt;
&lt;p&gt;A more advanced use case is when you want to interact with the model while* it is running, such as with the Basic Model Interface mentioned earlier. For this, you will need to communicate with the running MATLAB code.&lt;/p&gt;
&lt;p&gt;Communicating with the model inside the directory &lt;em&gt;can&lt;/em&gt; be done using the terminal, but more ideal would be a proper interface. If you set up &lt;a href=&quot;https://www.mathworks.com/matlabcentral/fileexchange/29027-web-server&quot;&gt;a MATLAB HTTP server&lt;/a&gt;, you can expose the server’s port inside the container. This then allows you to start the HTTP server and execute the MATLAB code from outside the container.&lt;/p&gt;
&lt;h3 id=&quot;data-exchange&quot;&gt;Data exchange&lt;/h3&gt;
&lt;p&gt;While telling the model to run certain routines is straightforward using an HTTP server, data exchange is a bit more complex. A simpler way is to write the model’s state or parameters of interest to file.&lt;/p&gt;
&lt;p&gt;MATLAB’s default file format is HDF5 nowadays, which is supported by most other languages (for example, Julia with HDF5.jl, or Python with h5py). Scripts or programs written in these other languages can then interact with this file, which can be loaded again in MATLAB if two-way communication is required.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sharing MATLAB models with everyone&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;453&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-3dd8c2ff.Cb2yxATD_PpHsa.webp&quot; srcset=&quot;&quot;&gt;
Communicating with a containerized MATLAB model through Python&lt;/p&gt;
&lt;h2 id=&quot;example-stemmus_scope-basic-model-interface&quot;&gt;Example: STEMMUS_SCOPE Basic Model Interface&lt;/h2&gt;
&lt;p&gt;A working example of a containerized MATLAB model is &lt;a href=&quot;https://github.com/EcoExtreML/STEMMUS_SCOPE&quot;&gt;STEMMUS_SCOPE&lt;/a&gt;, a land surface model. We wanted to write a &lt;a href=&quot;https://csdms.colorado.edu/wiki/BMI&quot;&gt;Basic Model Interface&lt;/a&gt; (BMI), to allow for coupling the model to other models such as the groundwater model MODFLOW.&lt;/p&gt;
&lt;p&gt;However, coupling a MATLAB model to models written in a different language is challenging, so we &lt;a href=&quot;https://github.com/EcoExtreML/STEMMUS_SCOPE_Processing/tree/v0.4.0/PyStemmusScope/bmi&quot;&gt;connected a Python BMI to the containerized model&lt;/a&gt;, as Python excels at being a “glue” language. This allows us to couple the STEMMUS_SCOPE model with other models implementing a BMI.&lt;/p&gt;
&lt;p&gt;One detail here is that we did not have access to a full MATLAB IDE, so it was too challenging to actually go the proper route and implement an HTTP server for STEMMUS_SCOPE. Instead, we communicate to the MATLAB processing using stdin/stdout.&lt;/p&gt;
&lt;h2 id=&quot;sharing-is-caring&quot;&gt;Sharing is caring&lt;/h2&gt;
&lt;p&gt;While it’s certainly more difficult than with many other programming languages, sharing easily (re-)usable MATLAB code with others is still possible. Not only that, but it can also make your own life easier by being able to run your code on other platforms and allowing you to run it in a single command.&lt;/p&gt;
&lt;p&gt;If you enjoyed this story, have a look at the blogpost “&lt;a href=&quot;https://medium.com/escience-center/how-to-ensure-that-others-can-run-your-code-4c7672524a69&quot;&gt;How to ensure that others can run your code&lt;/a&gt;” by Julian Gonggrijp, which touches on many reasons why* *you would want to make sure others can run your code (and how).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Sharing MATLAB models with everyone&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-c9e37c82.CatIam-l_ZFm20b.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@j0shuadcampbell?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Josh Campbell&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;*** Octave does not support all MATLAB functions, so the code will have to be modified to support both MATLAB and Octave. Octave can also be an order of magnitude slower than MATLAB, which can be problematic.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/sharing-matlab-models-with-everyone-e5b6ed0c.DWmPeRbD.jpg" medium="image"/><author>Bart Schilperoort</author></item><item><title>A Helpful Noob</title><link>https://blog2.esciencecenter.nl/posts/2025-02-21---a-helpful-noob</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-02-21---a-helpful-noob</guid><description>&lt;p&gt;&lt;img alt=&quot;A Helpful Noob&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-helpful-noob-a2f448b4.lQj8rzQD_Z2cSNID.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@keiteu_ko?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Keiteu Ko&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Yesterday, my colleague &lt;a href=&quot;https://github.com/fdiblen&quot;&gt;Faruk&lt;/a&gt; asked me to conduct a Hallway Test for the &lt;code&gt;[NLeSC/python-template](https://github.com/NLeSC/python-template)&lt;/code&gt; he is working on: he just grabbed me off the hallway and asked me to give it a spin. This is, however, not a story about the test, but of open-source intelligence (OSINT) and the contributions of yet another “helpful noob”.&lt;/p&gt;
&lt;p&gt;Right after I posted my feedback in an &lt;a href=&quot;https://github.com/NLeSC/python-template/issues/554&quot;&gt;issue&lt;/a&gt; of the project, someone else posted a helpful contribution right underneath:&lt;/p&gt;
&lt;p&gt;GitHub comment from xiaobai-marker, with edited link so y’all don’t get any funny ideasHuh? It took this person only a few seconds to post a fix for quite a list of small changes that I posted. That’s so nice! So let’s do a review of &lt;em&gt;their&lt;/em&gt; contributions.&lt;/p&gt;
&lt;h2 id=&quot;trail-github&quot;&gt;Trail: GitHub&lt;/h2&gt;
&lt;p&gt;Their GitHub handle is &lt;code&gt;xiaobai-marker&lt;/code&gt;. XiaoBai is (Pinyin writing of) Chinese and translates to “little white”, not referring to the actual color, but more in the direction of “unsullied”. It means Little Noob.&lt;/p&gt;
&lt;p&gt;A brief dive into &lt;code&gt;xiaobai-marker&lt;/code&gt; ‘s GitHub profile (by now mysteriously removed) confirms this initial impression.&lt;/p&gt;
&lt;p&gt;GitHub profile of &lt;code&gt;xiaobai-marker&lt;/code&gt;They forked only three publicly available repositories. They apparently deal with self-driving toy cars and machine learning to detect road lanes. Fun! However, that’s not a lot of content for someone who seems to contribute to other projects, especially considering that they did not open any repositories themselves.&lt;/p&gt;
&lt;p&gt;But we’re not judging. Any contributions are welcome, and that includes those from people with little experience. So let’s have a look at their actual contribution.&lt;/p&gt;
&lt;h2 id=&quot;trail-download-link&quot;&gt;Trail: Download Link&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mediafire.com&quot;&gt;MediaFire&lt;/a&gt; is a known file storage and sharing website. Clicking &lt;em&gt;this&lt;/em&gt; link is not &lt;em&gt;per se&lt;/em&gt; dangerous. Still, we proceed with caution.&lt;/p&gt;
&lt;p&gt;MediaFire download pageMediaFire uses VirusTotal to scan for malicious files. This inspires confidence, right? An encrypted &lt;code&gt;*.zip&lt;/code&gt; file, however, is opaque to any scans since we can’t look inside without the password, which was supplied on GitHub and is not known to MediaFire or VirusTotal. Another interesting detail is where the file comes from. Apparently it was uploaded the same day from somewhere in Russia. Is our Little Noob from Russia?&lt;/p&gt;
&lt;p&gt;Let’s check out the files now.&lt;/p&gt;
&lt;h2 id=&quot;trail-files&quot;&gt;Trail: Files&lt;/h2&gt;
&lt;p&gt;What did we actually download? A rather small zip file.&lt;/p&gt;
&lt;p&gt;$ ls -lah fix.zip
-rw-r—r— 1 ole users 367K Aug 27 08:15 fix.zipProviding the password, we can unpack it and have a look at the content.&lt;/p&gt;
&lt;p&gt;$ 7z e -pchangeme fix.zip&lt;/p&gt;
&lt;p&gt;7-Zip [64] 17.05 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
p7zip Version 17.05 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)&lt;/p&gt;
&lt;p&gt;Scanning the drive for archives:
1 file, 375771 bytes (367 KiB)&lt;/p&gt;
&lt;h2 id=&quot;extracting-archive-fixzip&quot;&gt;Extracting archive: fix.zip&lt;/h2&gt;
&lt;p&gt;Path = fix.zip
Type = zip
Physical Size = 375771&lt;/p&gt;
&lt;p&gt;Everything is Ok&lt;/p&gt;
&lt;p&gt;Folders: 1
Files: 2
Size:       747008
Compressed: 375771What did we just unpack?&lt;/p&gt;
&lt;p&gt;$ ls -lah fix/
total 456K
-rw-r—r— 1 ole users 490K Aug 27 08:15 msvcp140.dll
-rw-r—r— 1 ole users 240K Aug 27 08:15 x86_64-w64-ranlib.exeHuh. &lt;code&gt;ranlib&lt;/code&gt; is a standard programming tool, although here it is supposed to be an installer (!). This “fix” seems to have been written for a Windows system. I can’t run it on my Linux machine. Bummer. I’m also not very good at decompiling &lt;code&gt;*.exe&lt;/code&gt; files to check what’s really inside. But we can ask some websites for assistance.&lt;/p&gt;
&lt;h3 id=&quot;virustotal&quot;&gt;VirusTotal&lt;/h3&gt;
&lt;p&gt;First we upload the file to &lt;a href=&quot;https://virustotal.com&quot;&gt;virustotal.com&lt;/a&gt;, a Google-owned file and link analyzer and one of the authorities in the space of malware indexing. On the day of the initial analysis, 28 of 75 security vendors &lt;a href=&quot;https://www.virustotal.com/gui/file/546c34c2782216278a8273d3c9d3a954a980c7c2c7be220914aefe446fe94fd8/detection&quot;&gt;flagged the files as malicious&lt;/a&gt;. You don’t say! One day later this number is up to 35. It seems to be a fresh strain that is quickly being picked up by the security community.&lt;/p&gt;
&lt;p&gt;VirusTotal analysisSo what do we have here? “Trojan”? “MalwareX”? This is still quite vague.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Fun fact: One of the analyses — fourth row, right side — comes from CrowdStrike. Those are guys that &lt;em&gt;&lt;a href=&quot;https://arstechnica.com/information-technology/2024/07/major-outages-at-crowdstrike-microsoft-leave-the-world-with-bsods-and-confusion/&quot;&gt;&lt;em&gt;crashed&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; some &lt;em&gt;&lt;a href=&quot;https://blogs.microsoft.com/blog/2024/07/20/helping-our-customers-through-the-crowdstrike-outage/&quot;&gt;&lt;em&gt;8.5 million rather important Windows computers&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, resulting in &lt;em&gt;&lt;a href=&quot;https://www.oxfordeconomics.com/resource/crowdstrike-update-grounds-thousands-of-flights/&quot;&gt;&lt;em&gt;over 10.000 cancelled flights&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and causing &lt;em&gt;&lt;a href=&quot;https://www.neowin.net/news/systems-paralyzed-by-crowdstrike-within-78-minutes-to-cause-15-billion-in-losses-worldwide/&quot;&gt;&lt;em&gt;some $15 billion damages worldwide&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; in July 2024. Oops.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;triage&quot;&gt;Tria.ge&lt;/h3&gt;
&lt;p&gt;Triage provides a malware analysis sandbox and provides reports for submitted samples. Some kind soul already &lt;a href=&quot;https://tria.ge/240826-vhsrtawepj/behavioral4&quot;&gt;uploaded the one we found&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Triage analysis summary“Lumma”? “Stealer”? What’s that? Apparently this malware tries to steal…​ things? Let’s look into this.&lt;/p&gt;
&lt;p&gt;Some more interesting details can be found further down in the network section of the analysis. What’s a malware to do after it did its deeds? It has to send the stuff it found &lt;em&gt;somewhere&lt;/em&gt;, right? So Triage ran the malware in a sandbox and recorded the network traffic. These are some of the connections the malware made:&lt;/p&gt;
&lt;p&gt;Triage analysis network traffic&lt;code&gt;froytnewqowv.shop&lt;/code&gt; seems to be the URL of the Command-and-Control (C2) server of this malware. It tells the malware what to do and collects the bountiful harvest. Also take note of the &lt;code&gt;froytnewqowv.shop/api&lt;/code&gt; path that we will explore in a minute.&lt;/p&gt;
&lt;h2 id=&quot;trail-c2-server&quot;&gt;Trail: C2 server&lt;/h2&gt;
&lt;p&gt;Let’s see if we can find out more about who our malware talks to. WHO IS the one that owns the weird domain name?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“WHOIS is a public database that houses the information collected when someone registers a domain name”
— &lt;a href=&quot;https://www.domain.com/blog/what-is-whois-and-how-is-it-used/&quot;&gt;https://www.domain.com/blog/what-is-whois-and-how-is-it-used/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;whois&quot;&gt;WhoIs&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.whois.com/whois/froytnewqowv.shop&quot;&gt;whois&lt;/a&gt; look-up shows that the domain was registered just a few days ago via &lt;a href=&quot;https://www.namecheap.com/&quot;&gt;namecheap.com&lt;/a&gt;. This register hides the client’s contact information, like physical address or email.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;whois&lt;/code&gt; lookup of &lt;code&gt;the URL froytnewqowv.shop&lt;/code&gt;Furthermore, we see from the “Name Server” entries that they hide behind &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt;. This service can, among other things, act as an intermediary between a user and a website. This means that we cannot directly find out the IP address — the “actual address” that the URL is translated into — of the C2 server, since all the traffic is routed through Cloudflare’s machines first.&lt;/p&gt;
&lt;p&gt;Little Noob is privacy-conscious.&lt;/p&gt;
&lt;p&gt;Let’s give the C2 server a visit then. We open the website in a browser.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note that it’s usually not a good idea to browse possibly malicious sites, since they can* infect your computer.&lt;/p&gt;
&lt;h3 id=&quot;browsing-the-c2-website&quot;&gt;Browsing the C2 website&lt;/h3&gt;
&lt;p&gt;Opening the URL in a browser lets us see:&lt;/p&gt;
&lt;p&gt;Visiting the C2 serverWell, that’s not much. This is the default landing page of their &lt;code&gt;nginx&lt;/code&gt; web server, with no content whatsoever. Let’s have a look at the source code of this website then, by pressing &lt;code&gt;CTRL+U&lt;/code&gt; in the browser.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;html&gt;
&amp;#x3C;head&gt;&amp;#x3C;title&gt;405 Not Allowed&amp;#x3C;/title&gt;&amp;#x3C;/head&gt;
&amp;#x3C;body&gt;
&amp;#x3C;center&gt;&amp;#x3C;h1&gt;405 Not Allowed&amp;#x3C;/h1&gt;&amp;#x3C;/center&gt;
&amp;#x3C;hr&gt;&amp;#x3C;center&gt;nginx/1.18.0 (Ubuntu)&amp;#x3C;/center&gt;
&amp;#x3C;/body&gt;
&amp;#x3C;/html&gt;Ah yes. Privacy conscious. At least we learn that the server runs &lt;code&gt;nginx&lt;/code&gt; version &lt;code&gt;1.18.0&lt;/code&gt; on Ubuntu.&lt;/p&gt;
&lt;p&gt;If we look back at the network section of the Triage analysis, we see that the malware made a request to the &lt;code&gt;/api&lt;/code&gt; path. API stands for Application Programming Interface **and is basically a somewhat standardized interface for talking to computers programmatically. What does that API path look like in the browser?&lt;/p&gt;
&lt;p&gt;API pathI guess I’m not invited to that party. Let’s explore the website a bit more and guess some other paths.&lt;/p&gt;
&lt;p&gt;404 pageNope. Not that easy, apparently. &lt;code&gt;404&lt;/code&gt; is browser-speak for “I can’t find what you asked of me”. Let’s see what Google knows about this URL.&lt;/p&gt;
&lt;p&gt;Google search for the C2 URLAha. Another path: &lt;code&gt;/apib&lt;/code&gt;. Where does this lead to?&lt;/p&gt;
&lt;p&gt;A different 404 page? Hmm…Another dead end? But this one look different. Russian again. How come? After trying some more URLs by hand, it is apparent that everything that starts with &lt;code&gt;/api&lt;/code&gt; is leading to this &lt;em&gt;other&lt;/em&gt; 404-not-found page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/apia&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/apib&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api_I_misconfigured_my_nginx_server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s see what we can learn from this page. Translation:&lt;/p&gt;
&lt;p&gt;404**
Oops… There was a mistake&lt;/p&gt;
&lt;p&gt;Sorry, this page was not found or the administrator has closed access to it&lt;/p&gt;
&lt;p&gt;&amp;#x3C;- To the main pageNo surprises here. Let’s download the whole thing and see what we get.&lt;/p&gt;
&lt;h3 id=&quot;website-source-code&quot;&gt;Website source code&lt;/h3&gt;
&lt;p&gt;The website source contains the following files:&lt;/p&gt;
&lt;p&gt;$ tree
.
├── Ошибка_files
│   ├── dober.html
│   ├── doberman.min.html
│   ├── jquery-3.6.0.min.js
│   ├── tabler-flags.min.css
│   ├── tabler-icons.min.css
│   ├── tabler.min.css
│   ├── tabler.min.js
│   ├── tabler-payments.min.css
│   ├── tabler-vendors.min.css
│   ├── tom-select.complete.min.js
│   └── tom-select.css
└── Ошибка.htmlOur error page seems to have been built with &lt;a href=&quot;https://tabler.io/&quot;&gt;tabler.io&lt;/a&gt;. This seems to be a bit too much effort for a simple 404 page. Tabler is often used to build elaborate dashboards. So there’s probably more to it.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;css&lt;/code&gt; files are Cascading Style Sheets (CSS), which are used for styling a web page. Not too interesting. &lt;code&gt;[tom-select](https://tom-select.js.org/)&lt;/code&gt; is a standard JavaScript framework for UI control. &lt;code&gt;[jquery](https://jquery.com/)&lt;/code&gt; is a library to simplify HTML development, assisting with document traversal and other things.&lt;/p&gt;
&lt;p&gt;The interesting ones that remain are &lt;code&gt;dober.html&lt;/code&gt; and &lt;code&gt;doberman.min.html&lt;/code&gt;. What are those? Let’s have a look.&lt;/p&gt;
&lt;p&gt;The content of &lt;code&gt;dober.html&lt;/code&gt; is one single line of text which looks like this:&lt;/p&gt;
&lt;p&gt;&amp;#x3C;!DOCTYPE html&gt;&amp;#x3C;html lang=“en-US”&gt;&amp;#x3C;head&gt;&amp;#x3C;title&gt;Just a moment…&amp;#x3C;/title&gt;&amp;#x3C;meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”&gt;&amp;#x3C;meta http-equiv=“X-UA-Compatible” content=“IE=Edge”&gt;&amp;#x3C;meta name=“robots” content=“noindex,nofollow”&gt;&amp;#x3C;meta name=“viewport” content=“width=device-width,initial-scale=1”&gt;&amp;#x3C;style&gt;*{box-sizing:border-box;margin:0;padding:0}html{line-height:1.15;-webkit-text-size-adjust:100%;color:#313131}button,html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}@media (prefers-color-sch…Urgh. This HTML vomit is “minified”, which means it is condensed as much as possible to save bandwidth when opening a website. This makes it hard to read for us humans, though. Luckily we can get some help with disentangling it.&lt;/p&gt;
&lt;h3 id=&quot;unminifycom&quot;&gt;Unminify.com&lt;/h3&gt;
&lt;p&gt;While there are Integrated Development Environments (IDEs) that can disentangle minified HTML, there are also websites that do this for you with a click of a button.&lt;/p&gt;
&lt;p&gt;Unminifying HTML code, making it readable and prettyThe code in the screenshot above is now much more readable. Below in the unminified code of &lt;code&gt;doberman.min.html&lt;/code&gt; we can find a reference to a file that does not seem to exist. An excerpt of &lt;code&gt;doberman.min.html&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&amp;#x3C;script&gt;
(function () {
window._cf_chl_opt = {
cvId: “3”,
cZone: “froytnewqowv.shop”,
cType: “interactive”,
cNounce: “11691”,
cRay: “8b96971bcef66608”,
cHash: “a7c37071216d981”,
cUPMDTk: “/core/panel/js/doberman.min.js?2&amp;#x26;__cf_chl_tk=POTzyU0ftLF9cvsIaAitlr5np8LsKoghhsVMME6MjWg-1724704337-0.0.1.1-2559”,Where is this file &lt;code&gt;/core/panel/js/doberman.min.js&lt;/code&gt; referenced here? It was not downloaded with the rest. Is it being dynamically created and loaded? I would not know without more time to study it. Again, luckily, other people already did the hard work for us. Searching for this file string on Google leads to &lt;a href=&quot;https://www.intrinsec.com/wp-content/uploads/2023/10/TLP-CLEAR-Lumma-Stealer-EN-Information-report.pdf&quot;&gt;an in-depth report&lt;/a&gt; by the French security firm &lt;a href=&quot;https://www.intrinsec.com/&quot;&gt;Intrisec&lt;/a&gt;. The mysterious file is apparently not present anymore in this “newer” version of the Lumma Stealer:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;We also noticed the absence of the file “doberman.min.js” on new Lumma C2 panel […]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The full report is a fascinating read. Here’s the summary:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Various actors actively deploying Lumma Stealer in multiple campaigns&lt;/em&gt;**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lumma Stealer, also known as LummaC2 Stealer, is a malware-as-a-service sold through Telegram and Russian-speaking cybercrime forums. […​] Lumma is an information stealer written in C/C++ language that has been observed in the wild since at least August 2022. […​] This malware is designed to pilfer sensitive data from infected devices. Among the data targeted are cryptocurrency wallets, browser extensions, two-factor authentication codes, logins and passwords stored on browsers, and various files.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;trail-business-case&quot;&gt;Trail: Business Case&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://outpost24.com/&quot;&gt;Outpost24&lt;/a&gt; &lt;a href=&quot;https://outpost24.com/blog/everything-you-need-to-know-lummac2-stealer/&quot;&gt;explored the malware in detail&lt;/a&gt;, including their store. Joining the dark side starts sets you back $250, or a bit more if you aim for best-value. Granted, the chance of someone falling for this weak threat is low. But if the net is cast wide enough…? Imagine just a few victims falling for the malware, finding just &lt;em&gt;one&lt;/em&gt; &lt;a href=&quot;https://techinformed.com/crypto-hackers-have-already-stolen-almost-1-4-billion-this-year/&quot;&gt;juicy crypto-wallet&lt;/a&gt;. The amount of potential profit per dollar is staggering, as is the damage caused.&lt;/p&gt;
&lt;p&gt;Lumma Stealer store page, translated from Russian — by &lt;a href=&quot;https://outpost24.com/blog/everything-you-need-to-know-lummac2-stealer/&quot;&gt;Outpost24&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;
&lt;p&gt;As Research Software Engineers we don’t often think about cybersecurity. Our institute, the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, is an independent foundation and not a company with valuable trade secrets. We don’t usually work in projects that are high-profile targets. Nevertheless, people who write code are increasingly targeted by cyber-criminals. Do you remember the &lt;a href=&quot;https://arstechnica.com/security/2024/04/what-we-know-about-the-xz-utils-backdoor-that-almost-infected-the-world/&quot;&gt;drama around the program &lt;/a&gt;&lt;code&gt;[xz utils](https://arstechnica.com/security/2024/04/what-we-know-about-the-xz-utils-backdoor-that-almost-infected-the-world/)&lt;/code&gt; in March 2024? A user infiltrated a widely used open-source project, earned trust by making meaningful contributions, and finally injected a malicious backdoor into the source code. It was caught just in time before it was distributed widely.&lt;/p&gt;
&lt;p&gt;The case discussed here is a much cruder approach, amateurish even. Malware-as-a-service, like the Lumma Stealer, makes malware accessible for the masses, enabling this spray-and-pray approach. We can expect its use to only increase in time. It shows that all of us can be targets, at any time.&lt;/p&gt;
&lt;p&gt;Stay vigilant.&lt;/p&gt;
&lt;p&gt;Cross post: &lt;a href=&quot;https://ole.mn/posts/a-helpful-noob/&quot;&gt;https://ole.mn/posts/a-helpful-noob/&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 21 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;A Helpful Noob&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-helpful-noob-a2f448b4.lQj8rzQD_Z2cSNID.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@keiteu_ko?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Keiteu Ko&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Yesterday, my colleague &lt;a href=&quot;https://github.com/fdiblen&quot;&gt;Faruk&lt;/a&gt; asked me to conduct a Hallway Test for the &lt;code&gt;[NLeSC/python-template](https://github.com/NLeSC/python-template)&lt;/code&gt; he is working on: he just grabbed me off the hallway and asked me to give it a spin. This is, however, not a story about the test, but of open-source intelligence (OSINT) and the contributions of yet another “helpful noob”.&lt;/p&gt;
&lt;p&gt;Right after I posted my feedback in an &lt;a href=&quot;https://github.com/NLeSC/python-template/issues/554&quot;&gt;issue&lt;/a&gt; of the project, someone else posted a helpful contribution right underneath:&lt;/p&gt;
&lt;p&gt;GitHub comment from xiaobai-marker, with edited link so y’all don’t get any funny ideasHuh? It took this person only a few seconds to post a fix for quite a list of small changes that I posted. That’s so nice! So let’s do a review of &lt;em&gt;their&lt;/em&gt; contributions.&lt;/p&gt;
&lt;h2 id=&quot;trail-github&quot;&gt;Trail: GitHub&lt;/h2&gt;
&lt;p&gt;Their GitHub handle is &lt;code&gt;xiaobai-marker&lt;/code&gt;. XiaoBai is (Pinyin writing of) Chinese and translates to “little white”, not referring to the actual color, but more in the direction of “unsullied”. It means Little Noob.&lt;/p&gt;
&lt;p&gt;A brief dive into &lt;code&gt;xiaobai-marker&lt;/code&gt; ‘s GitHub profile (by now mysteriously removed) confirms this initial impression.&lt;/p&gt;
&lt;p&gt;GitHub profile of &lt;code&gt;xiaobai-marker&lt;/code&gt;They forked only three publicly available repositories. They apparently deal with self-driving toy cars and machine learning to detect road lanes. Fun! However, that’s not a lot of content for someone who seems to contribute to other projects, especially considering that they did not open any repositories themselves.&lt;/p&gt;
&lt;p&gt;But we’re not judging. Any contributions are welcome, and that includes those from people with little experience. So let’s have a look at their actual contribution.&lt;/p&gt;
&lt;h2 id=&quot;trail-download-link&quot;&gt;Trail: Download Link&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mediafire.com&quot;&gt;MediaFire&lt;/a&gt; is a known file storage and sharing website. Clicking &lt;em&gt;this&lt;/em&gt; link is not &lt;em&gt;per se&lt;/em&gt; dangerous. Still, we proceed with caution.&lt;/p&gt;
&lt;p&gt;MediaFire download pageMediaFire uses VirusTotal to scan for malicious files. This inspires confidence, right? An encrypted &lt;code&gt;*.zip&lt;/code&gt; file, however, is opaque to any scans since we can’t look inside without the password, which was supplied on GitHub and is not known to MediaFire or VirusTotal. Another interesting detail is where the file comes from. Apparently it was uploaded the same day from somewhere in Russia. Is our Little Noob from Russia?&lt;/p&gt;
&lt;p&gt;Let’s check out the files now.&lt;/p&gt;
&lt;h2 id=&quot;trail-files&quot;&gt;Trail: Files&lt;/h2&gt;
&lt;p&gt;What did we actually download? A rather small zip file.&lt;/p&gt;
&lt;p&gt;$ ls -lah fix.zip
-rw-r—r— 1 ole users 367K Aug 27 08:15 fix.zipProviding the password, we can unpack it and have a look at the content.&lt;/p&gt;
&lt;p&gt;$ 7z e -pchangeme fix.zip&lt;/p&gt;
&lt;p&gt;7-Zip [64] 17.05 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
p7zip Version 17.05 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)&lt;/p&gt;
&lt;p&gt;Scanning the drive for archives:
1 file, 375771 bytes (367 KiB)&lt;/p&gt;
&lt;h2 id=&quot;extracting-archive-fixzip&quot;&gt;Extracting archive: fix.zip&lt;/h2&gt;
&lt;p&gt;Path = fix.zip
Type = zip
Physical Size = 375771&lt;/p&gt;
&lt;p&gt;Everything is Ok&lt;/p&gt;
&lt;p&gt;Folders: 1
Files: 2
Size:       747008
Compressed: 375771What did we just unpack?&lt;/p&gt;
&lt;p&gt;$ ls -lah fix/
total 456K
-rw-r—r— 1 ole users 490K Aug 27 08:15 msvcp140.dll
-rw-r—r— 1 ole users 240K Aug 27 08:15 x86_64-w64-ranlib.exeHuh. &lt;code&gt;ranlib&lt;/code&gt; is a standard programming tool, although here it is supposed to be an installer (!). This “fix” seems to have been written for a Windows system. I can’t run it on my Linux machine. Bummer. I’m also not very good at decompiling &lt;code&gt;*.exe&lt;/code&gt; files to check what’s really inside. But we can ask some websites for assistance.&lt;/p&gt;
&lt;h3 id=&quot;virustotal&quot;&gt;VirusTotal&lt;/h3&gt;
&lt;p&gt;First we upload the file to &lt;a href=&quot;https://virustotal.com&quot;&gt;virustotal.com&lt;/a&gt;, a Google-owned file and link analyzer and one of the authorities in the space of malware indexing. On the day of the initial analysis, 28 of 75 security vendors &lt;a href=&quot;https://www.virustotal.com/gui/file/546c34c2782216278a8273d3c9d3a954a980c7c2c7be220914aefe446fe94fd8/detection&quot;&gt;flagged the files as malicious&lt;/a&gt;. You don’t say! One day later this number is up to 35. It seems to be a fresh strain that is quickly being picked up by the security community.&lt;/p&gt;
&lt;p&gt;VirusTotal analysisSo what do we have here? “Trojan”? “MalwareX”? This is still quite vague.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Fun fact: One of the analyses — fourth row, right side — comes from CrowdStrike. Those are guys that &lt;em&gt;&lt;a href=&quot;https://arstechnica.com/information-technology/2024/07/major-outages-at-crowdstrike-microsoft-leave-the-world-with-bsods-and-confusion/&quot;&gt;&lt;em&gt;crashed&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; some &lt;em&gt;&lt;a href=&quot;https://blogs.microsoft.com/blog/2024/07/20/helping-our-customers-through-the-crowdstrike-outage/&quot;&gt;&lt;em&gt;8.5 million rather important Windows computers&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, resulting in &lt;em&gt;&lt;a href=&quot;https://www.oxfordeconomics.com/resource/crowdstrike-update-grounds-thousands-of-flights/&quot;&gt;&lt;em&gt;over 10.000 cancelled flights&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and causing &lt;em&gt;&lt;a href=&quot;https://www.neowin.net/news/systems-paralyzed-by-crowdstrike-within-78-minutes-to-cause-15-billion-in-losses-worldwide/&quot;&gt;&lt;em&gt;some $15 billion damages worldwide&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; in July 2024. Oops.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;triage&quot;&gt;Tria.ge&lt;/h3&gt;
&lt;p&gt;Triage provides a malware analysis sandbox and provides reports for submitted samples. Some kind soul already &lt;a href=&quot;https://tria.ge/240826-vhsrtawepj/behavioral4&quot;&gt;uploaded the one we found&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Triage analysis summary“Lumma”? “Stealer”? What’s that? Apparently this malware tries to steal…​ things? Let’s look into this.&lt;/p&gt;
&lt;p&gt;Some more interesting details can be found further down in the network section of the analysis. What’s a malware to do after it did its deeds? It has to send the stuff it found &lt;em&gt;somewhere&lt;/em&gt;, right? So Triage ran the malware in a sandbox and recorded the network traffic. These are some of the connections the malware made:&lt;/p&gt;
&lt;p&gt;Triage analysis network traffic&lt;code&gt;froytnewqowv.shop&lt;/code&gt; seems to be the URL of the Command-and-Control (C2) server of this malware. It tells the malware what to do and collects the bountiful harvest. Also take note of the &lt;code&gt;froytnewqowv.shop/api&lt;/code&gt; path that we will explore in a minute.&lt;/p&gt;
&lt;h2 id=&quot;trail-c2-server&quot;&gt;Trail: C2 server&lt;/h2&gt;
&lt;p&gt;Let’s see if we can find out more about who our malware talks to. WHO IS the one that owns the weird domain name?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“WHOIS is a public database that houses the information collected when someone registers a domain name”
— &lt;a href=&quot;https://www.domain.com/blog/what-is-whois-and-how-is-it-used/&quot;&gt;https://www.domain.com/blog/what-is-whois-and-how-is-it-used/&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;whois&quot;&gt;WhoIs&lt;/h3&gt;
&lt;p&gt;A &lt;a href=&quot;https://www.whois.com/whois/froytnewqowv.shop&quot;&gt;whois&lt;/a&gt; look-up shows that the domain was registered just a few days ago via &lt;a href=&quot;https://www.namecheap.com/&quot;&gt;namecheap.com&lt;/a&gt;. This register hides the client’s contact information, like physical address or email.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;whois&lt;/code&gt; lookup of &lt;code&gt;the URL froytnewqowv.shop&lt;/code&gt;Furthermore, we see from the “Name Server” entries that they hide behind &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt;. This service can, among other things, act as an intermediary between a user and a website. This means that we cannot directly find out the IP address — the “actual address” that the URL is translated into — of the C2 server, since all the traffic is routed through Cloudflare’s machines first.&lt;/p&gt;
&lt;p&gt;Little Noob is privacy-conscious.&lt;/p&gt;
&lt;p&gt;Let’s give the C2 server a visit then. We open the website in a browser.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note that it’s usually not a good idea to browse possibly malicious sites, since they can* infect your computer.&lt;/p&gt;
&lt;h3 id=&quot;browsing-the-c2-website&quot;&gt;Browsing the C2 website&lt;/h3&gt;
&lt;p&gt;Opening the URL in a browser lets us see:&lt;/p&gt;
&lt;p&gt;Visiting the C2 serverWell, that’s not much. This is the default landing page of their &lt;code&gt;nginx&lt;/code&gt; web server, with no content whatsoever. Let’s have a look at the source code of this website then, by pressing &lt;code&gt;CTRL+U&lt;/code&gt; in the browser.&lt;/p&gt;
&lt;p&gt;&amp;#x3C;html&gt;
&amp;#x3C;head&gt;&amp;#x3C;title&gt;405 Not Allowed&amp;#x3C;/title&gt;&amp;#x3C;/head&gt;
&amp;#x3C;body&gt;
&amp;#x3C;center&gt;&amp;#x3C;h1&gt;405 Not Allowed&amp;#x3C;/h1&gt;&amp;#x3C;/center&gt;
&amp;#x3C;hr&gt;&amp;#x3C;center&gt;nginx/1.18.0 (Ubuntu)&amp;#x3C;/center&gt;
&amp;#x3C;/body&gt;
&amp;#x3C;/html&gt;Ah yes. Privacy conscious. At least we learn that the server runs &lt;code&gt;nginx&lt;/code&gt; version &lt;code&gt;1.18.0&lt;/code&gt; on Ubuntu.&lt;/p&gt;
&lt;p&gt;If we look back at the network section of the Triage analysis, we see that the malware made a request to the &lt;code&gt;/api&lt;/code&gt; path. API stands for Application Programming Interface **and is basically a somewhat standardized interface for talking to computers programmatically. What does that API path look like in the browser?&lt;/p&gt;
&lt;p&gt;API pathI guess I’m not invited to that party. Let’s explore the website a bit more and guess some other paths.&lt;/p&gt;
&lt;p&gt;404 pageNope. Not that easy, apparently. &lt;code&gt;404&lt;/code&gt; is browser-speak for “I can’t find what you asked of me”. Let’s see what Google knows about this URL.&lt;/p&gt;
&lt;p&gt;Google search for the C2 URLAha. Another path: &lt;code&gt;/apib&lt;/code&gt;. Where does this lead to?&lt;/p&gt;
&lt;p&gt;A different 404 page? Hmm…Another dead end? But this one look different. Russian again. How come? After trying some more URLs by hand, it is apparent that everything that starts with &lt;code&gt;/api&lt;/code&gt; is leading to this &lt;em&gt;other&lt;/em&gt; 404-not-found page:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/apia&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/apib&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/api_I_misconfigured_my_nginx_server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s see what we can learn from this page. Translation:&lt;/p&gt;
&lt;p&gt;404**
Oops… There was a mistake&lt;/p&gt;
&lt;p&gt;Sorry, this page was not found or the administrator has closed access to it&lt;/p&gt;
&lt;p&gt;&amp;#x3C;- To the main pageNo surprises here. Let’s download the whole thing and see what we get.&lt;/p&gt;
&lt;h3 id=&quot;website-source-code&quot;&gt;Website source code&lt;/h3&gt;
&lt;p&gt;The website source contains the following files:&lt;/p&gt;
&lt;p&gt;$ tree
.
├── Ошибка_files
│   ├── dober.html
│   ├── doberman.min.html
│   ├── jquery-3.6.0.min.js
│   ├── tabler-flags.min.css
│   ├── tabler-icons.min.css
│   ├── tabler.min.css
│   ├── tabler.min.js
│   ├── tabler-payments.min.css
│   ├── tabler-vendors.min.css
│   ├── tom-select.complete.min.js
│   └── tom-select.css
└── Ошибка.htmlOur error page seems to have been built with &lt;a href=&quot;https://tabler.io/&quot;&gt;tabler.io&lt;/a&gt;. This seems to be a bit too much effort for a simple 404 page. Tabler is often used to build elaborate dashboards. So there’s probably more to it.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;css&lt;/code&gt; files are Cascading Style Sheets (CSS), which are used for styling a web page. Not too interesting. &lt;code&gt;[tom-select](https://tom-select.js.org/)&lt;/code&gt; is a standard JavaScript framework for UI control. &lt;code&gt;[jquery](https://jquery.com/)&lt;/code&gt; is a library to simplify HTML development, assisting with document traversal and other things.&lt;/p&gt;
&lt;p&gt;The interesting ones that remain are &lt;code&gt;dober.html&lt;/code&gt; and &lt;code&gt;doberman.min.html&lt;/code&gt;. What are those? Let’s have a look.&lt;/p&gt;
&lt;p&gt;The content of &lt;code&gt;dober.html&lt;/code&gt; is one single line of text which looks like this:&lt;/p&gt;
&lt;p&gt;&amp;#x3C;!DOCTYPE html&gt;&amp;#x3C;html lang=“en-US”&gt;&amp;#x3C;head&gt;&amp;#x3C;title&gt;Just a moment…&amp;#x3C;/title&gt;&amp;#x3C;meta http-equiv=“Content-Type” content=“text/html; charset=UTF-8”&gt;&amp;#x3C;meta http-equiv=“X-UA-Compatible” content=“IE=Edge”&gt;&amp;#x3C;meta name=“robots” content=“noindex,nofollow”&gt;&amp;#x3C;meta name=“viewport” content=“width=device-width,initial-scale=1”&gt;&amp;#x3C;style&gt;*{box-sizing:border-box;margin:0;padding:0}html{line-height:1.15;-webkit-text-size-adjust:100%;color:#313131}button,html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}@media (prefers-color-sch…Urgh. This HTML vomit is “minified”, which means it is condensed as much as possible to save bandwidth when opening a website. This makes it hard to read for us humans, though. Luckily we can get some help with disentangling it.&lt;/p&gt;
&lt;h3 id=&quot;unminifycom&quot;&gt;Unminify.com&lt;/h3&gt;
&lt;p&gt;While there are Integrated Development Environments (IDEs) that can disentangle minified HTML, there are also websites that do this for you with a click of a button.&lt;/p&gt;
&lt;p&gt;Unminifying HTML code, making it readable and prettyThe code in the screenshot above is now much more readable. Below in the unminified code of &lt;code&gt;doberman.min.html&lt;/code&gt; we can find a reference to a file that does not seem to exist. An excerpt of &lt;code&gt;doberman.min.html&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&amp;#x3C;script&gt;
(function () {
window._cf_chl_opt = {
cvId: “3”,
cZone: “froytnewqowv.shop”,
cType: “interactive”,
cNounce: “11691”,
cRay: “8b96971bcef66608”,
cHash: “a7c37071216d981”,
cUPMDTk: “/core/panel/js/doberman.min.js?2&amp;#x26;__cf_chl_tk=POTzyU0ftLF9cvsIaAitlr5np8LsKoghhsVMME6MjWg-1724704337-0.0.1.1-2559”,Where is this file &lt;code&gt;/core/panel/js/doberman.min.js&lt;/code&gt; referenced here? It was not downloaded with the rest. Is it being dynamically created and loaded? I would not know without more time to study it. Again, luckily, other people already did the hard work for us. Searching for this file string on Google leads to &lt;a href=&quot;https://www.intrinsec.com/wp-content/uploads/2023/10/TLP-CLEAR-Lumma-Stealer-EN-Information-report.pdf&quot;&gt;an in-depth report&lt;/a&gt; by the French security firm &lt;a href=&quot;https://www.intrinsec.com/&quot;&gt;Intrisec&lt;/a&gt;. The mysterious file is apparently not present anymore in this “newer” version of the Lumma Stealer:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;We also noticed the absence of the file “doberman.min.js” on new Lumma C2 panel […]&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The full report is a fascinating read. Here’s the summary:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Various actors actively deploying Lumma Stealer in multiple campaigns&lt;/em&gt;**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lumma Stealer, also known as LummaC2 Stealer, is a malware-as-a-service sold through Telegram and Russian-speaking cybercrime forums. […​] Lumma is an information stealer written in C/C++ language that has been observed in the wild since at least August 2022. […​] This malware is designed to pilfer sensitive data from infected devices. Among the data targeted are cryptocurrency wallets, browser extensions, two-factor authentication codes, logins and passwords stored on browsers, and various files.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;trail-business-case&quot;&gt;Trail: Business Case&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://outpost24.com/&quot;&gt;Outpost24&lt;/a&gt; &lt;a href=&quot;https://outpost24.com/blog/everything-you-need-to-know-lummac2-stealer/&quot;&gt;explored the malware in detail&lt;/a&gt;, including their store. Joining the dark side starts sets you back $250, or a bit more if you aim for best-value. Granted, the chance of someone falling for this weak threat is low. But if the net is cast wide enough…? Imagine just a few victims falling for the malware, finding just &lt;em&gt;one&lt;/em&gt; &lt;a href=&quot;https://techinformed.com/crypto-hackers-have-already-stolen-almost-1-4-billion-this-year/&quot;&gt;juicy crypto-wallet&lt;/a&gt;. The amount of potential profit per dollar is staggering, as is the damage caused.&lt;/p&gt;
&lt;p&gt;Lumma Stealer store page, translated from Russian — by &lt;a href=&quot;https://outpost24.com/blog/everything-you-need-to-know-lummac2-stealer/&quot;&gt;Outpost24&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;
&lt;p&gt;As Research Software Engineers we don’t often think about cybersecurity. Our institute, the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, is an independent foundation and not a company with valuable trade secrets. We don’t usually work in projects that are high-profile targets. Nevertheless, people who write code are increasingly targeted by cyber-criminals. Do you remember the &lt;a href=&quot;https://arstechnica.com/security/2024/04/what-we-know-about-the-xz-utils-backdoor-that-almost-infected-the-world/&quot;&gt;drama around the program &lt;/a&gt;&lt;code&gt;[xz utils](https://arstechnica.com/security/2024/04/what-we-know-about-the-xz-utils-backdoor-that-almost-infected-the-world/)&lt;/code&gt; in March 2024? A user infiltrated a widely used open-source project, earned trust by making meaningful contributions, and finally injected a malicious backdoor into the source code. It was caught just in time before it was distributed widely.&lt;/p&gt;
&lt;p&gt;The case discussed here is a much cruder approach, amateurish even. Malware-as-a-service, like the Lumma Stealer, makes malware accessible for the masses, enabling this spray-and-pray approach. We can expect its use to only increase in time. It shows that all of us can be targets, at any time.&lt;/p&gt;
&lt;p&gt;Stay vigilant.&lt;/p&gt;
&lt;p&gt;Cross post: &lt;a href=&quot;https://ole.mn/posts/a-helpful-noob/&quot;&gt;https://ole.mn/posts/a-helpful-noob/&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/a-helpful-noob-a2f448b4.lQj8rzQD.jpg" medium="image"/><author>ole</author></item><item><title>Fast-Forward Merges on GitHub</title><link>https://blog2.esciencecenter.nl/posts/2025-02-21---fast-forward-merges-on-github</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-02-21---fast-forward-merges-on-github</guid><description>&lt;p&gt;&lt;em&gt;The year is 2025 CE and GitHub.com still can’t do “fast-forward” merges via its web-interface. But &lt;em&gt;you&lt;/em&gt; can; I’ll show you how.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@jhonkasalo?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Joakim Honkasalo&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;a href=&quot;https://github.com&quot;&gt;Github.com&lt;/a&gt; offers version-control-as-a-service, with all kinds of useful things bolted on top. The year is 2025 CE and GitHub leverages the vast power of &lt;code&gt;git&lt;/code&gt; and exposes it entirely to their users. Well, not entirely… One small feature of indomitable usefulness still holds out against the invaders. Well OK. Here the stories diverge.&lt;/p&gt;
&lt;p&gt;One &lt;code&gt;git&lt;/code&gt; feature that is not available via the &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt; web interface are “fast-forward (ff) merges”. It is among the highest &lt;code&gt;git&lt;/code&gt;-related feature requests with about 1500 upvotes.¹ To explain what that is and why one would want this, we have to take a detour first.&lt;/p&gt;
&lt;h2 id=&quot;intermezzo-merge-types&quot;&gt;Intermezzo: Merge Types&lt;/h2&gt;
&lt;p&gt;To set the ground for explaining fast-forward merging, I’ll cherry-pick (chuckle) a specific scenario.&lt;/p&gt;
&lt;p&gt;Let’s follow best practices where we have our &lt;code&gt;main&lt;/code&gt; branch protected, meaning that we cannot add changes to it directly. Any changes that should end up in &lt;code&gt;main&lt;/code&gt; will be merged via pull- (GitHub speak) or merge- (same, but GitLab speak) requests. That way there can be some auditing before code ends up in the &lt;code&gt;main&lt;/code&gt; branch. This could prevent minor hiccups like the &lt;a href=&quot;https://en.wikipedia.org/wiki/2024_CrowdStrike-related_IT_outages&quot;&gt;CrowdStrike-related IT outages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;nixCraft having a blast at CrowdstrikeGranted, I don’t think code pushed to &lt;code&gt;main&lt;/code&gt; was the cause for the global-scale IT outage, but it would have been funny if it was – however funny &lt;a href=&quot;https://www.businessinsider.com/businesses-claiming-losses-crowdstrike-outage-insurance-billions-losses-cyber-policies-2024-7&quot;&gt;~$10 billion in damages&lt;/a&gt; can be.&lt;/p&gt;
&lt;p&gt;A bit more opinionated than protecting &lt;code&gt;main&lt;/code&gt; is the choice to keep the &lt;code&gt;git&lt;/code&gt; commit history linear. With “commit” we mean a snapshot in time – a set of related changes to your code with a specific description – so you can find it back later. Reasons for a linear &lt;code&gt;git&lt;/code&gt; history could be that you follow the &lt;a href=&quot;https://finitestate.io/blog/git-v-branching-model&quot;&gt;Git V Branching Model&lt;/a&gt; or if you want to have &lt;a href=&quot;https://abelsiqueira.com/&quot;&gt;Abel&lt;/a&gt;’s &lt;a href=&quot;https://blog2.esciencecenter.nl/the-utopic-git-history-d44b81c09593&quot;&gt;Utopic Git History&lt;/a&gt;. In general, &lt;code&gt;git&lt;/code&gt; commit graphs can look a bit complicated.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git&lt;/code&gt; commit graph: Guitar Hero 🎸
&lt;code&gt;git&lt;/code&gt; commit graph: Harp 🎵
&lt;code&gt;git&lt;/code&gt; commit graph: London Underground 🚇 (/s)&lt;/p&gt;
&lt;h2 id=&quot;branches&quot;&gt;Branches&lt;/h2&gt;
&lt;p&gt;To compartmentalize development tasks and to keep the repository tidy, we often use “branches”. These are alternative realities of your code-base, and you can jump back and forth between them like &lt;a href=&quot;https://marvelcinematicuniverse.fandom.com/wiki/Doctor_Strange&quot;&gt;Dr. Strange&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Instead of the mess above, let’s simplify our &lt;code&gt;git&lt;/code&gt; commit history such that it looks like a straight string of pearls. In the following visualizations, time progresses towards the right. The horizontal lines represent branches, and the nodes on them are commits with a certain commit message. They &lt;em&gt;also&lt;/em&gt; have a specific fingerprint, called “hash”, that uniquely identifies them. We will come back to that later.&lt;/p&gt;
&lt;p&gt;When we work on a feature or a bugfix (or anything, really) we usually do that on a separate branch, nicely separated. After we finished working on this branch, we want to &lt;em&gt;somehow&lt;/em&gt; get the changes we made back onto the &lt;code&gt;main&lt;/code&gt; branch. There are different approaches for that.&lt;/p&gt;
&lt;h3 id=&quot;merge-commit&quot;&gt;Merge Commit&lt;/h3&gt;
&lt;p&gt;“Standard” merge commits leave the history where exactly the code came from intact. An extra “merge commit” contains the changes from our &lt;code&gt;feature&lt;/code&gt; branch.&lt;/p&gt;
&lt;h3 id=&quot;rebase&quot;&gt;Rebase&lt;/h3&gt;
&lt;p&gt;Another way to keep the &lt;code&gt;git&lt;/code&gt; history linear is “rebasing”. This approach basically re-plays the new commits that happened on the &lt;code&gt;feature&lt;/code&gt; branch onto the &lt;code&gt;main&lt;/code&gt; branch. This means that there is no “merge commit” on the &lt;code&gt;main&lt;/code&gt; branch anymore. However, if there have been commits to &lt;code&gt;main&lt;/code&gt; after &lt;code&gt;feature&lt;/code&gt; has been branched off, the &lt;code&gt;feature&lt;/code&gt; commits are re-written. Do you remember the “hash” fingerprint, I mentioned before? Here it becomes important. When rebasing, the commit content and commit messages are the same, but since these are effectively “new” commits, the commit hashes are different! This means that anything that was attached to a certain hash, like signatures or tags, will point to the commits on the &lt;code&gt;feature&lt;/code&gt; branch. To demonstrate this, we attached a tag &lt;code&gt;v1.0.0&lt;/code&gt; to one commit on the &lt;code&gt;feature&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;Do you see how the tag is kept dangling on the now useless feature branch?&lt;/p&gt;
&lt;h3 id=&quot;fast-forward-merging&quot;&gt;Fast-forward Merging&lt;/h3&gt;
&lt;p&gt;“Fast-forward” merging can be achieved if &lt;code&gt;main&lt;/code&gt; did &lt;em&gt;not receive any commits&lt;/em&gt; in the meantime. So clean! Instead of re-writing the commits onto another branch, the &lt;code&gt;main&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;feature&lt;/code&gt; commits are basically pointers to the exact same commit.&lt;/p&gt;
&lt;p&gt;This looks very similar to rebasing, does it not?&lt;/p&gt;
&lt;p&gt;In fact, if the main branch did not receive any new commits since the branching, fast-forward merging is the same as rebasing…&lt;/p&gt;
&lt;h2 id=&quot;github-rebasing&quot;&gt;GitHub Rebasing&lt;/h2&gt;
&lt;p&gt;…unless you are using the GitHub web interface. When you rebase a &lt;code&gt;feature&lt;/code&gt; branch on GitHub onto an untouched &lt;code&gt;main&lt;/code&gt; branch, the commits are still re-written. This is contrary to how &lt;code&gt;git&lt;/code&gt; on the command line works. Why is that such a big deal? The commit messages are the same. The commit content is the same. Why worry about a different commit hash?&lt;/p&gt;
&lt;p&gt;It matters, because lots of things are tied to a commit hash. A commit signature is tied to its hash! The signature gets lost if the hash changes during a rebase. The same holds true for tags. &lt;code&gt;feature&lt;/code&gt; commit tags will point to the commits on the &lt;code&gt;feature&lt;/code&gt; branch, not to the re-written ones on &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;There are two ways to achieve fast-forward merging when using GitHub. One is convoluted and error prone. The other one is cursed. Choose wisely.&lt;/p&gt;
&lt;h3 id=&quot;using-local-git&quot;&gt;Using Local &lt;code&gt;git&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Protecting your &lt;code&gt;main&lt;/code&gt; branch means that you can’t commit to it directly. You can, however, push sanctioned changes from &lt;code&gt;main&lt;/code&gt; to your remote repository on &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt;. Wait, what? I thought you can’t touch &lt;code&gt;main&lt;/code&gt;? Follow me, I’ll show you.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a pull request from &lt;code&gt;feature&lt;/code&gt; to &lt;code&gt;main&lt;/code&gt; on &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Open a terminal and create some magic:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;cd your/project/folder     # cd into your project directory
git pull    # get the latest changes to your local computer
git switch main    # select the &lt;code&gt;main&lt;/code&gt; branch, if necessary
git merge —ff-only feature    # ff-merge feature onto main
git push      # allowed! because you created a pull request&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The pull request is automatically closed 🪄&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While rather low-tech, this relies on the workflow and discipline of the developers to work. This is a danger zone. It is 4:55pm on a Friday afternoon. You opened a pull request to contribute your work on the &lt;code&gt;feature&lt;/code&gt; branch and now watch patiently how the green circle closes that shows that all CI tests passed. Your fingers itch to wrap things up quickly so you can go home and wolf down the lasagna you prepared already the day before.&lt;/p&gt;
&lt;p&gt;The mouse cursor hovers over the fat, green “Merge pull request” button.&lt;/p&gt;
&lt;p&gt;Don’t. Don’t do it.Stop! Resist the temptation!**&lt;/p&gt;
&lt;p&gt;Click that button and you need to spend the next half hour undoing the rebased, re-written commits to &lt;code&gt;main&lt;/code&gt;, while sweating profusely because now you are messing directly with the &lt;code&gt;main&lt;/code&gt; branch, which you tried to prevent by protecting it in the first place. And by now, at home, your partner has finished both their and your piece of the lasagna.&lt;/p&gt;
&lt;p&gt;Instead of following the suggested path, you need to step away from the browser and open the terminal. You pull the changes, fast-forward merge locally and finally push to &lt;code&gt;main&lt;/code&gt;, as shown above.&lt;/p&gt;
&lt;h3 id=&quot;using-actions&quot;&gt;Using Actions&lt;/h3&gt;
&lt;p&gt;This approach needs some set-up, but is safer to use afterwards.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disable the Merge Button&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We have learned now that the fat, green “Merge” button is dangerous², so we need to disable it. In your GitHub repository, go to&lt;/p&gt;
&lt;p&gt;Settings &lt;em&gt;→&lt;/em&gt; General &lt;em&gt;→&lt;/em&gt; Pull Requests*&lt;/p&gt;
&lt;p&gt;and allow only Squash Merging. Next, go to&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Settings &lt;em&gt;→&lt;/em&gt; Rules &lt;em&gt;→&lt;/em&gt; Rulesets&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;and add a new rule. Name it &lt;code&gt;disable_merge_button&lt;/code&gt;, set it to “Active”. Set the “Target branches” to the “default branch” a.k.a main . Check “Require a pull request before merging” and, while waving a magic wand, set “Allowed merge methods” to “Rebase”, contradicting the general repository settings. Check whichever other settings you would like and click on “Save changes”.&lt;/p&gt;
&lt;p&gt;Now pull requests cannot be merged anymore. Yay?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Automate the Wizardry&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Set up the “Fast Forward Merge” Action from the GitHub Marketplace: &lt;a href=&quot;https://github.com/marketplace/actions/fast-forward-merge&quot;&gt;https://github.com/marketplace/actions/fast-forward-merge&lt;/a&gt; . This gives you two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A message posted in the PR chat indicating whether fast-forward merging is possible.&lt;/li&gt;
&lt;li&gt;A GitHub Action that fast-forward merges your Pull Request. You trigger it by commenting &lt;code&gt;/fast-forward&lt;/code&gt; in the Pull Request chat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;N.B.: For the triggered ff-merge to work, the Action yml file has to already exist in the main branch. So you have to get it there &lt;em&gt;once&lt;/em&gt; via impure means.&lt;/p&gt;
&lt;p&gt;It works. Yet it feels dirty. You just made a forbidden deal with C̶t̶h̶u̶l̶h̶u̶ Octocat and you will probably need to sacrifice the lasagna you made so it does not come to haunt you at night.&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-Up&lt;/h2&gt;
&lt;p&gt;By now you not only know what fast-forward merging is, you also have ways to use it on your external repository on &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt;. You might have subscribed to &lt;a href=&quot;https://github.com/orgs/community/discussions/4618&quot;&gt;github.com/orgs/community/discussions/4618&lt;/a&gt; and now patiently wait for the powers-that-be to enable this feature on their website.&lt;/p&gt;
&lt;p&gt;Until that happens, feel free to choose one of the workarounds outlined above.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Upvote count combines upvotes and thumbs-up from &lt;a href=&quot;https://github.com/orgs/community/discussions/4618&quot;&gt;https://github.com/orgs/community/discussions/4618&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If you want to achieve fast-forward merging, that is.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cross post: &lt;a href=&quot;https://ole.mn/posts/fast-forward-github/&quot;&gt;https://ole.mn/posts/fast-forward-github/&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 21 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;The year is 2025 CE and GitHub.com still can’t do “fast-forward” merges via its web-interface. But &lt;em&gt;you&lt;/em&gt; can; I’ll show you how.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@jhonkasalo?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Joakim Honkasalo&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;a href=&quot;https://github.com&quot;&gt;Github.com&lt;/a&gt; offers version-control-as-a-service, with all kinds of useful things bolted on top. The year is 2025 CE and GitHub leverages the vast power of &lt;code&gt;git&lt;/code&gt; and exposes it entirely to their users. Well, not entirely… One small feature of indomitable usefulness still holds out against the invaders. Well OK. Here the stories diverge.&lt;/p&gt;
&lt;p&gt;One &lt;code&gt;git&lt;/code&gt; feature that is not available via the &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt; web interface are “fast-forward (ff) merges”. It is among the highest &lt;code&gt;git&lt;/code&gt;-related feature requests with about 1500 upvotes.¹ To explain what that is and why one would want this, we have to take a detour first.&lt;/p&gt;
&lt;h2 id=&quot;intermezzo-merge-types&quot;&gt;Intermezzo: Merge Types&lt;/h2&gt;
&lt;p&gt;To set the ground for explaining fast-forward merging, I’ll cherry-pick (chuckle) a specific scenario.&lt;/p&gt;
&lt;p&gt;Let’s follow best practices where we have our &lt;code&gt;main&lt;/code&gt; branch protected, meaning that we cannot add changes to it directly. Any changes that should end up in &lt;code&gt;main&lt;/code&gt; will be merged via pull- (GitHub speak) or merge- (same, but GitLab speak) requests. That way there can be some auditing before code ends up in the &lt;code&gt;main&lt;/code&gt; branch. This could prevent minor hiccups like the &lt;a href=&quot;https://en.wikipedia.org/wiki/2024_CrowdStrike-related_IT_outages&quot;&gt;CrowdStrike-related IT outages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;nixCraft having a blast at CrowdstrikeGranted, I don’t think code pushed to &lt;code&gt;main&lt;/code&gt; was the cause for the global-scale IT outage, but it would have been funny if it was – however funny &lt;a href=&quot;https://www.businessinsider.com/businesses-claiming-losses-crowdstrike-outage-insurance-billions-losses-cyber-policies-2024-7&quot;&gt;~$10 billion in damages&lt;/a&gt; can be.&lt;/p&gt;
&lt;p&gt;A bit more opinionated than protecting &lt;code&gt;main&lt;/code&gt; is the choice to keep the &lt;code&gt;git&lt;/code&gt; commit history linear. With “commit” we mean a snapshot in time – a set of related changes to your code with a specific description – so you can find it back later. Reasons for a linear &lt;code&gt;git&lt;/code&gt; history could be that you follow the &lt;a href=&quot;https://finitestate.io/blog/git-v-branching-model&quot;&gt;Git V Branching Model&lt;/a&gt; or if you want to have &lt;a href=&quot;https://abelsiqueira.com/&quot;&gt;Abel&lt;/a&gt;’s &lt;a href=&quot;https://blog2.esciencecenter.nl/the-utopic-git-history-d44b81c09593&quot;&gt;Utopic Git History&lt;/a&gt;. In general, &lt;code&gt;git&lt;/code&gt; commit graphs can look a bit complicated.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git&lt;/code&gt; commit graph: Guitar Hero 🎸
&lt;code&gt;git&lt;/code&gt; commit graph: Harp 🎵
&lt;code&gt;git&lt;/code&gt; commit graph: London Underground 🚇 (/s)&lt;/p&gt;
&lt;h2 id=&quot;branches&quot;&gt;Branches&lt;/h2&gt;
&lt;p&gt;To compartmentalize development tasks and to keep the repository tidy, we often use “branches”. These are alternative realities of your code-base, and you can jump back and forth between them like &lt;a href=&quot;https://marvelcinematicuniverse.fandom.com/wiki/Doctor_Strange&quot;&gt;Dr. Strange&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Instead of the mess above, let’s simplify our &lt;code&gt;git&lt;/code&gt; commit history such that it looks like a straight string of pearls. In the following visualizations, time progresses towards the right. The horizontal lines represent branches, and the nodes on them are commits with a certain commit message. They &lt;em&gt;also&lt;/em&gt; have a specific fingerprint, called “hash”, that uniquely identifies them. We will come back to that later.&lt;/p&gt;
&lt;p&gt;When we work on a feature or a bugfix (or anything, really) we usually do that on a separate branch, nicely separated. After we finished working on this branch, we want to &lt;em&gt;somehow&lt;/em&gt; get the changes we made back onto the &lt;code&gt;main&lt;/code&gt; branch. There are different approaches for that.&lt;/p&gt;
&lt;h3 id=&quot;merge-commit&quot;&gt;Merge Commit&lt;/h3&gt;
&lt;p&gt;“Standard” merge commits leave the history where exactly the code came from intact. An extra “merge commit” contains the changes from our &lt;code&gt;feature&lt;/code&gt; branch.&lt;/p&gt;
&lt;h3 id=&quot;rebase&quot;&gt;Rebase&lt;/h3&gt;
&lt;p&gt;Another way to keep the &lt;code&gt;git&lt;/code&gt; history linear is “rebasing”. This approach basically re-plays the new commits that happened on the &lt;code&gt;feature&lt;/code&gt; branch onto the &lt;code&gt;main&lt;/code&gt; branch. This means that there is no “merge commit” on the &lt;code&gt;main&lt;/code&gt; branch anymore. However, if there have been commits to &lt;code&gt;main&lt;/code&gt; after &lt;code&gt;feature&lt;/code&gt; has been branched off, the &lt;code&gt;feature&lt;/code&gt; commits are re-written. Do you remember the “hash” fingerprint, I mentioned before? Here it becomes important. When rebasing, the commit content and commit messages are the same, but since these are effectively “new” commits, the commit hashes are different! This means that anything that was attached to a certain hash, like signatures or tags, will point to the commits on the &lt;code&gt;feature&lt;/code&gt; branch. To demonstrate this, we attached a tag &lt;code&gt;v1.0.0&lt;/code&gt; to one commit on the &lt;code&gt;feature&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;Do you see how the tag is kept dangling on the now useless feature branch?&lt;/p&gt;
&lt;h3 id=&quot;fast-forward-merging&quot;&gt;Fast-forward Merging&lt;/h3&gt;
&lt;p&gt;“Fast-forward” merging can be achieved if &lt;code&gt;main&lt;/code&gt; did &lt;em&gt;not receive any commits&lt;/em&gt; in the meantime. So clean! Instead of re-writing the commits onto another branch, the &lt;code&gt;main&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;feature&lt;/code&gt; commits are basically pointers to the exact same commit.&lt;/p&gt;
&lt;p&gt;This looks very similar to rebasing, does it not?&lt;/p&gt;
&lt;p&gt;In fact, if the main branch did not receive any new commits since the branching, fast-forward merging is the same as rebasing…&lt;/p&gt;
&lt;h2 id=&quot;github-rebasing&quot;&gt;GitHub Rebasing&lt;/h2&gt;
&lt;p&gt;…unless you are using the GitHub web interface. When you rebase a &lt;code&gt;feature&lt;/code&gt; branch on GitHub onto an untouched &lt;code&gt;main&lt;/code&gt; branch, the commits are still re-written. This is contrary to how &lt;code&gt;git&lt;/code&gt; on the command line works. Why is that such a big deal? The commit messages are the same. The commit content is the same. Why worry about a different commit hash?&lt;/p&gt;
&lt;p&gt;It matters, because lots of things are tied to a commit hash. A commit signature is tied to its hash! The signature gets lost if the hash changes during a rebase. The same holds true for tags. &lt;code&gt;feature&lt;/code&gt; commit tags will point to the commits on the &lt;code&gt;feature&lt;/code&gt; branch, not to the re-written ones on &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;There are two ways to achieve fast-forward merging when using GitHub. One is convoluted and error prone. The other one is cursed. Choose wisely.&lt;/p&gt;
&lt;h3 id=&quot;using-local-git&quot;&gt;Using Local &lt;code&gt;git&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Protecting your &lt;code&gt;main&lt;/code&gt; branch means that you can’t commit to it directly. You can, however, push sanctioned changes from &lt;code&gt;main&lt;/code&gt; to your remote repository on &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt;. Wait, what? I thought you can’t touch &lt;code&gt;main&lt;/code&gt;? Follow me, I’ll show you.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a pull request from &lt;code&gt;feature&lt;/code&gt; to &lt;code&gt;main&lt;/code&gt; on &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Open a terminal and create some magic:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;cd your/project/folder     # cd into your project directory
git pull    # get the latest changes to your local computer
git switch main    # select the &lt;code&gt;main&lt;/code&gt; branch, if necessary
git merge —ff-only feature    # ff-merge feature onto main
git push      # allowed! because you created a pull request&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The pull request is automatically closed 🪄&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While rather low-tech, this relies on the workflow and discipline of the developers to work. This is a danger zone. It is 4:55pm on a Friday afternoon. You opened a pull request to contribute your work on the &lt;code&gt;feature&lt;/code&gt; branch and now watch patiently how the green circle closes that shows that all CI tests passed. Your fingers itch to wrap things up quickly so you can go home and wolf down the lasagna you prepared already the day before.&lt;/p&gt;
&lt;p&gt;The mouse cursor hovers over the fat, green “Merge pull request” button.&lt;/p&gt;
&lt;p&gt;Don’t. Don’t do it.Stop! Resist the temptation!**&lt;/p&gt;
&lt;p&gt;Click that button and you need to spend the next half hour undoing the rebased, re-written commits to &lt;code&gt;main&lt;/code&gt;, while sweating profusely because now you are messing directly with the &lt;code&gt;main&lt;/code&gt; branch, which you tried to prevent by protecting it in the first place. And by now, at home, your partner has finished both their and your piece of the lasagna.&lt;/p&gt;
&lt;p&gt;Instead of following the suggested path, you need to step away from the browser and open the terminal. You pull the changes, fast-forward merge locally and finally push to &lt;code&gt;main&lt;/code&gt;, as shown above.&lt;/p&gt;
&lt;h3 id=&quot;using-actions&quot;&gt;Using Actions&lt;/h3&gt;
&lt;p&gt;This approach needs some set-up, but is safer to use afterwards.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disable the Merge Button&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We have learned now that the fat, green “Merge” button is dangerous², so we need to disable it. In your GitHub repository, go to&lt;/p&gt;
&lt;p&gt;Settings &lt;em&gt;→&lt;/em&gt; General &lt;em&gt;→&lt;/em&gt; Pull Requests*&lt;/p&gt;
&lt;p&gt;and allow only Squash Merging. Next, go to&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Settings &lt;em&gt;→&lt;/em&gt; Rules &lt;em&gt;→&lt;/em&gt; Rulesets&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;and add a new rule. Name it &lt;code&gt;disable_merge_button&lt;/code&gt;, set it to “Active”. Set the “Target branches” to the “default branch” a.k.a main . Check “Require a pull request before merging” and, while waving a magic wand, set “Allowed merge methods” to “Rebase”, contradicting the general repository settings. Check whichever other settings you would like and click on “Save changes”.&lt;/p&gt;
&lt;p&gt;Now pull requests cannot be merged anymore. Yay?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Automate the Wizardry&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Set up the “Fast Forward Merge” Action from the GitHub Marketplace: &lt;a href=&quot;https://github.com/marketplace/actions/fast-forward-merge&quot;&gt;https://github.com/marketplace/actions/fast-forward-merge&lt;/a&gt; . This gives you two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A message posted in the PR chat indicating whether fast-forward merging is possible.&lt;/li&gt;
&lt;li&gt;A GitHub Action that fast-forward merges your Pull Request. You trigger it by commenting &lt;code&gt;/fast-forward&lt;/code&gt; in the Pull Request chat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;N.B.: For the triggered ff-merge to work, the Action yml file has to already exist in the main branch. So you have to get it there &lt;em&gt;once&lt;/em&gt; via impure means.&lt;/p&gt;
&lt;p&gt;It works. Yet it feels dirty. You just made a forbidden deal with C̶t̶h̶u̶l̶h̶u̶ Octocat and you will probably need to sacrifice the lasagna you made so it does not come to haunt you at night.&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-Up&lt;/h2&gt;
&lt;p&gt;By now you not only know what fast-forward merging is, you also have ways to use it on your external repository on &lt;a href=&quot;https://github.com&quot;&gt;github.com&lt;/a&gt;. You might have subscribed to &lt;a href=&quot;https://github.com/orgs/community/discussions/4618&quot;&gt;github.com/orgs/community/discussions/4618&lt;/a&gt; and now patiently wait for the powers-that-be to enable this feature on their website.&lt;/p&gt;
&lt;p&gt;Until that happens, feel free to choose one of the workarounds outlined above.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Upvote count combines upvotes and thumbs-up from &lt;a href=&quot;https://github.com/orgs/community/discussions/4618&quot;&gt;https://github.com/orgs/community/discussions/4618&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;If you want to achieve fast-forward merging, that is.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cross post: &lt;a href=&quot;https://ole.mn/posts/fast-forward-github/&quot;&gt;https://ole.mn/posts/fast-forward-github/&lt;/a&gt;&lt;/p&gt;</content:encoded><author>ole</author></item><item><title>FAIR principles: 5000 years of common sense</title><link>https://blog2.esciencecenter.nl/posts/2025-02-20---fair-principles-5000-years-of-common-sense</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-02-20---fair-principles-5000-years-of-common-sense</guid><description>&lt;p&gt;The FAIR acronym stands for Findable, Accessible, Interoperable and Reusable. If you are a researcher, certainly you’ve heard about FAIR principles. FAIR data, FAIR software, … It may sound as another extra, new responsibility to take care of. But, is it? We argue it is not extra, and most importantly, it’s definitely not new. Come with us on a journey through the history of knowledge sharing.&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://javierdelacueva.es/&quot;&gt;Javier de la Cueva&lt;/a&gt;, with &lt;a href=&quot;https://pabrod.github.io/&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt; as coauthor.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;FAIR principles: 5000 years of common sense&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;342&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/fair-principles-5000-years-of-common-sen-e12a18c3.CXM7Q9rk_Z1qfUac.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@paulmelki?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Paul Melki&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;seminal paper&lt;/a&gt; where the FAIR guiding principles were stated was published in the year 2016. If you are a researcher, most certainly you would have heard about FAIR principles, FAIR data or FAIR research software.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Backronym&quot;&gt;backronym&lt;/a&gt; FAIR stands for Findable, Accessible, Interoperable and Reusable. In many forums, FAIR principles are understood as a new added responsibility to take care of by science and data practitioners. Contrary to this idea, we argue that to comply with the FAIR guiding principles is not a novel requirement. Indeed, the ideas behind the FAIR guiding principles are no less than 5000 years old, and can be traced back to the first libraries.&lt;/p&gt;
&lt;p&gt;If a name is an acronym, it is likely to be a buzzword. According to &lt;a href=&quot;https://en.wikipedia.org/wiki/Postmodernism%2C_or%2C_the_Cultural_Logic_of_Late_Capitalism&quot;&gt;Fredric Jameson&lt;/a&gt;, postmodernism is characterized by a permanent rebranding of old concepts so they may be commercialized again as new. And, indeed, FAIR is an acronym. It is often applied to research data, research software and even, although less often, to research publications. We argue that, contrary to other acronyms, FAIR is here to stay. Why? Because it is not a rebranding but the logical evolution in the digital realm of the principles that governed the analogical archives.&lt;/p&gt;
&lt;h2 id=&quot;a-fair-library&quot;&gt;A FAIR library&lt;/h2&gt;
&lt;p&gt;Let’s forget about the digital world for a moment and take a walk to the neighborhood’s library. There we are, surrounded by elderly people quietly reading their newspapers, kids attending read-aloud sessions, students… well, studying, and all kind of people borrowing and returning books.&lt;/p&gt;
&lt;p&gt;Let’s take a look around with the FAIR principles in mind.&lt;/p&gt;
&lt;h2 id=&quot;findable&quot;&gt;Findable&lt;/h2&gt;
&lt;p&gt;The materials in the library are certainly findable. A good library contains thousands of volumes, so they better have a system in place. This is as true today as it was in the library of Alexandria. Some of us still remember the times when this system was a set of cardboard boxes. Nowadays, the system is usually digital. You can even browse it from home!&lt;/p&gt;
&lt;h2 id=&quot;accessible&quot;&gt;Accessible&lt;/h2&gt;
&lt;p&gt;Accessibility is also a trademark of public libraries. The building itself usually can be freely accessed by anyone, and memberships are free or, worst case scenario, very affordable.&lt;/p&gt;
&lt;p&gt;Furthermore, many libraries have sections with materials for users with special needs. Audiobooks, books typed in Braille or in extra large fonts or simplified-language versions.&lt;/p&gt;
&lt;h2 id=&quot;interoperable&quot;&gt;Interoperable&lt;/h2&gt;
&lt;p&gt;Standardized fonts are one of those everyday wonders we don’t even realize anymore. Can you imagine how hard would it be to read if all the content was hand-written, with the unique scripting style of each author?&lt;/p&gt;
&lt;p&gt;Even more, think of word separation. Believe it or not, thefactthatwedonotwritelikethis is a relatively late development. We take spaces between written words for granted, but they are an example of technology.&lt;/p&gt;
&lt;p&gt;And of course, translations allow readers to operate with books originally written in languages unknown to them.&lt;/p&gt;
&lt;h2 id=&quot;reusable&quot;&gt;Reusable&lt;/h2&gt;
&lt;p&gt;How do you reuse a book’s content? Well, by using the most quintessential library service: borrow and return.&lt;/p&gt;
&lt;p&gt;Citing a book is also a form of reusablity. In some cases, you can even go further than citing and create derivatives from it. Think of for instance of encyclopediae and dictionaries. Those are composed works, with many authors and, to a large extent, independent entries. They are, by definition, work in progress.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The attentive reader certainly noticed that some of the features of books and libraries could fit in more than one FAIR concepts. For instance, are standardized fonts improving accessibility or interoperability? What about translations? Please don’t take our examples as a matter of rigorous taxonomy, but stick to the spirit of the idea.&lt;/p&gt;
&lt;p&gt;When looking back in history, it is tempting to stop too early back in time. Instead of going back only 20 years, let’s explore a bit deeper. Let’s not fall victims of the palimpsestic syndrome, i.e.*: attributing the creation of a concept to the first person or institution you heard it from. All of the FAIR principles, with minor adjustments, have been present since literally millenia ago in the world of books.&lt;/p&gt;
&lt;p&gt;We also need the FAIR principles to fight the &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;reproducibility crisis&lt;/a&gt; that is taking place in science as we speak. And keep in mind that reproducibility is not only desirable, but a defining feature of scientific knowledge.&lt;/p&gt;
&lt;p&gt;So no, FAIR principles are not new. And no, FAIR principles are not optional. Not bad for a buzzword!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;We want to express our gratitude to &lt;a href=&quot;https://www.esciencecenter.nl/team/lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martínez-Ortiz&lt;/a&gt; for their excellent feedback.&lt;/p&gt;</description><pubDate>Thu, 20 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The FAIR acronym stands for Findable, Accessible, Interoperable and Reusable. If you are a researcher, certainly you’ve heard about FAIR principles. FAIR data, FAIR software, … It may sound as another extra, new responsibility to take care of. But, is it? We argue it is not extra, and most importantly, it’s definitely not new. Come with us on a journey through the history of knowledge sharing.&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://javierdelacueva.es/&quot;&gt;Javier de la Cueva&lt;/a&gt;, with &lt;a href=&quot;https://pabrod.github.io/&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt; as coauthor.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;FAIR principles: 5000 years of common sense&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;342&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/fair-principles-5000-years-of-common-sen-e12a18c3.CXM7Q9rk_Z1qfUac.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@paulmelki?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Paul Melki&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;seminal paper&lt;/a&gt; where the FAIR guiding principles were stated was published in the year 2016. If you are a researcher, most certainly you would have heard about FAIR principles, FAIR data or FAIR research software.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Backronym&quot;&gt;backronym&lt;/a&gt; FAIR stands for Findable, Accessible, Interoperable and Reusable. In many forums, FAIR principles are understood as a new added responsibility to take care of by science and data practitioners. Contrary to this idea, we argue that to comply with the FAIR guiding principles is not a novel requirement. Indeed, the ideas behind the FAIR guiding principles are no less than 5000 years old, and can be traced back to the first libraries.&lt;/p&gt;
&lt;p&gt;If a name is an acronym, it is likely to be a buzzword. According to &lt;a href=&quot;https://en.wikipedia.org/wiki/Postmodernism%2C_or%2C_the_Cultural_Logic_of_Late_Capitalism&quot;&gt;Fredric Jameson&lt;/a&gt;, postmodernism is characterized by a permanent rebranding of old concepts so they may be commercialized again as new. And, indeed, FAIR is an acronym. It is often applied to research data, research software and even, although less often, to research publications. We argue that, contrary to other acronyms, FAIR is here to stay. Why? Because it is not a rebranding but the logical evolution in the digital realm of the principles that governed the analogical archives.&lt;/p&gt;
&lt;h2 id=&quot;a-fair-library&quot;&gt;A FAIR library&lt;/h2&gt;
&lt;p&gt;Let’s forget about the digital world for a moment and take a walk to the neighborhood’s library. There we are, surrounded by elderly people quietly reading their newspapers, kids attending read-aloud sessions, students… well, studying, and all kind of people borrowing and returning books.&lt;/p&gt;
&lt;p&gt;Let’s take a look around with the FAIR principles in mind.&lt;/p&gt;
&lt;h2 id=&quot;findable&quot;&gt;Findable&lt;/h2&gt;
&lt;p&gt;The materials in the library are certainly findable. A good library contains thousands of volumes, so they better have a system in place. This is as true today as it was in the library of Alexandria. Some of us still remember the times when this system was a set of cardboard boxes. Nowadays, the system is usually digital. You can even browse it from home!&lt;/p&gt;
&lt;h2 id=&quot;accessible&quot;&gt;Accessible&lt;/h2&gt;
&lt;p&gt;Accessibility is also a trademark of public libraries. The building itself usually can be freely accessed by anyone, and memberships are free or, worst case scenario, very affordable.&lt;/p&gt;
&lt;p&gt;Furthermore, many libraries have sections with materials for users with special needs. Audiobooks, books typed in Braille or in extra large fonts or simplified-language versions.&lt;/p&gt;
&lt;h2 id=&quot;interoperable&quot;&gt;Interoperable&lt;/h2&gt;
&lt;p&gt;Standardized fonts are one of those everyday wonders we don’t even realize anymore. Can you imagine how hard would it be to read if all the content was hand-written, with the unique scripting style of each author?&lt;/p&gt;
&lt;p&gt;Even more, think of word separation. Believe it or not, thefactthatwedonotwritelikethis is a relatively late development. We take spaces between written words for granted, but they are an example of technology.&lt;/p&gt;
&lt;p&gt;And of course, translations allow readers to operate with books originally written in languages unknown to them.&lt;/p&gt;
&lt;h2 id=&quot;reusable&quot;&gt;Reusable&lt;/h2&gt;
&lt;p&gt;How do you reuse a book’s content? Well, by using the most quintessential library service: borrow and return.&lt;/p&gt;
&lt;p&gt;Citing a book is also a form of reusablity. In some cases, you can even go further than citing and create derivatives from it. Think of for instance of encyclopediae and dictionaries. Those are composed works, with many authors and, to a large extent, independent entries. They are, by definition, work in progress.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The attentive reader certainly noticed that some of the features of books and libraries could fit in more than one FAIR concepts. For instance, are standardized fonts improving accessibility or interoperability? What about translations? Please don’t take our examples as a matter of rigorous taxonomy, but stick to the spirit of the idea.&lt;/p&gt;
&lt;p&gt;When looking back in history, it is tempting to stop too early back in time. Instead of going back only 20 years, let’s explore a bit deeper. Let’s not fall victims of the palimpsestic syndrome, i.e.*: attributing the creation of a concept to the first person or institution you heard it from. All of the FAIR principles, with minor adjustments, have been present since literally millenia ago in the world of books.&lt;/p&gt;
&lt;p&gt;We also need the FAIR principles to fight the &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;reproducibility crisis&lt;/a&gt; that is taking place in science as we speak. And keep in mind that reproducibility is not only desirable, but a defining feature of scientific knowledge.&lt;/p&gt;
&lt;p&gt;So no, FAIR principles are not new. And no, FAIR principles are not optional. Not bad for a buzzword!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;We want to express our gratitude to &lt;a href=&quot;https://www.esciencecenter.nl/team/lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martínez-Ortiz&lt;/a&gt; for their excellent feedback.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/fair-principles-5000-years-of-common-sen-e12a18c3.CXM7Q9rk.jpg" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Reproducible research with The Turing Way</title><link>https://blog2.esciencecenter.nl/posts/2025-02-10---reproducible-research-with-the-turing-way</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-02-10---reproducible-research-with-the-turing-way</guid><description>&lt;h2 id=&quot;the-netherlands-escience-center-and-turing-way-have-long-been-collaborating-on-the-common-goal-to-improve-reproducible-research-practices&quot;&gt;&lt;em&gt;The Netherlands eScience Center and Turing Way have long been collaborating on the common goal to improve reproducible research practices&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;A long time ago, in the far-away Amsterdam Science Park, the eScience Center created their own “&lt;a href=&quot;https://guide.esciencecenter.nl/&quot;&gt;eScience Center software development guide&lt;/a&gt;”. The aim of The Guide was for our RSEs to have a starting point to learn about how to write research software in adherence to open science practices. In other words, reproducible research software.&lt;/p&gt;
&lt;p&gt;After a few years, we came across &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;, and saw that there was a lot of overlap between our goals: we both wanted to share good practices in reproducible research in general, and reproducible research software specifically.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Reproducible research with The Turing Way&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;522&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/reproducible-research-with-the-turing-wa-c5be87d6.CPPUEa3s_28q7kT.webp&quot; srcset=&quot;&quot;&gt;
Image by &lt;a href=&quot;https://www.scriberia.com/&quot;&gt;Scriberia&lt;/a&gt;In 2020, we decided to migrate our content to &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;, with a few exceptions. Our rule of thumb is: all content which is interesting to a general audience should be in &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt; and; content which is eScience Center specific, should go in The Guide. For instance, the description of &lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/licensing&quot;&gt;why one should use a license&lt;/a&gt; goes in The Turing Way, whereas &lt;a href=&quot;https://guide.esciencecenter.nl/#/best_practices?id=licensing&quot;&gt;our decision to use Apache2&lt;/a&gt;, goes in The Guide.&lt;/p&gt;
&lt;p&gt;We used to block time to work on The Guide (“guide sprints”), which was essentially the same concept as the “Book Dash” events. We decided, in the spirit of open science, to NOT duplicate efforts, but instead dedicate our efforts in contributing to &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;. For a few years now, we have been (together with colleagues at VU Amsterdam and TU/Delft) involved in organizing local Book Dash events.&lt;/p&gt;
&lt;p&gt;At a personal level, being involved in the project has allowed me to learn a lot about how to contribute to an open science community. Specifically, a community that works on a project based on Open Source principles — and you don’t have to be a skilled developer to contribute. I have also met many knowledgeable inspiring people! I have felt really welcome as part of the community.&lt;/p&gt;
&lt;p&gt;For the last couple of years, I have also been involved in the Book Dash working group. In this group, I am involved in planning the Book Dash events, and try to encourage the (remote) participation of the Dutch community.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Reproducible research with The Turing Way&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;560&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/reproducible-research-with-the-turing-wa-bb58223c.BAYU7S73_Z1Uuvws.webp&quot; srcset=&quot;&quot;&gt;
Image by &lt;a href=&quot;https://www.scriberia.com/&quot;&gt;Scriberia&lt;/a&gt;&lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;The Turing Way*&lt;/a&gt; has become an important reference resource for our internal use and as part of the resources we share with the research community in the Netherlands.&lt;/p&gt;
&lt;p&gt;Beyond the multiple times on this blog, &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt; is mentioned in: our internal Project Management Protocol and our internal training resources, our &lt;a href=&quot;https://esciencecenter-digital-skills.github.io/research-software-support/&quot;&gt;Research Software Support&lt;/a&gt; training materials, our &lt;a href=&quot;https://doi.org/10.5281/zenodo.7038280&quot;&gt;Practical Guide to Software Management Plans&lt;/a&gt; and training materials developed in our &lt;a href=&quot;https://tdcc.nl/projects/project-initiatives-nes/tdcc-nes-bottleneck-projects/best-practices-for-sustainable-software/&quot;&gt;Best Practices for Sustainable software&lt;/a&gt; project point to different chapters as reference resources. It will also be part of the reference resources for the &lt;a href=&quot;https://everse.software/RSQKit/&quot;&gt;EVERSE Research Software Quality kit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the eScience Center,* &lt;em&gt;&lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; *is a priceless resource for sharing our expertise in contributing to reproducible research software.&lt;/p&gt;
&lt;p&gt;Has &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt; helped you in your work? Please share your story &lt;a href=&quot;https://github.com/the-turing-way/the-turing-way/issues/4032#top&quot;&gt;here&lt;/a&gt;. If you are interested in joining a Book Dash, you can contact &lt;a href=&quot;https://github.com/c-martinez&quot;&gt;Carlos&lt;/a&gt; or &lt;a href=&quot;https://github.com/the-turing-way/the-turing-way?tab=readme-ov-file#get-in-touch&quot;&gt;get in touch&lt;/a&gt; with &lt;em&gt;The Turing Way&lt;/em&gt;&lt;/p&gt;</description><pubDate>Mon, 10 Feb 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-netherlands-escience-center-and-turing-way-have-long-been-collaborating-on-the-common-goal-to-improve-reproducible-research-practices&quot;&gt;&lt;em&gt;The Netherlands eScience Center and Turing Way have long been collaborating on the common goal to improve reproducible research practices&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;A long time ago, in the far-away Amsterdam Science Park, the eScience Center created their own “&lt;a href=&quot;https://guide.esciencecenter.nl/&quot;&gt;eScience Center software development guide&lt;/a&gt;”. The aim of The Guide was for our RSEs to have a starting point to learn about how to write research software in adherence to open science practices. In other words, reproducible research software.&lt;/p&gt;
&lt;p&gt;After a few years, we came across &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;, and saw that there was a lot of overlap between our goals: we both wanted to share good practices in reproducible research in general, and reproducible research software specifically.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Reproducible research with The Turing Way&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;522&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/reproducible-research-with-the-turing-wa-c5be87d6.CPPUEa3s_28q7kT.webp&quot; srcset=&quot;&quot;&gt;
Image by &lt;a href=&quot;https://www.scriberia.com/&quot;&gt;Scriberia&lt;/a&gt;In 2020, we decided to migrate our content to &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;, with a few exceptions. Our rule of thumb is: all content which is interesting to a general audience should be in &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt; and; content which is eScience Center specific, should go in The Guide. For instance, the description of &lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/licensing&quot;&gt;why one should use a license&lt;/a&gt; goes in The Turing Way, whereas &lt;a href=&quot;https://guide.esciencecenter.nl/#/best_practices?id=licensing&quot;&gt;our decision to use Apache2&lt;/a&gt;, goes in The Guide.&lt;/p&gt;
&lt;p&gt;We used to block time to work on The Guide (“guide sprints”), which was essentially the same concept as the “Book Dash” events. We decided, in the spirit of open science, to NOT duplicate efforts, but instead dedicate our efforts in contributing to &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;. For a few years now, we have been (together with colleagues at VU Amsterdam and TU/Delft) involved in organizing local Book Dash events.&lt;/p&gt;
&lt;p&gt;At a personal level, being involved in the project has allowed me to learn a lot about how to contribute to an open science community. Specifically, a community that works on a project based on Open Source principles — and you don’t have to be a skilled developer to contribute. I have also met many knowledgeable inspiring people! I have felt really welcome as part of the community.&lt;/p&gt;
&lt;p&gt;For the last couple of years, I have also been involved in the Book Dash working group. In this group, I am involved in planning the Book Dash events, and try to encourage the (remote) participation of the Dutch community.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Reproducible research with The Turing Way&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;560&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/reproducible-research-with-the-turing-wa-bb58223c.BAYU7S73_Z1Uuvws.webp&quot; srcset=&quot;&quot;&gt;
Image by &lt;a href=&quot;https://www.scriberia.com/&quot;&gt;Scriberia&lt;/a&gt;&lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;The Turing Way*&lt;/a&gt; has become an important reference resource for our internal use and as part of the resources we share with the research community in the Netherlands.&lt;/p&gt;
&lt;p&gt;Beyond the multiple times on this blog, &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt; is mentioned in: our internal Project Management Protocol and our internal training resources, our &lt;a href=&quot;https://esciencecenter-digital-skills.github.io/research-software-support/&quot;&gt;Research Software Support&lt;/a&gt; training materials, our &lt;a href=&quot;https://doi.org/10.5281/zenodo.7038280&quot;&gt;Practical Guide to Software Management Plans&lt;/a&gt; and training materials developed in our &lt;a href=&quot;https://tdcc.nl/projects/project-initiatives-nes/tdcc-nes-bottleneck-projects/best-practices-for-sustainable-software/&quot;&gt;Best Practices for Sustainable software&lt;/a&gt; project point to different chapters as reference resources. It will also be part of the reference resources for the &lt;a href=&quot;https://everse.software/RSQKit/&quot;&gt;EVERSE Research Software Quality kit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the eScience Center,* &lt;em&gt;&lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; *is a priceless resource for sharing our expertise in contributing to reproducible research software.&lt;/p&gt;
&lt;p&gt;Has &lt;a href=&quot;https://book.the-turing-way.org/&quot;&gt;&lt;em&gt;The Turing Way&lt;/em&gt;&lt;/a&gt; helped you in your work? Please share your story &lt;a href=&quot;https://github.com/the-turing-way/the-turing-way/issues/4032#top&quot;&gt;here&lt;/a&gt;. If you are interested in joining a Book Dash, you can contact &lt;a href=&quot;https://github.com/c-martinez&quot;&gt;Carlos&lt;/a&gt; or &lt;a href=&quot;https://github.com/the-turing-way/the-turing-way?tab=readme-ov-file#get-in-touch&quot;&gt;get in touch&lt;/a&gt; with &lt;em&gt;The Turing Way&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/reproducible-research-with-the-turing-wa-c5be87d6.CPPUEa3s.png" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>A Different Game</title><link>https://blog2.esciencecenter.nl/posts/2025-01-28---a-different-game</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-01-28---a-different-game</guid><description>&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;&lt;em&gt;According to a panel of football experts, the world’s best male player of the year 2024 was Rodri. The choice is naturally debatable, but even if you put him together with other stars like Erling Haaland and Kylian Mbappé, they will not stand a chance in a match against a full team of 11 amateurs. The world stars could perform great dribblings and accurate passes, but they cannot play the team sport called football.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To build complex software, highly skilled programmers are essential. But only effective collaboration enables them to achieve big things in the world of modern software engineering.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Different Game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-different-game-f432a766.ChfXoZ1z_ZQPtfd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rleija_?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Ruben Leija&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;from-programmer-to-software-engineer&quot;&gt;From Programmer to Software Engineer&lt;/h2&gt;
&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we do not play football, but we develop research software. We also teach &lt;a href=&quot;https://www.esciencecenter.nl/training-materials/&quot;&gt;courses and workshops&lt;/a&gt;, including &lt;em&gt;Collaborative Software Development&lt;/em&gt;. Compared to workshops about Deep Learning or GPU Programming, tools like &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt;, &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; or &lt;a href=&quot;https://gitlab.com/&quot;&gt;GitLab&lt;/a&gt; may not seem very advanced. Nevertheless, at the end of some workshops, some participants almost refuse to leave the room, enthusiastically finishing the collaborative setup for a project. Also, I vividly remember how a partner of ours spontaneously mentioned her most important learning while working with us: “I learned to cooperate with others!”&lt;/p&gt;
&lt;p&gt;The impact that the relatively little technical learnings have on the personal progress seems almost unreasonably large. That is because we do not just teach how to use the Git ecosystem, but how to collaborate. Mastering the tools gives a glimpse at another level of software development that may have seemed unreachable for many programmers — like a lonely football player that has practised his or her skills on the ball and suddenly finds themselves in a well-organized team of players.&lt;/p&gt;
&lt;p&gt;It is not a coincidence that Git was invented by the initiator of the most prominent open-source software. With his initial versions of Linux, Linus Torvalds made a great start. However, without good tooling, collaboration causes friction. To use &lt;a href=&quot;https://ideas.ted.com/the-wisdom-of-linus-torvalds/&quot;&gt;Linus’ own words&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;We were in this bad spot where we had thousands of people who wanted to participate, but in many ways I was the break point.&lt;/p&gt;
&lt;p&gt;On his own, Linus could never have developed an operating system that now runs on millions of computers, including high-performance clusters, desktop PCs, laptops, phones, embedded systems and more. Seamless collaboration is the key:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The big point for me was not being alone and having ten, maybe 100 people being involved. […] Going from 100 people to a million people is not a big deal.&lt;/p&gt;
&lt;p&gt;The open-source software community turned Linux into high quality software in which bugs are fixed at a speed that software companies could only dream of, and new features come in by the day.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Different Game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;526&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-different-game-9cf5e1f7.CBj888-K_Z2cJmk6.webp&quot; srcset=&quot;&quot;&gt;
A graph showing contributions to a Git repository.Epiphany moments emerge when individual software engineers realize — for instance during a workshop — that they can reach that new level of software engineering. In a collaborative setting, tools and methods like version control, automated testing, &lt;a href=&quot;https://en.wikipedia.org/wiki/Lint_%28software%29&quot;&gt;linting&lt;/a&gt;, and &lt;a href=&quot;https://www.redhat.com/en/topics/devops/what-is-ci-cd&quot;&gt;continuous integration&lt;/a&gt; are no longer merely aesthetic practices. Not surprisingly: the rules of the game make sense once you play it.&lt;/p&gt;
&lt;h2 id=&quot;incentives&quot;&gt;Incentives?&lt;/h2&gt;
&lt;p&gt;Software engineers working in the industry often pride themselves on their practical engineering skills. Partly understandably, because even Computer Science PhDs, hence highly skilled individuals, can seem like novices when they join a team and don’t know how to collaborate with them. This is, however, a comparison between players of different games: individual programming and collaborative software development, respectively.&lt;/p&gt;
&lt;p&gt;For a company, the ability to develop software collaboratively is essential to survive after the start-up stage. If they do not adopt methods to join their forces effectively, their software engineers drown in a swamp of ever-increasing maintenance efforts and dependencies on individualized knowledge.&lt;/p&gt;
&lt;h2 id=&quot;reality-check&quot;&gt;Reality Check&lt;/h2&gt;
&lt;p&gt;So why is collaborative software development not the default method? One reason is that collaborative methods imply some overhead: developers need to invest time in learning to apply the tools — which only pays off in a team that thinks beyond short-term goals.&lt;/p&gt;
&lt;p&gt;But collaborative development is more than tooling: it also requires open communication and mutual trust, which often comes into conflict with hierarchies and individualized reward systems. Each member of a team needs to find intrinsic motivation and confidence that they can contribute something meaningful.&lt;/p&gt;
&lt;p&gt;Collaborative development principles often compete with existing incentives. In academia, software may be necessary to run an experiment, but is frequently abandoned as soon as the corresponding paper is published. Terms like “project-ware”, “PhD-ware” and “professor-ware” are typically not used in a positive way, but the one-off approach concurs with the fact that individual performance is measured by the number of publications.&lt;/p&gt;
&lt;p&gt;Developing software so that other researchers can extend it for their own experiments brings no benefit — in a highly competitive environment, the opposite might even be the case. In the football analogy: a striker that is measured by how well they can shoot penalties does not benefit from practicing combination play with the team.&lt;/p&gt;
&lt;p&gt;The same applies in industry settings, even though playing the team game is more fundamental. Anyway, developers are hired, promoted and fired based on their individual performances. An engineer who quickly drops a new feature into production is more likely to be perceived as a mythical 10x engineer* than their peer who makes sure it still works after the next update, for instance by implementing integration tests.&lt;/p&gt;
&lt;h2 id=&quot;agile-waterfall-and-hierarchies&quot;&gt;Agile, Waterfall and Hierarchies&lt;/h2&gt;
&lt;p&gt;How to tackle the complexities of software development has been a hot topic for decades. The &lt;em&gt;Waterfall&lt;/em&gt; approach tries to plan a project as a sequence of clearly defined steps that eventually lead to the finish line. In the reality of software engineering, however, that finish line tends to be moving, while the intermediate steps face unforeseen obstacles and complexities that cannot be fully grasped by an individual engineer.&lt;/p&gt;
&lt;p&gt;To account for the inherent dynamics of software development, &lt;em&gt;Agile&lt;/em&gt; methods have proposed that planning has to be refined iteratively, involving continuous interaction between all stakeholders — requiring effective collaboration on various levels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Different Game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-different-game-351e29e4.BEoFyw-g_ZBzg6q.webp&quot; srcset=&quot;&quot;&gt;
Collaboration is more than learning how to use Git. *Photo by Lisamarie Babik — Ted &amp;#x26; Ian. Uploaded by Edward, CC BY 2.0, *&lt;a href=&quot;https://commons.wikimedia.org/w/index.php?curid=9546406&quot;&gt;&lt;em&gt;https://commons.wikimedia.org/w/index.php?curid=9546406&lt;/em&gt;&lt;/a&gt;However, the reality of organizational hierarchies, project-based budgeting and purely individual accountability conflicts with the radical changes that are required to have teams that can refine their (intermediate) goals autonomously. In practice, &lt;em&gt;Agile&lt;/em&gt; therefore often means not much more than introducing a level of fancy terminology and rituals.&lt;/p&gt;
&lt;h2 id=&quot;to-the-next-level&quot;&gt;To the Next Level&lt;/h2&gt;
&lt;p&gt;In any organization, collaboration remains a trade-off between immediate personal advancement on the one hand, and contributing to sustainable, collective progress on the other hand. The feedback that we get at &lt;em&gt;Collaborative Software Development&lt;/em&gt; workshops shows that many people like the team game: it allows them to shine as part of a team that is able to build things far bigger than what any member could achieve on their own.&lt;/p&gt;
&lt;p&gt;The topic of collaborative software development might be so fascinating because it touches upon many issues beyond engineering. Like forming an effective football team, software engineering is a social process that requires technical skills, but can also lead to questions about the structure of an entire organization.&lt;/p&gt;</description><pubDate>Tue, 28 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;&lt;em&gt;According to a panel of football experts, the world’s best male player of the year 2024 was Rodri. The choice is naturally debatable, but even if you put him together with other stars like Erling Haaland and Kylian Mbappé, they will not stand a chance in a match against a full team of 11 amateurs. The world stars could perform great dribblings and accurate passes, but they cannot play the team sport called football.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To build complex software, highly skilled programmers are essential. But only effective collaboration enables them to achieve big things in the world of modern software engineering.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Different Game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-different-game-f432a766.ChfXoZ1z_ZQPtfd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rleija_?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Ruben Leija&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;from-programmer-to-software-engineer&quot;&gt;From Programmer to Software Engineer&lt;/h2&gt;
&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we do not play football, but we develop research software. We also teach &lt;a href=&quot;https://www.esciencecenter.nl/training-materials/&quot;&gt;courses and workshops&lt;/a&gt;, including &lt;em&gt;Collaborative Software Development&lt;/em&gt;. Compared to workshops about Deep Learning or GPU Programming, tools like &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt;, &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; or &lt;a href=&quot;https://gitlab.com/&quot;&gt;GitLab&lt;/a&gt; may not seem very advanced. Nevertheless, at the end of some workshops, some participants almost refuse to leave the room, enthusiastically finishing the collaborative setup for a project. Also, I vividly remember how a partner of ours spontaneously mentioned her most important learning while working with us: “I learned to cooperate with others!”&lt;/p&gt;
&lt;p&gt;The impact that the relatively little technical learnings have on the personal progress seems almost unreasonably large. That is because we do not just teach how to use the Git ecosystem, but how to collaborate. Mastering the tools gives a glimpse at another level of software development that may have seemed unreachable for many programmers — like a lonely football player that has practised his or her skills on the ball and suddenly finds themselves in a well-organized team of players.&lt;/p&gt;
&lt;p&gt;It is not a coincidence that Git was invented by the initiator of the most prominent open-source software. With his initial versions of Linux, Linus Torvalds made a great start. However, without good tooling, collaboration causes friction. To use &lt;a href=&quot;https://ideas.ted.com/the-wisdom-of-linus-torvalds/&quot;&gt;Linus’ own words&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;We were in this bad spot where we had thousands of people who wanted to participate, but in many ways I was the break point.&lt;/p&gt;
&lt;p&gt;On his own, Linus could never have developed an operating system that now runs on millions of computers, including high-performance clusters, desktop PCs, laptops, phones, embedded systems and more. Seamless collaboration is the key:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The big point for me was not being alone and having ten, maybe 100 people being involved. […] Going from 100 people to a million people is not a big deal.&lt;/p&gt;
&lt;p&gt;The open-source software community turned Linux into high quality software in which bugs are fixed at a speed that software companies could only dream of, and new features come in by the day.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Different Game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;526&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-different-game-9cf5e1f7.CBj888-K_Z2cJmk6.webp&quot; srcset=&quot;&quot;&gt;
A graph showing contributions to a Git repository.Epiphany moments emerge when individual software engineers realize — for instance during a workshop — that they can reach that new level of software engineering. In a collaborative setting, tools and methods like version control, automated testing, &lt;a href=&quot;https://en.wikipedia.org/wiki/Lint_%28software%29&quot;&gt;linting&lt;/a&gt;, and &lt;a href=&quot;https://www.redhat.com/en/topics/devops/what-is-ci-cd&quot;&gt;continuous integration&lt;/a&gt; are no longer merely aesthetic practices. Not surprisingly: the rules of the game make sense once you play it.&lt;/p&gt;
&lt;h2 id=&quot;incentives&quot;&gt;Incentives?&lt;/h2&gt;
&lt;p&gt;Software engineers working in the industry often pride themselves on their practical engineering skills. Partly understandably, because even Computer Science PhDs, hence highly skilled individuals, can seem like novices when they join a team and don’t know how to collaborate with them. This is, however, a comparison between players of different games: individual programming and collaborative software development, respectively.&lt;/p&gt;
&lt;p&gt;For a company, the ability to develop software collaboratively is essential to survive after the start-up stage. If they do not adopt methods to join their forces effectively, their software engineers drown in a swamp of ever-increasing maintenance efforts and dependencies on individualized knowledge.&lt;/p&gt;
&lt;h2 id=&quot;reality-check&quot;&gt;Reality Check&lt;/h2&gt;
&lt;p&gt;So why is collaborative software development not the default method? One reason is that collaborative methods imply some overhead: developers need to invest time in learning to apply the tools — which only pays off in a team that thinks beyond short-term goals.&lt;/p&gt;
&lt;p&gt;But collaborative development is more than tooling: it also requires open communication and mutual trust, which often comes into conflict with hierarchies and individualized reward systems. Each member of a team needs to find intrinsic motivation and confidence that they can contribute something meaningful.&lt;/p&gt;
&lt;p&gt;Collaborative development principles often compete with existing incentives. In academia, software may be necessary to run an experiment, but is frequently abandoned as soon as the corresponding paper is published. Terms like “project-ware”, “PhD-ware” and “professor-ware” are typically not used in a positive way, but the one-off approach concurs with the fact that individual performance is measured by the number of publications.&lt;/p&gt;
&lt;p&gt;Developing software so that other researchers can extend it for their own experiments brings no benefit — in a highly competitive environment, the opposite might even be the case. In the football analogy: a striker that is measured by how well they can shoot penalties does not benefit from practicing combination play with the team.&lt;/p&gt;
&lt;p&gt;The same applies in industry settings, even though playing the team game is more fundamental. Anyway, developers are hired, promoted and fired based on their individual performances. An engineer who quickly drops a new feature into production is more likely to be perceived as a mythical 10x engineer* than their peer who makes sure it still works after the next update, for instance by implementing integration tests.&lt;/p&gt;
&lt;h2 id=&quot;agile-waterfall-and-hierarchies&quot;&gt;Agile, Waterfall and Hierarchies&lt;/h2&gt;
&lt;p&gt;How to tackle the complexities of software development has been a hot topic for decades. The &lt;em&gt;Waterfall&lt;/em&gt; approach tries to plan a project as a sequence of clearly defined steps that eventually lead to the finish line. In the reality of software engineering, however, that finish line tends to be moving, while the intermediate steps face unforeseen obstacles and complexities that cannot be fully grasped by an individual engineer.&lt;/p&gt;
&lt;p&gt;To account for the inherent dynamics of software development, &lt;em&gt;Agile&lt;/em&gt; methods have proposed that planning has to be refined iteratively, involving continuous interaction between all stakeholders — requiring effective collaboration on various levels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Different Game&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-different-game-351e29e4.BEoFyw-g_ZBzg6q.webp&quot; srcset=&quot;&quot;&gt;
Collaboration is more than learning how to use Git. *Photo by Lisamarie Babik — Ted &amp;#x26; Ian. Uploaded by Edward, CC BY 2.0, *&lt;a href=&quot;https://commons.wikimedia.org/w/index.php?curid=9546406&quot;&gt;&lt;em&gt;https://commons.wikimedia.org/w/index.php?curid=9546406&lt;/em&gt;&lt;/a&gt;However, the reality of organizational hierarchies, project-based budgeting and purely individual accountability conflicts with the radical changes that are required to have teams that can refine their (intermediate) goals autonomously. In practice, &lt;em&gt;Agile&lt;/em&gt; therefore often means not much more than introducing a level of fancy terminology and rituals.&lt;/p&gt;
&lt;h2 id=&quot;to-the-next-level&quot;&gt;To the Next Level&lt;/h2&gt;
&lt;p&gt;In any organization, collaboration remains a trade-off between immediate personal advancement on the one hand, and contributing to sustainable, collective progress on the other hand. The feedback that we get at &lt;em&gt;Collaborative Software Development&lt;/em&gt; workshops shows that many people like the team game: it allows them to shine as part of a team that is able to build things far bigger than what any member could achieve on their own.&lt;/p&gt;
&lt;p&gt;The topic of collaborative software development might be so fascinating because it touches upon many issues beyond engineering. Like forming an effective football team, software engineering is a social process that requires technical skills, but can also lead to questions about the structure of an entire organization.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/a-different-game-f432a766.ChfXoZ1z.jpg" medium="image"/><author>Carsten Schnober</author></item><item><title>How to run a containerized Agent-Based Model on HPC</title><link>https://blog2.esciencecenter.nl/posts/2025-01-23---how-to-run-a-containerized-agent-based-model-on-hpc</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-01-23---how-to-run-a-containerized-agent-based-model-on-hpc</guid><description>&lt;p&gt;&lt;em&gt;This blog was written by &lt;em&gt;&lt;a href=&quot;https://medium.com/@fdiblen&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/olga-lyashevska/&quot;&gt;&lt;em&gt;Olga Lyashevska&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Imagine you are preparing &lt;a href=&quot;https://en.wikipedia.org/wiki/Torta_caprese&quot;&gt;Torta Caprese&lt;/a&gt; for your friend’s birthday. You have a recipe that consistently delights everyone, but you want to ensure it turns out perfectly every time, regardless of the oven you are baking in or ambient temperature. To achieve this, you always use a cake tin for the batter, which gives its form. In the realm of software development, a similar concept exists — the container. Much like its culinary counterpart, a software container offers a lightweight, consistent and isolated environment for your application, just like the cake tin. The beauty of using a software container is that all the necessary ingredients and instructions are neatly packaged together, including code, dependencies, and runtime environment. This ensures that the application runs consistently and reliably across different computing environments and operating systems.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to run a containerized Agent-Based Model on HPC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-642d9679.Bm-OR_PN_ZAnYGI.webp&quot; srcset=&quot;&quot;&gt;
Illustration: generated with &lt;a href=&quot;http://www.midjourney.com&quot;&gt;Midjourney&lt;/a&gt;Introduction**&lt;/p&gt;
&lt;p&gt;In this blog, we provide a step-by-step guide on running a containerized &lt;a href=&quot;https://en.wikipedia.org/wiki/Agent-based_model&quot;&gt;Agent Based Model&lt;/a&gt; (ABM) on High-Performance Computing (HPC) systems. We will explain how to package code and all dependencies in a container and execute on HPC in an easy way. As an example of ABM, we picked &lt;a href=&quot;https://ccl.northwestern.edu/netlogo/&quot;&gt;NetLogo&lt;/a&gt;, a widely popular software among users who may not be technically inclined.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;NetLogo is a multi-agent programmable modeling environment. It is used by tens of thousands of students, teachers and researchers worldwide.&lt;/p&gt;
&lt;p&gt;The steps outlined below are not limited to NetLogo or ABMs; you can follow this guide to run any application in a containerized format on HPC systems. So why might we want to run NetLogo on HPC? Let’s go back to our baker analogy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HPC and its significance in handling complex computational tasks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let’s imagine that your Torta Caprese has gained immense popularity, and now you are asked to bake it for a friend’s wedding. However, this time, you are not using your humble home oven (desktop computer); instead, you have access to a state-of-the-art industrial oven capable of efficiency and speed. This industrial oven represents HPC systems. HPC systems are known for their ability to process large volumes of data and complex computations at high speed. Do you want to risk any variation in the baking process? No. You are equally meticulous about the execution of your application on the HPC infrastructure. This is where the concept of containerization comes into the picture. By utilizing containers on HPC systems, you ensure that your application runs efficiently and consistently, regardless of the computing environment it is deployed.&lt;/p&gt;
&lt;p&gt;Back to NetLogo. Imagine you have a NetLogo model that has grown too complex and too slow to be run efficiently on your desktop and you decide to run it on HPC system. You have access to the HPC system via secure shell (SSH), but you do not have the necessary permissions to install NetLogo on the system or you do not know how to do it. Perhaps, you may even want to run the model without GUI (Graphical User Interface) because it avoids overhead and makes your model run faster.&lt;/p&gt;
&lt;p&gt;The purpose of this blog is to demonstrate how to run a single Netlogo model on HPC using &lt;a href=&quot;https://apptainer.org/&quot;&gt;Apptainer&lt;/a&gt; container. We use the &lt;a href=&quot;https://ccl.northwestern.edu/netlogo/6.3.0/NetLogo-6.3.0-64.tgz&quot;&gt;Netlogo&lt;/a&gt; distribution as a base for the container. Apptainer allows us to package the model and its dependencies (i.e. Netlogo) in a single image that can be run uniformly across different systems. Apptainer is particularly suitable for HPC, as it is designed to bring containers and reproducibility to the scientific community and does not require admin access to run. The container is then used to run the Netlogo model in headless mode. Headless mode is a mode in which the model is run without the GUI and the output is saved in a csv file.&lt;/p&gt;
&lt;p&gt;Let’s follow the next steps together. But first, you need to make sure that you have the following installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://apptainer.org/&quot;&gt;Apptainer&lt;/a&gt; 1.2.5 or newer&lt;/li&gt;
&lt;li&gt;a Linux OS with sudo rights, any system will do&lt;/li&gt;
&lt;li&gt;shell, any shell will do&lt;/li&gt;
&lt;li&gt;access to an HPC system via SSH&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we are going to follow these steps to run your model within a container on HPC:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 1. Create a definition file&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;First, we create a &lt;code&gt;netlogo-headless.def&lt;/code&gt; file with the following content:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 2. Build a container&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We are going to build an apptainer container on your local machine from a definition file that we have just created in Step 1. For this, a Linux system with sudo rights is needed.&lt;/p&gt;
&lt;p&gt;This command will create an apptainer image &lt;code&gt;netlogo-headless.sif&lt;/code&gt; which we will use to run the model in headless mode on HPC.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 3. Prepare &lt;code&gt;job.sh&lt;/code&gt; file&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We need to create a shell script that contains the command to run the model in headless mode. First, we look at how to run the model in headless mode without a container.&lt;/p&gt;
&lt;p&gt;./netlogo-headless.sh — model “PATH_TO_MODEL” — experiment “EXPERIMENT_NAME” — table OUTPUT.CSVThe line of code above will execute a &lt;code&gt;netlogo-headless.sh&lt;/code&gt; command, where&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt; — model&lt;/code&gt; is an argument that specifies the NetLogo model to be run;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt; — experiment&lt;/code&gt; argument is optional and can be used to specify the name of the experiment;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt; — table&lt;/code&gt; argument is optional and can be used to specify the name of the output file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;apptainer exec netlogo-headless.sif netlogo-headless.sh — model “PATH_TO_MODEL” — experiment “EXPERIMENT_NAME” — table OUTPUT.CSVFor example, to run a model &lt;code&gt;Wolf Sheep Simple 5.nlogo&lt;/code&gt; with an experiment &lt;code&gt;Wolf Sheep Simple model analysis&lt;/code&gt; and save the output in &lt;code&gt;wolf_sheep_output.csv&lt;/code&gt;, use the following command.&lt;/p&gt;
&lt;p&gt;We save the code above as &lt;code&gt;job.sh&lt;/code&gt; and change permissions to make it executable with&lt;/p&gt;
&lt;p&gt;chmod +x job.shStep 3. Create an archive to be copied to HPC*&lt;/p&gt;
&lt;p&gt;To run our model on HPC, we need to copy all files to the remote machine. First, we create an archive on a local machine that contains the model, the container, and the shell script. For this, we create a directory and copy &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;netlogo-headless.sif&lt;/code&gt;, and &lt;code&gt;job.sh&lt;/code&gt; into it and call this directory &lt;code&gt;jobHPC&lt;/code&gt;. Then we create a gzip tarball of a directory.&lt;/p&gt;
&lt;p&gt;tar -czvf jobHPC.tar.gz jobHPC&lt;em&gt;Step 4. Copy to HPC&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To copy &lt;code&gt;jobHPC.tar.gz&lt;/code&gt; file from your local machine to HPC cluster, we can use the &lt;code&gt;scp&lt;/code&gt; command. This command will copy &lt;code&gt;jobHPC.tar.gz&lt;/code&gt; file to the remote machine using SSH (Secure Shell) protocol for data transfer.&lt;/p&gt;
&lt;p&gt;scp jobHPC.tar.gz username@remote:/path/to/remote/directoryReplace &lt;code&gt;username@remote&lt;/code&gt; with your username and the address of the HPC cluster. Replace &lt;code&gt;/path/to/remote/directory&lt;/code&gt; with the path to the directory on the HPC cluster where you want to copy the file. This command will prompt you for your password on the HPC cluster before copying the file.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 5. Unpack the archive on HPC&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once the file is copied to the HPC cluster, log into the remote machine and unpack the archive using the following command:&lt;/p&gt;
&lt;p&gt;tar -xzvf jobHPC.tar.gz&lt;em&gt;Step 6. Run model on HPC&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Submit a job to a (&lt;a href=&quot;https://slurm.schedmd.com/&quot;&gt;SLURM&lt;/a&gt;) scheduler on HPC using the following command:&lt;/p&gt;
&lt;p&gt;Here, we set a limit of 2 hours for the job to run. You can change the time limit as per your requirements.&lt;/p&gt;
&lt;p&gt;Now you can pull up information about the jobs in the queue:&lt;/p&gt;
&lt;p&gt;squeue —user=your-usernameWe use here the &lt;code&gt;--user&lt;/code&gt;flag because we only want to see our job.&lt;/p&gt;
&lt;p&gt;You can stop your job with&lt;/p&gt;
&lt;p&gt;scancel your_job-id&lt;em&gt;Step 7. Retrieve results&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once finished you can retrieve your results. For this, you need to identify the files you need to retrieve. To copy the files to your local machine run:&lt;/p&gt;
&lt;p&gt;scp username@remote:/path/to/remote/file /path/to/local/destinationReplace &lt;code&gt;/path/to/remote/file&lt;/code&gt; with the path to the file on the HPC system, and &lt;code&gt;/path/to/local/destination&lt;/code&gt; with the path where you want to save the file on your local machine.&lt;/p&gt;
&lt;p&gt;For example, to copy &lt;code&gt;job_output.txt&lt;/code&gt; from the HPC system to your desktop:&lt;/p&gt;
&lt;p&gt;scp &lt;a href=&quot;mailto:user@hpc.example.com&quot;&gt;user@hpc.example.com&lt;/a&gt;:/home/user/job_output.txt ~/Desktop/Finally, if you want to copy multiple files, you need to add flag &lt;code&gt;--r&lt;/code&gt; which will allow you to copy all files in the directory &lt;code&gt;job_output&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;scp -r &lt;a href=&quot;mailto:user@hpc.example.com&quot;&gt;user@hpc.example.com&lt;/a&gt;:/home/user/job_output/ ~/Desktop/
&lt;img alt=&quot;How to run a containerized Agent-Based Model on HPC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-0680d40a.DNh6sdSk_Z1aV0V3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@lightsabercollection?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Lightsaber Collection&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Conclusion**&lt;/p&gt;
&lt;p&gt;To wrap up our containerization journey, we have covered some solid ground in getting your NetLogo models up and running on HPC systems. Containerization, much like the cake tin, provides a reliable and consistent environment for your applications, ensuring they perform as expected regardless of the computing setup. From creating our container image using Apptainer to running the job scripts to transfer files to the HPC cluster and running job, we have laid out all the steps. Whether you are diving into ABM or tackling real-world problems, containerization on HPC enables you to handle complex computational tasks.&lt;/p&gt;
&lt;p&gt;Now, go ahead and make a Torta Caprese for yourself to celebrate that you learned something new! Here is a &lt;a href=&quot;https://food52.com/recipes/64554-torta-caprese-chocolate-and-almond-flourless-cake&quot;&gt;recipe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to run a containerized Agent-Based Model on HPC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-cd889241.C4i4tuNu_Z2dxwrf.webp&quot; srcset=&quot;&quot;&gt;
Image: &lt;a href=&quot;https://unsplash.com/&quot;&gt;https://unsplash.com&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 23 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This blog was written by &lt;em&gt;&lt;a href=&quot;https://medium.com/@fdiblen&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/olga-lyashevska/&quot;&gt;&lt;em&gt;Olga Lyashevska&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Imagine you are preparing &lt;a href=&quot;https://en.wikipedia.org/wiki/Torta_caprese&quot;&gt;Torta Caprese&lt;/a&gt; for your friend’s birthday. You have a recipe that consistently delights everyone, but you want to ensure it turns out perfectly every time, regardless of the oven you are baking in or ambient temperature. To achieve this, you always use a cake tin for the batter, which gives its form. In the realm of software development, a similar concept exists — the container. Much like its culinary counterpart, a software container offers a lightweight, consistent and isolated environment for your application, just like the cake tin. The beauty of using a software container is that all the necessary ingredients and instructions are neatly packaged together, including code, dependencies, and runtime environment. This ensures that the application runs consistently and reliably across different computing environments and operating systems.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to run a containerized Agent-Based Model on HPC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-642d9679.Bm-OR_PN_ZAnYGI.webp&quot; srcset=&quot;&quot;&gt;
Illustration: generated with &lt;a href=&quot;http://www.midjourney.com&quot;&gt;Midjourney&lt;/a&gt;Introduction**&lt;/p&gt;
&lt;p&gt;In this blog, we provide a step-by-step guide on running a containerized &lt;a href=&quot;https://en.wikipedia.org/wiki/Agent-based_model&quot;&gt;Agent Based Model&lt;/a&gt; (ABM) on High-Performance Computing (HPC) systems. We will explain how to package code and all dependencies in a container and execute on HPC in an easy way. As an example of ABM, we picked &lt;a href=&quot;https://ccl.northwestern.edu/netlogo/&quot;&gt;NetLogo&lt;/a&gt;, a widely popular software among users who may not be technically inclined.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;NetLogo is a multi-agent programmable modeling environment. It is used by tens of thousands of students, teachers and researchers worldwide.&lt;/p&gt;
&lt;p&gt;The steps outlined below are not limited to NetLogo or ABMs; you can follow this guide to run any application in a containerized format on HPC systems. So why might we want to run NetLogo on HPC? Let’s go back to our baker analogy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HPC and its significance in handling complex computational tasks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let’s imagine that your Torta Caprese has gained immense popularity, and now you are asked to bake it for a friend’s wedding. However, this time, you are not using your humble home oven (desktop computer); instead, you have access to a state-of-the-art industrial oven capable of efficiency and speed. This industrial oven represents HPC systems. HPC systems are known for their ability to process large volumes of data and complex computations at high speed. Do you want to risk any variation in the baking process? No. You are equally meticulous about the execution of your application on the HPC infrastructure. This is where the concept of containerization comes into the picture. By utilizing containers on HPC systems, you ensure that your application runs efficiently and consistently, regardless of the computing environment it is deployed.&lt;/p&gt;
&lt;p&gt;Back to NetLogo. Imagine you have a NetLogo model that has grown too complex and too slow to be run efficiently on your desktop and you decide to run it on HPC system. You have access to the HPC system via secure shell (SSH), but you do not have the necessary permissions to install NetLogo on the system or you do not know how to do it. Perhaps, you may even want to run the model without GUI (Graphical User Interface) because it avoids overhead and makes your model run faster.&lt;/p&gt;
&lt;p&gt;The purpose of this blog is to demonstrate how to run a single Netlogo model on HPC using &lt;a href=&quot;https://apptainer.org/&quot;&gt;Apptainer&lt;/a&gt; container. We use the &lt;a href=&quot;https://ccl.northwestern.edu/netlogo/6.3.0/NetLogo-6.3.0-64.tgz&quot;&gt;Netlogo&lt;/a&gt; distribution as a base for the container. Apptainer allows us to package the model and its dependencies (i.e. Netlogo) in a single image that can be run uniformly across different systems. Apptainer is particularly suitable for HPC, as it is designed to bring containers and reproducibility to the scientific community and does not require admin access to run. The container is then used to run the Netlogo model in headless mode. Headless mode is a mode in which the model is run without the GUI and the output is saved in a csv file.&lt;/p&gt;
&lt;p&gt;Let’s follow the next steps together. But first, you need to make sure that you have the following installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://apptainer.org/&quot;&gt;Apptainer&lt;/a&gt; 1.2.5 or newer&lt;/li&gt;
&lt;li&gt;a Linux OS with sudo rights, any system will do&lt;/li&gt;
&lt;li&gt;shell, any shell will do&lt;/li&gt;
&lt;li&gt;access to an HPC system via SSH&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we are going to follow these steps to run your model within a container on HPC:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 1. Create a definition file&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;First, we create a &lt;code&gt;netlogo-headless.def&lt;/code&gt; file with the following content:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 2. Build a container&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We are going to build an apptainer container on your local machine from a definition file that we have just created in Step 1. For this, a Linux system with sudo rights is needed.&lt;/p&gt;
&lt;p&gt;This command will create an apptainer image &lt;code&gt;netlogo-headless.sif&lt;/code&gt; which we will use to run the model in headless mode on HPC.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 3. Prepare &lt;code&gt;job.sh&lt;/code&gt; file&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We need to create a shell script that contains the command to run the model in headless mode. First, we look at how to run the model in headless mode without a container.&lt;/p&gt;
&lt;p&gt;./netlogo-headless.sh — model “PATH_TO_MODEL” — experiment “EXPERIMENT_NAME” — table OUTPUT.CSVThe line of code above will execute a &lt;code&gt;netlogo-headless.sh&lt;/code&gt; command, where&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt; — model&lt;/code&gt; is an argument that specifies the NetLogo model to be run;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt; — experiment&lt;/code&gt; argument is optional and can be used to specify the name of the experiment;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt; — table&lt;/code&gt; argument is optional and can be used to specify the name of the output file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;apptainer exec netlogo-headless.sif netlogo-headless.sh — model “PATH_TO_MODEL” — experiment “EXPERIMENT_NAME” — table OUTPUT.CSVFor example, to run a model &lt;code&gt;Wolf Sheep Simple 5.nlogo&lt;/code&gt; with an experiment &lt;code&gt;Wolf Sheep Simple model analysis&lt;/code&gt; and save the output in &lt;code&gt;wolf_sheep_output.csv&lt;/code&gt;, use the following command.&lt;/p&gt;
&lt;p&gt;We save the code above as &lt;code&gt;job.sh&lt;/code&gt; and change permissions to make it executable with&lt;/p&gt;
&lt;p&gt;chmod +x job.shStep 3. Create an archive to be copied to HPC*&lt;/p&gt;
&lt;p&gt;To run our model on HPC, we need to copy all files to the remote machine. First, we create an archive on a local machine that contains the model, the container, and the shell script. For this, we create a directory and copy &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;netlogo-headless.sif&lt;/code&gt;, and &lt;code&gt;job.sh&lt;/code&gt; into it and call this directory &lt;code&gt;jobHPC&lt;/code&gt;. Then we create a gzip tarball of a directory.&lt;/p&gt;
&lt;p&gt;tar -czvf jobHPC.tar.gz jobHPC&lt;em&gt;Step 4. Copy to HPC&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To copy &lt;code&gt;jobHPC.tar.gz&lt;/code&gt; file from your local machine to HPC cluster, we can use the &lt;code&gt;scp&lt;/code&gt; command. This command will copy &lt;code&gt;jobHPC.tar.gz&lt;/code&gt; file to the remote machine using SSH (Secure Shell) protocol for data transfer.&lt;/p&gt;
&lt;p&gt;scp jobHPC.tar.gz username@remote:/path/to/remote/directoryReplace &lt;code&gt;username@remote&lt;/code&gt; with your username and the address of the HPC cluster. Replace &lt;code&gt;/path/to/remote/directory&lt;/code&gt; with the path to the directory on the HPC cluster where you want to copy the file. This command will prompt you for your password on the HPC cluster before copying the file.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 5. Unpack the archive on HPC&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once the file is copied to the HPC cluster, log into the remote machine and unpack the archive using the following command:&lt;/p&gt;
&lt;p&gt;tar -xzvf jobHPC.tar.gz&lt;em&gt;Step 6. Run model on HPC&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Submit a job to a (&lt;a href=&quot;https://slurm.schedmd.com/&quot;&gt;SLURM&lt;/a&gt;) scheduler on HPC using the following command:&lt;/p&gt;
&lt;p&gt;Here, we set a limit of 2 hours for the job to run. You can change the time limit as per your requirements.&lt;/p&gt;
&lt;p&gt;Now you can pull up information about the jobs in the queue:&lt;/p&gt;
&lt;p&gt;squeue —user=your-usernameWe use here the &lt;code&gt;--user&lt;/code&gt;flag because we only want to see our job.&lt;/p&gt;
&lt;p&gt;You can stop your job with&lt;/p&gt;
&lt;p&gt;scancel your_job-id&lt;em&gt;Step 7. Retrieve results&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once finished you can retrieve your results. For this, you need to identify the files you need to retrieve. To copy the files to your local machine run:&lt;/p&gt;
&lt;p&gt;scp username@remote:/path/to/remote/file /path/to/local/destinationReplace &lt;code&gt;/path/to/remote/file&lt;/code&gt; with the path to the file on the HPC system, and &lt;code&gt;/path/to/local/destination&lt;/code&gt; with the path where you want to save the file on your local machine.&lt;/p&gt;
&lt;p&gt;For example, to copy &lt;code&gt;job_output.txt&lt;/code&gt; from the HPC system to your desktop:&lt;/p&gt;
&lt;p&gt;scp &lt;a href=&quot;mailto:user@hpc.example.com&quot;&gt;user@hpc.example.com&lt;/a&gt;:/home/user/job_output.txt ~/Desktop/Finally, if you want to copy multiple files, you need to add flag &lt;code&gt;--r&lt;/code&gt; which will allow you to copy all files in the directory &lt;code&gt;job_output&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;scp -r &lt;a href=&quot;mailto:user@hpc.example.com&quot;&gt;user@hpc.example.com&lt;/a&gt;:/home/user/job_output/ ~/Desktop/
&lt;img alt=&quot;How to run a containerized Agent-Based Model on HPC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-0680d40a.DNh6sdSk_Z1aV0V3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@lightsabercollection?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Lightsaber Collection&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Conclusion**&lt;/p&gt;
&lt;p&gt;To wrap up our containerization journey, we have covered some solid ground in getting your NetLogo models up and running on HPC systems. Containerization, much like the cake tin, provides a reliable and consistent environment for your applications, ensuring they perform as expected regardless of the computing setup. From creating our container image using Apptainer to running the job scripts to transfer files to the HPC cluster and running job, we have laid out all the steps. Whether you are diving into ABM or tackling real-world problems, containerization on HPC enables you to handle complex computational tasks.&lt;/p&gt;
&lt;p&gt;Now, go ahead and make a Torta Caprese for yourself to celebrate that you learned something new! Here is a &lt;a href=&quot;https://food52.com/recipes/64554-torta-caprese-chocolate-and-almond-flourless-cake&quot;&gt;recipe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to run a containerized Agent-Based Model on HPC&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-cd889241.C4i4tuNu_Z2dxwrf.webp&quot; srcset=&quot;&quot;&gt;
Image: &lt;a href=&quot;https://unsplash.com/&quot;&gt;https://unsplash.com&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-to-run-a-containerized-agent-based-m-642d9679.Bm-OR_PN.png" medium="image"/><author>Olga Lyashevska</author></item><item><title>My experience of getting codechecked</title><link>https://blog2.esciencecenter.nl/posts/2025-01-16---my-experience-of-getting-codechecked</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2025-01-16---my-experience-of-getting-codechecked</guid><description>&lt;p&gt;6&lt;/p&gt;
&lt;p&gt;*By eScience Fellow *&lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/eduard-klapwijk/&quot;&gt;&lt;em&gt;Eduard Klapwijk&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This year I was finalizing and publishing one of my own research projects. My coauthors and I took many steps to make the project as reproducible as possible.&lt;/p&gt;
&lt;p&gt;Because I am setting up a codecheck workflow to check the reproducibility of research results for researchers at my institute, I was eager to submit my own work to the test. How reproducible would our work be when submitted to an external test?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;My experience of getting codechecked&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/my-experience-of-getting-codechecked-fd5cf777.CFP8GMsa_WjAUO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@hjkp?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;henry perks&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-check-for-reproducibility&quot;&gt;A check for reproducibility&lt;/h2&gt;
&lt;p&gt;I submitted my work to the &lt;a href=&quot;https://codecheck.org.uk/&quot;&gt;CODECHECK&lt;/a&gt; (&lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-n%C3%BCst2021&quot;&gt;Nüst and Eglen 2021&lt;/a&gt;) community workflow, which means that an external codechecker will do a light-weight reproducibility check. They will try to re-run my code to see if results reported in the paper can be reproduced.&lt;/p&gt;
&lt;p&gt;A codecheck was the perfect opportunity for checking how reproducible our project was. At the same time, the experience of getting my own work codechecked would help in understanding a researcher’s perspective on the process. In this post, I will share my personal experience of getting codechecked. This will hopefully demystify the process for any reader new to codechecking or curious about what codecheck is all about.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;My experience of getting codechecked&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;360&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/my-experience-of-getting-codechecked-c91a8ead.C3rwIrhs_Z1k7CIi.webp&quot; srcset=&quot;&quot;&gt;
Image: The &lt;a href=&quot;https://codecheck.org.uk/process/#figure-2-the-codecheck-example-process-implementation&quot;&gt;CODECHECK&lt;/a&gt; example workflow implementation.&lt;/p&gt;
&lt;h2 id=&quot;the-project-neuroup&quot;&gt;The project: neuroUp&lt;/h2&gt;
&lt;p&gt;The project submitted for the codecheck was in the making for about four years — a nice example of &lt;a href=&quot;https://linkinghub.elsevier.com/retrieve/pii/S1364661319302426&quot;&gt;Slow Science&lt;/a&gt; as per Uta Frith’s analogy. From the start of these four years, I tried to make all our scripts reproducible.&lt;/p&gt;
&lt;p&gt;A few years ago, we started out with a couple of unconnected R scripts. Only when I started drafting the research article, I combined the draft manuscript with the project’s code and computations in one place. I first used &lt;a href=&quot;https://rmarkdown.rstudio.com/&quot;&gt;R Markdown&lt;/a&gt; for this, and in the end of 2023 I switched to a similar tool now available in RStudio called &lt;a href=&quot;https://quarto.org/&quot;&gt;Quarto&lt;/a&gt;. On top of this, a key tool for reproducibility was the use of &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; and &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; for version control. This helped to systematically track the evolution of the project and its code and allowed us to go back to a previous state of the code if needed.&lt;/p&gt;
&lt;p&gt;An important phase in the project was the step from working with loosely connected R scripts to the development of an R package (we called it &lt;a href=&quot;https://eduardklap.github.io/neuroUp/&quot;&gt;neuroUp&lt;/a&gt;). With the help of the fantastic &lt;a href=&quot;https://r-pkgs.org/&quot;&gt;R packages&lt;/a&gt; book by Hadley Wickham and Jennifer Bryan, I managed to develop my first R package out of the code for this paper. Although after having done this, I believe that for most research projects developing a custom software package is an overkill, organizing code in a package does provide a lot of benefits that make your code much more reproducible. It organizes your project according to a convention, specifies dependencies, and bundles data, code, and documentation (&lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-marwick2018&quot;&gt;Marwick, Boettiger, and Mullen 2018&lt;/a&gt;). This means other researchers can install, cite and use the package without having to understand exactly how your code works.&lt;/p&gt;
&lt;p&gt;When we posted &lt;a href=&quot;https://doi.org/10.31234/osf.io/cz32t&quot;&gt;the preprint for our paper&lt;/a&gt;, we also published a &lt;a href=&quot;https://eduardklap.github.io/sample-size-fmri/&quot;&gt;reproducible version of the manuscript&lt;/a&gt; online. That was the moment that we turned to the CODECHECK community workflow to check whether results were indeed reproducible, at least according to one independent codechecker who was not part of the research team.&lt;/p&gt;
&lt;h2 id=&quot;submitting-work-to-be-codechecked&quot;&gt;Submitting work to be codechecked&lt;/h2&gt;
&lt;p&gt;I chose CODECHECK because they offer a journal-independent community workflow. To be honest, submitting the work was daunting at first. I hesitated because based on the &lt;a href=&quot;https://codecheck.org.uk/guide/community-workflow-author#2-requirements&quot;&gt;instructions for authors&lt;/a&gt;, I thought I had to partly restructure my project and provide a new README and metadata file. Luckily, looking at some of the forked repositories in the &lt;a href=&quot;https://github.com/orgs/codecheckers/repositories&quot;&gt;codecheckers GitHub organization&lt;/a&gt; really helped. That made me realize that some were much more detailed than others and that I could suffice with just describing the files in the repository and instructions on how to run the code (I liked &lt;a href=&quot;https://github.com/codecheckers/mb11CalculusPilot&quot;&gt;this example&lt;/a&gt; by Bjørn Bartholdy and based my README on it).&lt;/p&gt;
&lt;p&gt;After the preparations, the procedure was straightforward. Using my GitHub account, I opened an issue on the codecheckers GitHub, which is made easy using their &lt;a href=&quot;https://github.com/codecheckers/register/issues/new/choose&quot;&gt;template issue&lt;/a&gt;. The only thing that confused me a little was the instruction to “link to the repository in the codecheckers organisation with the code”. Once I figured that I could also link to my own public repository that would be forked by the codechecker in the process, my project was ready to go!&lt;/p&gt;
&lt;h2 id=&quot;getting-the-results-of-the-check&quot;&gt;Getting the results of the check&lt;/h2&gt;
&lt;p&gt;After a short waiting time, I got notified with some good news: the checker was able to reproduce my work and we got a certificate (see &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-r%C3%B6seler2024&quot;&gt;Röseler 2024&lt;/a&gt;)! Of course, I was very happy. This meant that at least one other person at another moment in time was able to reproduce our work with the help of our data and code.&lt;/p&gt;
&lt;p&gt;But, as I also experienced when I later code-checked someone else’s work (&lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-joeytang2024&quot;&gt;Joey Tang et al. 2024&lt;/a&gt;), when everything is working smoothly (eventually maybe after debugging some dependencies), the whole process is not overly exciting. The machine is doing most of the work in that case, you just see a bunch of identical images or tables appearing on your screen.&lt;/p&gt;
&lt;p&gt;The kind of reproducibility that is checked (computational or methods reproducibility) is in the end actually quite basic. What is being checked is nothing more than a minimum but necessary condition of good and believable research: what is verified is whether the results can be independently re-run using the same data and code. Other relating concepts for reliable and trustworthy research results such as replicability, generalizibility, and robustness, may be more exciting, but require also much more effort or even new studies to check.&lt;/p&gt;
&lt;h2 id=&quot;final-reflections&quot;&gt;Final reflections&lt;/h2&gt;
&lt;p&gt;As with most things in life, preparing for the codecheck (by making sure your work is reproducible) is most of the work. Here are some key points to consider (see also these ten simple rules for reproducible research: &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-sandve2013&quot;&gt;Sandve et al. 2013&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Record all the steps taken to process and analyze your data in scripts and avoid manual steps that are harder to reproduce.&lt;/li&gt;
&lt;li&gt;Documenting your code is key. Explain what steps are needed to reproduce the results (see our &lt;a href=&quot;https://github.com/codecheckers/sample-size-codecheck/&quot;&gt;README&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Make sure you systematically list all dependencies (software and packages).&lt;/li&gt;
&lt;li&gt;Use tools for version control.&lt;/li&gt;
&lt;li&gt;Use tools like &lt;a href=&quot;https://quarto.org/&quot;&gt;Quarto&lt;/a&gt;, &lt;a href=&quot;https://rmarkdown.rstudio.com/&quot;&gt;R markdown&lt;/a&gt;, or &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter notebooks&lt;/a&gt;. They provide a great way to share code, narrative text, and output in one document, making it much easier to clearly describe the steps that were taken to process and analyse the data.&lt;/li&gt;
&lt;li&gt;Partial reproducibility is always better than zero reproducibility! Don’t let the perfect be the enemy of the good.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In conclusion, getting our research codechecked was a very nice experience. With just a few extra steps (providing a short metadata file, adapting our README, requesting the check), we managed to obtain a nice certificate confirming that the computations underlying our article could be independently executed. I believe this additional check — next to traditional peer review — gives a nice extra boost to the credibility of our work. We therefore happily cited the CODECHECK certificate in our paper that got published recently (see &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-klapwijk2025&quot;&gt;Klapwijk et al. 2025&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Did you work hard to make your research reproducible? Then definitely have it codechecked!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I would like to thank Lieke de Boer for excellent feedback on a draft version of this post.&lt;/p&gt;
&lt;p&gt;This post was initially published &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/&quot;&gt;here&lt;/a&gt;. For attribution, please cite this work as:&lt;/p&gt;
&lt;p&gt;Klapwijk, Eduard T. 2025. “My Experience of Getting Codechecked.” January 16, 2025. &lt;a href=&quot;https://doi.org/10.5281/zenodo.14651307&quot;&gt;https://doi.org/10.5281/zenodo.14651307&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 16 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;6&lt;/p&gt;
&lt;p&gt;*By eScience Fellow *&lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/eduard-klapwijk/&quot;&gt;&lt;em&gt;Eduard Klapwijk&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This year I was finalizing and publishing one of my own research projects. My coauthors and I took many steps to make the project as reproducible as possible.&lt;/p&gt;
&lt;p&gt;Because I am setting up a codecheck workflow to check the reproducibility of research results for researchers at my institute, I was eager to submit my own work to the test. How reproducible would our work be when submitted to an external test?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;My experience of getting codechecked&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/my-experience-of-getting-codechecked-fd5cf777.CFP8GMsa_WjAUO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@hjkp?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;henry perks&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-check-for-reproducibility&quot;&gt;A check for reproducibility&lt;/h2&gt;
&lt;p&gt;I submitted my work to the &lt;a href=&quot;https://codecheck.org.uk/&quot;&gt;CODECHECK&lt;/a&gt; (&lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-n%C3%BCst2021&quot;&gt;Nüst and Eglen 2021&lt;/a&gt;) community workflow, which means that an external codechecker will do a light-weight reproducibility check. They will try to re-run my code to see if results reported in the paper can be reproduced.&lt;/p&gt;
&lt;p&gt;A codecheck was the perfect opportunity for checking how reproducible our project was. At the same time, the experience of getting my own work codechecked would help in understanding a researcher’s perspective on the process. In this post, I will share my personal experience of getting codechecked. This will hopefully demystify the process for any reader new to codechecking or curious about what codecheck is all about.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;My experience of getting codechecked&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;360&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/my-experience-of-getting-codechecked-c91a8ead.C3rwIrhs_Z1k7CIi.webp&quot; srcset=&quot;&quot;&gt;
Image: The &lt;a href=&quot;https://codecheck.org.uk/process/#figure-2-the-codecheck-example-process-implementation&quot;&gt;CODECHECK&lt;/a&gt; example workflow implementation.&lt;/p&gt;
&lt;h2 id=&quot;the-project-neuroup&quot;&gt;The project: neuroUp&lt;/h2&gt;
&lt;p&gt;The project submitted for the codecheck was in the making for about four years — a nice example of &lt;a href=&quot;https://linkinghub.elsevier.com/retrieve/pii/S1364661319302426&quot;&gt;Slow Science&lt;/a&gt; as per Uta Frith’s analogy. From the start of these four years, I tried to make all our scripts reproducible.&lt;/p&gt;
&lt;p&gt;A few years ago, we started out with a couple of unconnected R scripts. Only when I started drafting the research article, I combined the draft manuscript with the project’s code and computations in one place. I first used &lt;a href=&quot;https://rmarkdown.rstudio.com/&quot;&gt;R Markdown&lt;/a&gt; for this, and in the end of 2023 I switched to a similar tool now available in RStudio called &lt;a href=&quot;https://quarto.org/&quot;&gt;Quarto&lt;/a&gt;. On top of this, a key tool for reproducibility was the use of &lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; and &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; for version control. This helped to systematically track the evolution of the project and its code and allowed us to go back to a previous state of the code if needed.&lt;/p&gt;
&lt;p&gt;An important phase in the project was the step from working with loosely connected R scripts to the development of an R package (we called it &lt;a href=&quot;https://eduardklap.github.io/neuroUp/&quot;&gt;neuroUp&lt;/a&gt;). With the help of the fantastic &lt;a href=&quot;https://r-pkgs.org/&quot;&gt;R packages&lt;/a&gt; book by Hadley Wickham and Jennifer Bryan, I managed to develop my first R package out of the code for this paper. Although after having done this, I believe that for most research projects developing a custom software package is an overkill, organizing code in a package does provide a lot of benefits that make your code much more reproducible. It organizes your project according to a convention, specifies dependencies, and bundles data, code, and documentation (&lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-marwick2018&quot;&gt;Marwick, Boettiger, and Mullen 2018&lt;/a&gt;). This means other researchers can install, cite and use the package without having to understand exactly how your code works.&lt;/p&gt;
&lt;p&gt;When we posted &lt;a href=&quot;https://doi.org/10.31234/osf.io/cz32t&quot;&gt;the preprint for our paper&lt;/a&gt;, we also published a &lt;a href=&quot;https://eduardklap.github.io/sample-size-fmri/&quot;&gt;reproducible version of the manuscript&lt;/a&gt; online. That was the moment that we turned to the CODECHECK community workflow to check whether results were indeed reproducible, at least according to one independent codechecker who was not part of the research team.&lt;/p&gt;
&lt;h2 id=&quot;submitting-work-to-be-codechecked&quot;&gt;Submitting work to be codechecked&lt;/h2&gt;
&lt;p&gt;I chose CODECHECK because they offer a journal-independent community workflow. To be honest, submitting the work was daunting at first. I hesitated because based on the &lt;a href=&quot;https://codecheck.org.uk/guide/community-workflow-author#2-requirements&quot;&gt;instructions for authors&lt;/a&gt;, I thought I had to partly restructure my project and provide a new README and metadata file. Luckily, looking at some of the forked repositories in the &lt;a href=&quot;https://github.com/orgs/codecheckers/repositories&quot;&gt;codecheckers GitHub organization&lt;/a&gt; really helped. That made me realize that some were much more detailed than others and that I could suffice with just describing the files in the repository and instructions on how to run the code (I liked &lt;a href=&quot;https://github.com/codecheckers/mb11CalculusPilot&quot;&gt;this example&lt;/a&gt; by Bjørn Bartholdy and based my README on it).&lt;/p&gt;
&lt;p&gt;After the preparations, the procedure was straightforward. Using my GitHub account, I opened an issue on the codecheckers GitHub, which is made easy using their &lt;a href=&quot;https://github.com/codecheckers/register/issues/new/choose&quot;&gt;template issue&lt;/a&gt;. The only thing that confused me a little was the instruction to “link to the repository in the codecheckers organisation with the code”. Once I figured that I could also link to my own public repository that would be forked by the codechecker in the process, my project was ready to go!&lt;/p&gt;
&lt;h2 id=&quot;getting-the-results-of-the-check&quot;&gt;Getting the results of the check&lt;/h2&gt;
&lt;p&gt;After a short waiting time, I got notified with some good news: the checker was able to reproduce my work and we got a certificate (see &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-r%C3%B6seler2024&quot;&gt;Röseler 2024&lt;/a&gt;)! Of course, I was very happy. This meant that at least one other person at another moment in time was able to reproduce our work with the help of our data and code.&lt;/p&gt;
&lt;p&gt;But, as I also experienced when I later code-checked someone else’s work (&lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-joeytang2024&quot;&gt;Joey Tang et al. 2024&lt;/a&gt;), when everything is working smoothly (eventually maybe after debugging some dependencies), the whole process is not overly exciting. The machine is doing most of the work in that case, you just see a bunch of identical images or tables appearing on your screen.&lt;/p&gt;
&lt;p&gt;The kind of reproducibility that is checked (computational or methods reproducibility) is in the end actually quite basic. What is being checked is nothing more than a minimum but necessary condition of good and believable research: what is verified is whether the results can be independently re-run using the same data and code. Other relating concepts for reliable and trustworthy research results such as replicability, generalizibility, and robustness, may be more exciting, but require also much more effort or even new studies to check.&lt;/p&gt;
&lt;h2 id=&quot;final-reflections&quot;&gt;Final reflections&lt;/h2&gt;
&lt;p&gt;As with most things in life, preparing for the codecheck (by making sure your work is reproducible) is most of the work. Here are some key points to consider (see also these ten simple rules for reproducible research: &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-sandve2013&quot;&gt;Sandve et al. 2013&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Record all the steps taken to process and analyze your data in scripts and avoid manual steps that are harder to reproduce.&lt;/li&gt;
&lt;li&gt;Documenting your code is key. Explain what steps are needed to reproduce the results (see our &lt;a href=&quot;https://github.com/codecheckers/sample-size-codecheck/&quot;&gt;README&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Make sure you systematically list all dependencies (software and packages).&lt;/li&gt;
&lt;li&gt;Use tools for version control.&lt;/li&gt;
&lt;li&gt;Use tools like &lt;a href=&quot;https://quarto.org/&quot;&gt;Quarto&lt;/a&gt;, &lt;a href=&quot;https://rmarkdown.rstudio.com/&quot;&gt;R markdown&lt;/a&gt;, or &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter notebooks&lt;/a&gt;. They provide a great way to share code, narrative text, and output in one document, making it much easier to clearly describe the steps that were taken to process and analyse the data.&lt;/li&gt;
&lt;li&gt;Partial reproducibility is always better than zero reproducibility! Don’t let the perfect be the enemy of the good.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In conclusion, getting our research codechecked was a very nice experience. With just a few extra steps (providing a short metadata file, adapting our README, requesting the check), we managed to obtain a nice certificate confirming that the computations underlying our article could be independently executed. I believe this additional check — next to traditional peer review — gives a nice extra boost to the credibility of our work. We therefore happily cited the CODECHECK certificate in our paper that got published recently (see &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/#ref-klapwijk2025&quot;&gt;Klapwijk et al. 2025&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Did you work hard to make your research reproducible? Then definitely have it codechecked!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I would like to thank Lieke de Boer for excellent feedback on a draft version of this post.&lt;/p&gt;
&lt;p&gt;This post was initially published &lt;a href=&quot;https://eduardklap.github.io/repro-checks/posts/2025-01-16-experience-getting-codechecked/&quot;&gt;here&lt;/a&gt;. For attribution, please cite this work as:&lt;/p&gt;
&lt;p&gt;Klapwijk, Eduard T. 2025. “My Experience of Getting Codechecked.” January 16, 2025. &lt;a href=&quot;https://doi.org/10.5281/zenodo.14651307&quot;&gt;https://doi.org/10.5281/zenodo.14651307&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/my-experience-of-getting-codechecked-fd5cf777.CFP8GMsa.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Out of office: holiday mode activated</title><link>https://blog2.esciencecenter.nl/posts/2024-12-20---out-of-office-holiday-mode-activated</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-12-20---out-of-office-holiday-mode-activated</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;711&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Lgda4zrJwtyb8A-E-JQ7Jg-1e176f31.Bbnqjlvu_1wPykP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As the year winds down, the Netherlands eScience Center editorial team will be taking a short hiatus for the holidays to recharge and prepare for an exciting year ahead. While we’re away, we’ve curated a list of thought-provoking blog posts for you to explore. From open science innovations to the latest in data-driven research, these articles will keep you inspired. Wishing you a joyful holiday season and see you in the new year!&lt;/p&gt;
&lt;p&gt;Blogs to read while we’re away:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/beyond-research-e220eb18f8b4?sk=a9d1492d69a1737156859679d895e5a0&quot;&gt;Beyond Research&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/a-helpful-noob-540229f13ac0?sk=d1438f07a60c4fb95c646fd7c87129e2&quot;&gt;A Helpful Noob&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/what-research-software-engineers-can-learn-from-taylor-swift-92bf955a5bb4?sk=941654c629a8c43fe4c1dd7242358711&quot;&gt;What Research Software Engineers can learn from Taylor Swift&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/un-wieldy-workflows-with-wrf-4a4947b88a98?sk=4e04510a60fcb53354019aaddda217b3&quot;&gt;(Un)wieldy workflows with WRF&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 20 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;711&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Lgda4zrJwtyb8A-E-JQ7Jg-1e176f31.Bbnqjlvu_1wPykP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;As the year winds down, the Netherlands eScience Center editorial team will be taking a short hiatus for the holidays to recharge and prepare for an exciting year ahead. While we’re away, we’ve curated a list of thought-provoking blog posts for you to explore. From open science innovations to the latest in data-driven research, these articles will keep you inspired. Wishing you a joyful holiday season and see you in the new year!&lt;/p&gt;
&lt;p&gt;Blogs to read while we’re away:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/beyond-research-e220eb18f8b4?sk=a9d1492d69a1737156859679d895e5a0&quot;&gt;Beyond Research&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/a-helpful-noob-540229f13ac0?sk=d1438f07a60c4fb95c646fd7c87129e2&quot;&gt;A Helpful Noob&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/what-research-software-engineers-can-learn-from-taylor-swift-92bf955a5bb4?sk=941654c629a8c43fe4c1dd7242358711&quot;&gt;What Research Software Engineers can learn from Taylor Swift&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/un-wieldy-workflows-with-wrf-4a4947b88a98?sk=4e04510a60fcb53354019aaddda217b3&quot;&gt;(Un)wieldy workflows with WRF&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Lgda4zrJwtyb8A-E-JQ7Jg-1e176f31.Bbnqjlvu.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Amsterdam as seen by a weather model</title><link>https://blog2.esciencecenter.nl/posts/2024-12-10---amsterdam-as-seen-by-a-weather-model</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-12-10---amsterdam-as-seen-by-a-weather-model</guid><description>&lt;h2 id=&quot;visualizing-local-climate-zones-in-3d-with-the-cityblocks-package&quot;&gt;Visualizing local climate zones in 3D with the Cityblocks package&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;What sets a weather model apart from a video game? While video games prioritize stunning visuals over strict realism, weather models focus entirely on physics. Visualizations come as an afterthought at best. A missed opportunity, since good visualizations can reveal fascinating insights into how these models interpret the world. In this blogpost we bring Amsterdam to life in 3D through the eyes of a weather model — and invite you to try it for your city as well.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Weather models have a peculiar view of a city. To them, the world is made of boxes. Many roughly rectangular boxes. A typical grid box contains more than one building, so weather models see cities at a block level.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;660&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_l4MLhZBrZbnuEC8AjIcJuQ-6d434fb4.BITi-oSW_Z1JXlcN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Weather and climate models divide the earth in grid cells. Each grid cell encompasses a wealth of information and processes, which must be represented in a simplified form. Source: wikipedia&lt;/p&gt;
&lt;p&gt;To describe cities at block level, one option is to use &lt;a href=&quot;https://doi.org/10.1016/j.rse.2023.113573&quot;&gt;local climate zones&lt;/a&gt; (LCZs): a set of typical building blocks modeled after cities across the globe. Each LCZ is associated with certain properties, such as the typical building height, street width, or green fraction. With that, weather models have all the info they need to simulate the interaction between the city and the atmosphere, in a simplified form.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1104&quot; height=&quot;384&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_I_qyITwlKMyiXrfSdUfluQ-7ef7b6a6.BdNWV3xD_1bOLvl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Left: Illustration of the local climate zones ( source ). Right: map of local climate zones for Amsterdam ( ).&lt;/p&gt;
&lt;p&gt;Typically, maps of local climate zones are displayed in 2D — a flat map. In principle, this is good enough, as we have only one LCZ per grid cell. But it doesn’t really appeal to the imagination. From the map above, I cannot tell how realistic this representation of Amsterdam actually is.&lt;/p&gt;
&lt;p&gt;That’s why I started playing around with 3D visualizations instead. The idea is to reproduce the tiles from the illustration above as building blocks, and then place them on a plane in accordance with the pixels on the 2D map. Below, we detail two approaches, one with CityJSON, and one with QGIS.&lt;/p&gt;
&lt;h2 id=&quot;building-a-city-in-cityjson&quot;&gt;Building a city in CityJSON&lt;/h2&gt;
&lt;p&gt;CityJSON file format is intended as a lightweight and developer-friendly format for spatial information. Like JSON, it is basically a set of key-value pairs. The &lt;a href=&quot;https://www.cityjson.org/specs/overview/&quot;&gt;CityJSON format&lt;/a&gt; specifies which keys are allowed/required and what values they can have. I was not familiar with the format, so this part of the blogpost also represents my learning experience. A simple CityJSON file could look like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;CityJSON&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;metadata&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;geographicalExtent&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;transform&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;scale&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;translate&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;extensions&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;vertices&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;CityObjects&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;id-1&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;geometry&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &quot;boundaries&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &quot;lod&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Solid&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;attributes&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;function&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;something&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GenericCityObject&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;vertices&lt;/code&gt; represent points in 3D space. This file specifies 8 points. Each &lt;code&gt;CityObject&lt;/code&gt; specifies an array of &lt;code&gt;boundaries&lt;/code&gt;, which are essentially surfaces obtained by connecting the vertices. Here we have 6 surfaces, and if you draw them all up, you will see that this is simply a model for a cube.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.cityjson.org/&quot;&gt;CityJSON home page&lt;/a&gt; is very welcoming. It contains lots of useful information and examples. There is an official online CityJSON &lt;a href=&quot;https://validator.cityjson.org/&quot;&gt;validator&lt;/a&gt;, as well as a &lt;a href=&quot;https://viewer.cityjson.org/&quot;&gt;viewer&lt;/a&gt; called Ninja. So once you’ve obtained a CityJSON file, you can easily validate it and display it in the browser.&lt;/p&gt;
&lt;p&gt;I started with the &lt;a href=&quot;https://www.cityjson.org/datasets/#simple-geometries&quot;&gt;example&lt;/a&gt; of 2 cubes, and wrote &lt;a href=&quot;https://github.com/Urban-M4/cityjson-generator&quot;&gt;some Python code&lt;/a&gt; to reproduce them as templates, such that I could place blocks randomly everywhere, and scale them in width and height. I created multiple combinations of blocks to reproduce the LCZ archetypes.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;406&quot; height=&quot;387&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EwYAPHFMN43apRcsZYo7QQ-18380ed7.B5AGWn_A_Z1X8E6D.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;LCZ archetypes reproduced in CityJSON.&lt;/p&gt;
&lt;p&gt;Next, I played a little bit with some random data to see how big of a city I could render. I found that 100 by 100 tiles still worked okay in the Ninja viewer. Effectively, this corresponds to a city of 10 by 10 km. I downloaded the global LCZ map from &lt;a href=&quot;https://doi.org/10.5281/zenodo.7670653&quot;&gt;Demuzere et al.&lt;/a&gt; and cut out the Amsterdam area. The last step was to loop over all pixels in the image, and add the corresponding tile to the CityJSON file.&lt;/p&gt;
&lt;p&gt;The code ran quite slowly, but it worked. The Ninja viewer went into “performance mode”, but eventually was able to display the data just fine. I was ready to observe the highly anticipating result…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;462&quot; height=&quot;387&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_qw1Ym7xaVw_aT_FnEQHvAw-bdc06d5d.DkKxDMRf_1s33Wy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Amsterdam rendered as 3D LCZ tiles. Blue designates correspond to water, yellow designates all other non-urban land use pixels.&lt;/p&gt;
&lt;p&gt;Admittedly, that looks a bit less spectacular than I had hoped for. The interactive view is a bit better, but still. While you can recognize the river, a canal, some parks and different types of buildings, this doesn’t really appeal to the imagination as I had hoped.&lt;/p&gt;
&lt;p&gt;One way to improve upon this initial view would be to render the different LCZ classes with different colors, and make the tiles prettier with things like trees, just like on the example tiles above. However, it seemed the online CityJSON viewer doesn’t support rendering materials, and I was already pushing its limits.&lt;/p&gt;
&lt;p&gt;In order to proceed with CityJSON, we would need to speed things up, and use a better viewer. There are several ways to speed things up. For example, by using &lt;a href=&quot;https://www.cityjson.org/cityjsonseq/&quot;&gt;CityJSON Sequence&lt;/a&gt; s and maybe converting to &lt;a href=&quot;https://github.com/3DGI/tyler&quot;&gt;3D Tiles&lt;/a&gt;. Concerning the viewer, I tried using the Blender and QGIS plugins, but I struggled to use them properly. In the long run, I would like to publish something like this on an interactive webpage, so I would prefer to look at other solutions. The standard viewer uses &lt;a href=&quot;https://threejs.org/&quot;&gt;three.js&lt;/a&gt; under the hood. It seems quite doable to embed such a viewer in a static website hosted from GitHub pages, for example. As such, anyone could clone the template and host their own city model with ease.&lt;/p&gt;
&lt;h2 id=&quot;making-it-beautiful-with-qgis&quot;&gt;Making it beautiful with QGIS&lt;/h2&gt;
&lt;p&gt;At this point I was showing my progress to my colleague Maurice. He is one of our GIS experts and helped me to reproduce the workflow in &lt;a href=&quot;https://www.qgis.org/&quot;&gt;QGIS&lt;/a&gt;. This alleviated some of the issues we had with the CityJSON viewer. With QGIS, we could render tiles in different colors, and use true coordinates to combine the tiles with other map layers. For example, here is a version where the colours of the tiles correspond to those on the 2D map above.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LlwYC1PNrl72OFSl81SLpA-65cd6b3e.DyFh8ZIo_1ptwiL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;3D rendering of local climate zones and other land use types for Amsterdam, using data from the global dataset from Demuzere et al.&lt;/p&gt;
&lt;p&gt;With QGIS, we took a slightly different approach. Instead of storing 3D cityblocks, we made 2D imprints of the LCZ types, and extruded them to a set height during the 3D render. We used Python with &lt;a href=&quot;https://rasterio.readthedocs.io/en/stable/&quot;&gt;rasterio&lt;/a&gt; and &lt;a href=&quot;https://geopandas.org/en/stable/&quot;&gt;geopandas&lt;/a&gt; to read and crop the original data and generate the 2D tiles. Intermediate data was stored as a &lt;a href=&quot;https://en.wikipedia.org/wiki/GeoPackage&quot;&gt;GeoPackage&lt;/a&gt;, which can easily be loaded in QGIS.&lt;/p&gt;
&lt;h3 id=&quot;introducing-cityblocks-a-simple-tool-to-visualize-your-own-city&quot;&gt;Introducing Cityblocks: a simple tool to visualize your own city&lt;/h3&gt;
&lt;p&gt;We decided to spend a bit more time to make this workflow available for anyone. We polished the code and converted it into a small and easy to use Python utility called &lt;a href=&quot;https://pypi.org/project/cityblocks/&quot;&gt;Cityblocks&lt;/a&gt;. You can use it to download the global dataset, extract an area of interest, and convert the data into tiles. Subsequently, the data can be visualized in QGIS, or something else in case you prefer. You can find the code and instructions &lt;a href=&quot;https://github.com/Urban-M4/cityblocks&quot;&gt;here&lt;/a&gt;. At the moment, this is mostly tested for our Amsterdam use case, so we are very curious to get feedback on your experience with it for other cities.&lt;/p&gt;
&lt;h2 id=&quot;making-it-beautiful&quot;&gt;Making it beautiful&lt;/h2&gt;
&lt;p&gt;At this point, we though it’d be nice to turn this little side quest into a real map that would stand its ground in an atlas of eScience Center projects.&lt;/p&gt;
&lt;p&gt;A good map tells a story that jumps at the viewer without much context. We considered many different options, and settled on a design that places the tiles on a background map of Amsterdam, with a subtle raster to hint at the gridded nature of weather models. Here is the final result:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1414&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_C8-_I_H5hGt1j7SPd-BK0Q-1a1ebcf6.BOPdODeY_Z2dXLNL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;3D Local climate zones overlaid on an aerial photograph of Amsterdam. The aerial photograph comes from PDOK.&lt;/p&gt;
&lt;p&gt;Seeing the map with and without LCZs makes it easy to compare the “human” view to the “weather model view”. Notice that most of the riverbank area, including the station, is classified as “heavy industry”, whereas the city center is dominated by “compact to open midrise”, for example. Apart from evaluating the classification itself, this view also reveals the relatively coarse structure the weather model sees, and how rigid the city looks. Perhaps it is a sobering view that reminds us that even sophisticated weather models are only an approximation of reality.&lt;/p&gt;
&lt;p&gt;But it is inspiring at the same time! How can we improve upon this? One of the obvious wins is to use local properties like building height, rather than using fixed values from the LCZ classification. We started doing that several years ago in a project called &lt;a href=&quot;https://research-software-directory.org/projects/summer-in-the-city&quot;&gt;Summer in the City&lt;/a&gt;. In that project, we identified properties like building height and “urban fraction” for the Netherlands. Now, in the &lt;a href=&quot;https://research-software-directory.org/projects/urban-m4&quot;&gt;Urban-M4&lt;/a&gt; project, we are adding information on the radiative properties of buildings, by using open street view imagery. At the same time, our project partners at Wageningen University are collecting information on building age and other properties to add better-localized information on things like insulation status.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;I also have some ideas regarding the workflow and visualization. If time permits, here are some things I’d like to improve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generalize tile creation: currently the position and dimensions of the buildings are hardcoded based on a tile size of 100x100m. It would be nice to generate them on the fly instead, so we could accomadate various resolutions.&lt;/li&gt;
&lt;li&gt;Randomize the tiles: related to the above, I’ve been thinking a bit on how to add some natural variation to the positioning of buildings. For example by randomly shifting tiles across periodic boundaries.&lt;/li&gt;
&lt;li&gt;Beyond LCZs: a generic tile creation routine could generate tiles based on some key properties like road width, building width, green fraction, et cetera. That would make it possible to vary these parameters independently, rather than coupled through LCZs.&lt;/li&gt;
&lt;li&gt;Combining the workflows for QGIS and CityJSON. Currently they have diverged a bit, but they share many steps. With a bit of work we could streamline and generalize the workflow and add support for other output formats as well.&lt;/li&gt;
&lt;li&gt;Procedural generation: automatically create artificial worlds and gamify urban weather and climate simulation 🙂&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;concluding-remarks&quot;&gt;Concluding remarks&lt;/h2&gt;
&lt;p&gt;When it comes to visualization in weather and climate modelling, we often focus on output data. Here, we introduce an original visualization of the methodology instead. This provides valuable insights into the power and limitations of the LCZ approach. It appeals to the imagination can make our work more captivating.&lt;/p&gt;
&lt;p&gt;What are your thoughs about using visualizations like this? Do you have other ideas, or want to share your own maps made with the Cityblocks package? We have created a &lt;a href=&quot;https://github.com/Urban-M4/cityblocks/issues/9&quot;&gt;GitHub issue&lt;/a&gt; to collect images of cities across the globe. It would be awesome if you would contribute your city as well!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Claire Donnely and Ole Mussmann for providing comments on an earlier version, and to Tim Tensen and Maurice de Kleijn for creating the beautiful QGIS map. A chatbot was used to improve the formulation of a few sentences.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Tue, 10 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;visualizing-local-climate-zones-in-3d-with-the-cityblocks-package&quot;&gt;Visualizing local climate zones in 3D with the Cityblocks package&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;What sets a weather model apart from a video game? While video games prioritize stunning visuals over strict realism, weather models focus entirely on physics. Visualizations come as an afterthought at best. A missed opportunity, since good visualizations can reveal fascinating insights into how these models interpret the world. In this blogpost we bring Amsterdam to life in 3D through the eyes of a weather model — and invite you to try it for your city as well.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Weather models have a peculiar view of a city. To them, the world is made of boxes. Many roughly rectangular boxes. A typical grid box contains more than one building, so weather models see cities at a block level.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;660&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_l4MLhZBrZbnuEC8AjIcJuQ-6d434fb4.BITi-oSW_Z1JXlcN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Weather and climate models divide the earth in grid cells. Each grid cell encompasses a wealth of information and processes, which must be represented in a simplified form. Source: wikipedia&lt;/p&gt;
&lt;p&gt;To describe cities at block level, one option is to use &lt;a href=&quot;https://doi.org/10.1016/j.rse.2023.113573&quot;&gt;local climate zones&lt;/a&gt; (LCZs): a set of typical building blocks modeled after cities across the globe. Each LCZ is associated with certain properties, such as the typical building height, street width, or green fraction. With that, weather models have all the info they need to simulate the interaction between the city and the atmosphere, in a simplified form.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1104&quot; height=&quot;384&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_I_qyITwlKMyiXrfSdUfluQ-7ef7b6a6.BdNWV3xD_1bOLvl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Left: Illustration of the local climate zones ( source ). Right: map of local climate zones for Amsterdam ( ).&lt;/p&gt;
&lt;p&gt;Typically, maps of local climate zones are displayed in 2D — a flat map. In principle, this is good enough, as we have only one LCZ per grid cell. But it doesn’t really appeal to the imagination. From the map above, I cannot tell how realistic this representation of Amsterdam actually is.&lt;/p&gt;
&lt;p&gt;That’s why I started playing around with 3D visualizations instead. The idea is to reproduce the tiles from the illustration above as building blocks, and then place them on a plane in accordance with the pixels on the 2D map. Below, we detail two approaches, one with CityJSON, and one with QGIS.&lt;/p&gt;
&lt;h2 id=&quot;building-a-city-in-cityjson&quot;&gt;Building a city in CityJSON&lt;/h2&gt;
&lt;p&gt;CityJSON file format is intended as a lightweight and developer-friendly format for spatial information. Like JSON, it is basically a set of key-value pairs. The &lt;a href=&quot;https://www.cityjson.org/specs/overview/&quot;&gt;CityJSON format&lt;/a&gt; specifies which keys are allowed/required and what values they can have. I was not familiar with the format, so this part of the blogpost also represents my learning experience. A simple CityJSON file could look like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;CityJSON&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;2.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;metadata&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;geographicalExtent&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;transform&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;scale&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.001&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;translate&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;extensions&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;vertices&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &quot;CityObjects&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &quot;id-1&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;geometry&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &quot;boundaries&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;              [[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;            ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;          ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &quot;lod&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;          &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Solid&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;attributes&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;function&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;something&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;      &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;GenericCityObject&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;vertices&lt;/code&gt; represent points in 3D space. This file specifies 8 points. Each &lt;code&gt;CityObject&lt;/code&gt; specifies an array of &lt;code&gt;boundaries&lt;/code&gt;, which are essentially surfaces obtained by connecting the vertices. Here we have 6 surfaces, and if you draw them all up, you will see that this is simply a model for a cube.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.cityjson.org/&quot;&gt;CityJSON home page&lt;/a&gt; is very welcoming. It contains lots of useful information and examples. There is an official online CityJSON &lt;a href=&quot;https://validator.cityjson.org/&quot;&gt;validator&lt;/a&gt;, as well as a &lt;a href=&quot;https://viewer.cityjson.org/&quot;&gt;viewer&lt;/a&gt; called Ninja. So once you’ve obtained a CityJSON file, you can easily validate it and display it in the browser.&lt;/p&gt;
&lt;p&gt;I started with the &lt;a href=&quot;https://www.cityjson.org/datasets/#simple-geometries&quot;&gt;example&lt;/a&gt; of 2 cubes, and wrote &lt;a href=&quot;https://github.com/Urban-M4/cityjson-generator&quot;&gt;some Python code&lt;/a&gt; to reproduce them as templates, such that I could place blocks randomly everywhere, and scale them in width and height. I created multiple combinations of blocks to reproduce the LCZ archetypes.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;406&quot; height=&quot;387&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EwYAPHFMN43apRcsZYo7QQ-18380ed7.B5AGWn_A_Z1X8E6D.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;LCZ archetypes reproduced in CityJSON.&lt;/p&gt;
&lt;p&gt;Next, I played a little bit with some random data to see how big of a city I could render. I found that 100 by 100 tiles still worked okay in the Ninja viewer. Effectively, this corresponds to a city of 10 by 10 km. I downloaded the global LCZ map from &lt;a href=&quot;https://doi.org/10.5281/zenodo.7670653&quot;&gt;Demuzere et al.&lt;/a&gt; and cut out the Amsterdam area. The last step was to loop over all pixels in the image, and add the corresponding tile to the CityJSON file.&lt;/p&gt;
&lt;p&gt;The code ran quite slowly, but it worked. The Ninja viewer went into “performance mode”, but eventually was able to display the data just fine. I was ready to observe the highly anticipating result…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;462&quot; height=&quot;387&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_qw1Ym7xaVw_aT_FnEQHvAw-bdc06d5d.DkKxDMRf_1s33Wy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Amsterdam rendered as 3D LCZ tiles. Blue designates correspond to water, yellow designates all other non-urban land use pixels.&lt;/p&gt;
&lt;p&gt;Admittedly, that looks a bit less spectacular than I had hoped for. The interactive view is a bit better, but still. While you can recognize the river, a canal, some parks and different types of buildings, this doesn’t really appeal to the imagination as I had hoped.&lt;/p&gt;
&lt;p&gt;One way to improve upon this initial view would be to render the different LCZ classes with different colors, and make the tiles prettier with things like trees, just like on the example tiles above. However, it seemed the online CityJSON viewer doesn’t support rendering materials, and I was already pushing its limits.&lt;/p&gt;
&lt;p&gt;In order to proceed with CityJSON, we would need to speed things up, and use a better viewer. There are several ways to speed things up. For example, by using &lt;a href=&quot;https://www.cityjson.org/cityjsonseq/&quot;&gt;CityJSON Sequence&lt;/a&gt; s and maybe converting to &lt;a href=&quot;https://github.com/3DGI/tyler&quot;&gt;3D Tiles&lt;/a&gt;. Concerning the viewer, I tried using the Blender and QGIS plugins, but I struggled to use them properly. In the long run, I would like to publish something like this on an interactive webpage, so I would prefer to look at other solutions. The standard viewer uses &lt;a href=&quot;https://threejs.org/&quot;&gt;three.js&lt;/a&gt; under the hood. It seems quite doable to embed such a viewer in a static website hosted from GitHub pages, for example. As such, anyone could clone the template and host their own city model with ease.&lt;/p&gt;
&lt;h2 id=&quot;making-it-beautiful-with-qgis&quot;&gt;Making it beautiful with QGIS&lt;/h2&gt;
&lt;p&gt;At this point I was showing my progress to my colleague Maurice. He is one of our GIS experts and helped me to reproduce the workflow in &lt;a href=&quot;https://www.qgis.org/&quot;&gt;QGIS&lt;/a&gt;. This alleviated some of the issues we had with the CityJSON viewer. With QGIS, we could render tiles in different colors, and use true coordinates to combine the tiles with other map layers. For example, here is a version where the colours of the tiles correspond to those on the 2D map above.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LlwYC1PNrl72OFSl81SLpA-65cd6b3e.DyFh8ZIo_1ptwiL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;3D rendering of local climate zones and other land use types for Amsterdam, using data from the global dataset from Demuzere et al.&lt;/p&gt;
&lt;p&gt;With QGIS, we took a slightly different approach. Instead of storing 3D cityblocks, we made 2D imprints of the LCZ types, and extruded them to a set height during the 3D render. We used Python with &lt;a href=&quot;https://rasterio.readthedocs.io/en/stable/&quot;&gt;rasterio&lt;/a&gt; and &lt;a href=&quot;https://geopandas.org/en/stable/&quot;&gt;geopandas&lt;/a&gt; to read and crop the original data and generate the 2D tiles. Intermediate data was stored as a &lt;a href=&quot;https://en.wikipedia.org/wiki/GeoPackage&quot;&gt;GeoPackage&lt;/a&gt;, which can easily be loaded in QGIS.&lt;/p&gt;
&lt;h3 id=&quot;introducing-cityblocks-a-simple-tool-to-visualize-your-own-city&quot;&gt;Introducing Cityblocks: a simple tool to visualize your own city&lt;/h3&gt;
&lt;p&gt;We decided to spend a bit more time to make this workflow available for anyone. We polished the code and converted it into a small and easy to use Python utility called &lt;a href=&quot;https://pypi.org/project/cityblocks/&quot;&gt;Cityblocks&lt;/a&gt;. You can use it to download the global dataset, extract an area of interest, and convert the data into tiles. Subsequently, the data can be visualized in QGIS, or something else in case you prefer. You can find the code and instructions &lt;a href=&quot;https://github.com/Urban-M4/cityblocks&quot;&gt;here&lt;/a&gt;. At the moment, this is mostly tested for our Amsterdam use case, so we are very curious to get feedback on your experience with it for other cities.&lt;/p&gt;
&lt;h2 id=&quot;making-it-beautiful&quot;&gt;Making it beautiful&lt;/h2&gt;
&lt;p&gt;At this point, we though it’d be nice to turn this little side quest into a real map that would stand its ground in an atlas of eScience Center projects.&lt;/p&gt;
&lt;p&gt;A good map tells a story that jumps at the viewer without much context. We considered many different options, and settled on a design that places the tiles on a background map of Amsterdam, with a subtle raster to hint at the gridded nature of weather models. Here is the final result:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1414&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_C8-_I_H5hGt1j7SPd-BK0Q-1a1ebcf6.BOPdODeY_Z2dXLNL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;3D Local climate zones overlaid on an aerial photograph of Amsterdam. The aerial photograph comes from PDOK.&lt;/p&gt;
&lt;p&gt;Seeing the map with and without LCZs makes it easy to compare the “human” view to the “weather model view”. Notice that most of the riverbank area, including the station, is classified as “heavy industry”, whereas the city center is dominated by “compact to open midrise”, for example. Apart from evaluating the classification itself, this view also reveals the relatively coarse structure the weather model sees, and how rigid the city looks. Perhaps it is a sobering view that reminds us that even sophisticated weather models are only an approximation of reality.&lt;/p&gt;
&lt;p&gt;But it is inspiring at the same time! How can we improve upon this? One of the obvious wins is to use local properties like building height, rather than using fixed values from the LCZ classification. We started doing that several years ago in a project called &lt;a href=&quot;https://research-software-directory.org/projects/summer-in-the-city&quot;&gt;Summer in the City&lt;/a&gt;. In that project, we identified properties like building height and “urban fraction” for the Netherlands. Now, in the &lt;a href=&quot;https://research-software-directory.org/projects/urban-m4&quot;&gt;Urban-M4&lt;/a&gt; project, we are adding information on the radiative properties of buildings, by using open street view imagery. At the same time, our project partners at Wageningen University are collecting information on building age and other properties to add better-localized information on things like insulation status.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;I also have some ideas regarding the workflow and visualization. If time permits, here are some things I’d like to improve:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generalize tile creation: currently the position and dimensions of the buildings are hardcoded based on a tile size of 100x100m. It would be nice to generate them on the fly instead, so we could accomadate various resolutions.&lt;/li&gt;
&lt;li&gt;Randomize the tiles: related to the above, I’ve been thinking a bit on how to add some natural variation to the positioning of buildings. For example by randomly shifting tiles across periodic boundaries.&lt;/li&gt;
&lt;li&gt;Beyond LCZs: a generic tile creation routine could generate tiles based on some key properties like road width, building width, green fraction, et cetera. That would make it possible to vary these parameters independently, rather than coupled through LCZs.&lt;/li&gt;
&lt;li&gt;Combining the workflows for QGIS and CityJSON. Currently they have diverged a bit, but they share many steps. With a bit of work we could streamline and generalize the workflow and add support for other output formats as well.&lt;/li&gt;
&lt;li&gt;Procedural generation: automatically create artificial worlds and gamify urban weather and climate simulation 🙂&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;concluding-remarks&quot;&gt;Concluding remarks&lt;/h2&gt;
&lt;p&gt;When it comes to visualization in weather and climate modelling, we often focus on output data. Here, we introduce an original visualization of the methodology instead. This provides valuable insights into the power and limitations of the LCZ approach. It appeals to the imagination can make our work more captivating.&lt;/p&gt;
&lt;p&gt;What are your thoughs about using visualizations like this? Do you have other ideas, or want to share your own maps made with the Cityblocks package? We have created a &lt;a href=&quot;https://github.com/Urban-M4/cityblocks/issues/9&quot;&gt;GitHub issue&lt;/a&gt; to collect images of cities across the globe. It would be awesome if you would contribute your city as well!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Claire Donnely and Ole Mussmann for providing comments on an earlier version, and to Tim Tensen and Maurice de Kleijn for creating the beautiful QGIS map. A chatbot was used to improve the formulation of a few sentences.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_l4MLhZBrZbnuEC8AjIcJuQ-6d434fb4.BITi-oSW.png" medium="image"/><author>Peter Kalverla</author></item><item><title>How much research output is really open, and how can we tell?</title><link>https://blog2.esciencecenter.nl/posts/2024-12-06---how-much-research-output-is-really-open-and-how-can-we-tell</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-12-06---how-much-research-output-is-really-open-and-how-can-we-tell</guid><description>&lt;p&gt;Written by &lt;a href=&quot;https://estherplomp.github.io/&quot;&gt;Esther Plomp&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/meron-vermaas/&quot;&gt;Meron Vermaas&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt;, &lt;a href=&quot;https://nemoandrea.github.io/#primarySection/greeterSlider&quot;&gt;Nemo Andrea&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/ewan-cahen/&quot;&gt;Ewan Cahen&lt;/a&gt;, &lt;a href=&quot;https://www.uu.nl/medewerkers/FPWeijdema&quot;&gt;Felix Weijdema&lt;/a&gt;, &lt;a href=&quot;https://www.uu.nl/medewerkers/DCHuijser&quot;&gt;Dorien Huijser&lt;/a&gt;, &lt;a href=&quot;https://www.openscience.nl/en/marta-teperek&quot;&gt;Marta Teperek&lt;/a&gt;, &lt;a href=&quot;https://www.tudelft.nl/library/research-data-management/r/support/data-stewardship/contact/bjoern-bartholdy&quot;&gt;Bjørn Bartholdy&lt;/a&gt; &amp;#x26; &lt;a href=&quot;https://www.universiteitleiden.nl/en/staffmembers/ana-parron-cabanero#tab-1&quot;&gt;Ana Parrón Cabañero&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;During the Open Science Festival in Maastricht on 22 October 2024, we gathered a full room for the session &lt;em&gt;&lt;a href=&quot;http://web.archive.org/web/20241107150720/https://www.opensciencefestival.nl/en/programme/tracking-research-objects-levelling-the-playing-field-in-research-assessment&quot;&gt;&lt;em&gt;Tracking Research Objects: Levelling the playing field in research assessment&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;! This was a topic that eScience Fellows Meron Vermaas and Esther Plomp were interested in investigating as a part of their &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;&lt;em&gt;eScience Center Fellowship&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; project. Read on to find out how you can investigate this using their methods!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How much research output is really open, and how can we tell?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-much-research-output-is-really-open--20fe968e.cQyvYruU_Z1kYsox.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@maplerockdesign?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Richard Bell&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We currently know a lot about how much research is published in Open Access publications for the Netherlands, to the degree that there are complete data and percentages available. For example, &lt;a href=&quot;https://www.tudelft.nl/en/library/support/library-for-researchers/publishing-outreach/creating-your-publishing-strategy/open-access-publishing&quot;&gt;TU Delft researchers published 98% of their publications Open Access in 2023&lt;/a&gt;. How much of the other research outputs are published openly remains a wild guess, as it is a lot more difficult to measure research objects such as datasets, software repositories, protocols, podcasts, community outreach projects and so forth.&lt;/p&gt;
&lt;p&gt;Just because these research objects are difficult to measure, does not necessarily mean they should not be measured. Being able to measure the degree of Open Access has led to positive attention for research outputs being openly available, and measuring this for other research objects may also result in increased sharing and recognition of these efforts.&lt;/p&gt;
&lt;p&gt;We therefore started our session with some case studies on how other research objects can be made more visible. Esther presented on a project from TU Delft, and Meron presented on two projects he has been involved with from the Vrije Universiteit Amsterdam and the HvA. See &lt;a href=&quot;https://doi.org/10.5281/zenodo.13952611&quot;&gt;their slides&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How much research output is really open, and how can we tell?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;671&quot; height=&quot;138&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-much-research-output-is-really-open--9a0295d3.4X1PY1Tg_1gzJm9.webp&quot; srcset=&quot;&quot;&gt;
Esther and Meron worked together during their eScience Fellowship projects with &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/ewan-cahen/&quot;&gt;Ewan Cahen&lt;/a&gt; from the Netherlands eScience Center to set up a workflow that could deduce from the DOIs of a journal article whether accompanying research objects are available. It turns out that it is possible to measure this fairly easily with a script that Ewan worked on, as long as the research objects are cited within the publication. This &lt;a href=&quot;https://github.com/EstherPlomp/TNW-Tracking/blob/main/main.py&quot;&gt;script is available on GitHub&lt;/a&gt; for others to try out and reuse.&lt;/p&gt;
&lt;p&gt;According to this data/script, the amount of shared research objects for the TU Delft Faculty of Applied Sciences in the period 2020–2023 range from 0–28%. This is likely to be an underestimate, as not all researchers cite the underlying/associated research objects within the article. The next steps for this project are to set up guidelines for researchers to make them aware why citation of these research objects are important, as well as perform text scraping to see how many other research objects are overlooked if we only look at cited research objects within the articles. For this, they will use a workflow that Meron has previously worked on during his &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/meron-vermaas/&quot;&gt;eScience Fellowship&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Meron and Ewan created a workflow to find code repositories created by researchers at the VU. Because it is not yet possible to track these in a straightforward way, they found them by looking into mentions of software repositories in scientific papers. While around 70% of the researchers mention the use of a research software (such as Python or R), only ~10% mention a code repository. However, mentioning a code repository does not automatically mean the code was created by the authors of the paper. Thus, this is probably an overestimation of the amount of software that was actually produced and published by researchers from the VU. As a next step &lt;a href=&quot;https://github.com/meronvermaas/PURE_fulltext_analysis&quot;&gt;the scripts (available on GitHub&lt;/a&gt;) also searched through the code repositories and checked if the contributors are affiliated to the VU. This allows for finding and then reaching out to researchers who shared their code, so that support can be offered to make the code repositories more FAIR. Getting in touch with those researchers is an ongoing effort.&lt;/p&gt;
&lt;h3 id=&quot;community-input-on-research-object-tracking&quot;&gt;Community input on research object tracking&lt;/h3&gt;
&lt;p&gt;After a presentation on these efforts, the group split into six groups that discussed questions related to research object tracking for ~ 15 minutes, and at the end of the session we reported back to the full group on our findings. Below follows a short summary for each of the groups:&lt;/p&gt;
&lt;p&gt;Group 1: Should we track research objects (what are the disadvantages?)?**&lt;/p&gt;
&lt;p&gt;This group thought it would be beneficial to track research objects and did not discuss any disadvantages. The group thought it was important for recognising the work, as well as the possibility of validating and verifying research. Careful attention should be paid to the gamification of this system, however, as well as the costs that may be involved in making these research objects available in a reusable and trackable manner. There needs to be incentives for the researchers and professional staff involved in these efforts to make it worthwhile.&lt;/p&gt;
&lt;p&gt;It also needs to be clearer what the definition of a research object is and what the scope is. Potentially every research output can be considered a research object — even non-digital objects such as physical samples (blood samples, synthetic materials, or geological samples).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 2: In what way would tracking of research objects nurture a culture of sharing research outputs?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By tracking research objects individuals involved in research can be made aware of the benefits of sharing research objects: the visibility and accessibility of research outputs are important. To promote sharing practices we can develop and provide workshops and share recommended practices (research objects need a DOI, be registered in CRIS (current research information system), and/or made discoverable via preprint servers or data repositories).&lt;/p&gt;
&lt;p&gt;Nevertheless, sharing research objects may be discipline dependent, and may not apply to all disciplines, or may apply differently (what about law and history?). Not all research may result in research objects that are trackable!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 3: What (existing) technological infrastructure would be needed to effectively track research objects?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This group discussed how ORCID could also be used to automatically track research objects. ORCID has options to connect with existing research-object infrastructures and automatically add the publications, protocols and software to a researcher’s profiles. Since ORCID is not widely used for tracking research objects, more awareness of these capabilities may be needed.&lt;/p&gt;
&lt;p&gt;For data and software sharing the existing infrastructure are already available. For example, there are hosting services that make use of Git such as GitHub, or open source alternatives such as GitLab and GitTea, in combination with data repositories. For the sharing of protocols, there are protocols servers that can be used such as &lt;a href=&quot;http://protocols.io&quot;&gt;protocols.io&lt;/a&gt;, or open source alternatives such as &lt;a href=&quot;https://osf.io/&quot;&gt;OSF&lt;/a&gt;. Since the infrastructure already exists for many purposes, the limiting factor seems to be the awareness of the resources available, and the practical implementation of citing research objects in publications. An example is the self-citation needed to automatically detect shared research objects (as done in the case study described by Esther). To solve this problem, the group came up with an idea of a tool where researchers can upload their text of a version of their article (before submitting to a journal!), that will analyse the text content and check for missing links and DOIs (for example: “you mentioned a GitHub repository but no DOI for data was found” or “no data repository was found, did you know you can upload your data free of charge to 4TU.ReseachData”). This way, researchers are automatically notified about any missing links or citations to research objects. Currently, there is a proposal (by a group not part of the session) to develop a software called “&lt;a href=&quot;https://osf.io/z3tr9&quot;&gt;Transparency Check&lt;/a&gt;” that will provide an automatic assessment and suggestions for the improvement of the transparency of data and methods in research reports before they are published.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 4: How can we balance quantitative metrics and qualitative indicators in the evaluation of research objects?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;They also discussed the dangers of quantitative metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Counting outputs can lead to prioritising quantity over quality (such as splitting up a dataset and publishing the subsets to have “more” datasets published).&lt;/li&gt;
&lt;li&gt;Quantitative metrics are subjected to circumventing, hacking and gaming.&lt;/li&gt;
&lt;li&gt;Quantitative metrics do not describe how the funding was used throughout the project and provide little context.&lt;/li&gt;
&lt;li&gt;It is difficult to quantify open science related work.&lt;/li&gt;
&lt;li&gt;Comparing metrics between institutes may lead to counterproductive competition and not be representative of the actual work that went into the outputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Group 5: What would you use research object tracking for? How can tracking research objects promote equity and inclusion within the research community?**&lt;/p&gt;
&lt;p&gt;This group noted that tracking research objects can be helpful to measure impact of research, and may also be very relevant to funders. It can also help to provide input for policies and to provide ways to guide support distribution, as it would be possible to establish targeted support based on the tracking research objects. Tracking research objects could promote equity and inclusion within the research community as it would provide recognition for all research outputs, not just papers, also datasets, podcasts and other research objects. This could include recognition for all staff involved in research, also professional staff.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 6: How do we track research objects in a way that helps us to understand how behaviour changes over time?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The last group came up with their own question to address, and focused on working backwards from what type of behaviour we would like to track or change. The end goal is not to track research objects: we want the broader adoption of open science practices. The group pondered how the why behind all of this could be changing — why would researchers want to share their research objects? What research objects could they create, and which of those are being tracked? They also discussed whether Data Management Plans could be a tool to change behaviour, and whether monitoring data management plans would be helpful: are Data Management Plans updated — when and why?&lt;/p&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;
&lt;p&gt;We also distributed a survey/form with 9 respondents to collect examples of best practices across the Dutch and international landscape:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which infrastructures are used in your organisation to track research objects?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The majority (8 out of 9) mentioned their current research information system (CRIS), generally PURE. Three cases mention tracking the use of &lt;a href=&quot;http://www.isaac.nwo.nl/en&quot;&gt;ISAAC&lt;/a&gt;, &lt;a href=&quot;https://dataverse.nl/&quot;&gt;dataverse&lt;/a&gt;, &lt;a href=&quot;https://data.4tu.nl/&quot;&gt;the inhouse repository&lt;/a&gt; and &lt;a href=&quot;https://openalex.org/&quot;&gt;OpenAlex&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which research objects are being tracked?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Considering the majority using PURE as their main tracking system, it does not come as a surprise that publications are also the main research object being tracked. Six also mention datasets and there are isolated occurrences of tracking code, media appearances, supervised theses, keynote lectures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What does your organisation use research object tracking for?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Most responses mention reporting, evaluation and assessment. Also the ambition to use it to effectively recognise and reward non traditional research outputs.One institute responded that descriptive reports on scientific activities at departmental level are used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you know of other successful examples of research object tracking?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Positive responses were sparse in this question. The &lt;a href=&quot;https://theplosblog.plos.org/2023/06/open-science-indicators-update-q1-2023/&quot;&gt;PLOS Open Science Indicators&lt;/a&gt; were mentioned and a &lt;a href=&quot;https://fairdashboard.helmholtz-metadaten.de/en/data_in_helmholtz&quot;&gt;FAIR dashboard &lt;/a&gt;was shared. A promising outlook into the future was mentioned where an institute is working on creating a platform to keep track of the research outputs (as well as the Research Data Management &amp;#x26; Open Science compliance documents such as Data Management Plans, Software Management Plans, Privacy and Ethics). In the session slide initiatives such as &lt;a href=&quot;https://quest-dashboard.charite.de/&quot;&gt;Charité Metrics Dashboard&lt;/a&gt;, &lt;a href=&quot;https://frenchopensciencemonitor.esr.gouv.fr/&quot;&gt;French Open Science monitor&lt;/a&gt; and the &lt;a href=&quot;https://open-science-monitoring.org/&quot;&gt;Open Science Monitoring Initiative&lt;/a&gt; were mentioned.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Collaborative initiatives can create a more equitable research assessment framework that recognizes diverse contributions to science. If you’re passionate about advancing Open Science and interested in contributing to similar community projects, consider applying for the &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;eScience Center Fellowship program&lt;/a&gt;. The Fellowship gives researchers and supporters the opportunity to work on technical solutions for open science challenges while collaborating with experts in the field.&lt;/p&gt;</description><pubDate>Fri, 06 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Written by &lt;a href=&quot;https://estherplomp.github.io/&quot;&gt;Esther Plomp&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/meron-vermaas/&quot;&gt;Meron Vermaas&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt;, &lt;a href=&quot;https://nemoandrea.github.io/#primarySection/greeterSlider&quot;&gt;Nemo Andrea&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/ewan-cahen/&quot;&gt;Ewan Cahen&lt;/a&gt;, &lt;a href=&quot;https://www.uu.nl/medewerkers/FPWeijdema&quot;&gt;Felix Weijdema&lt;/a&gt;, &lt;a href=&quot;https://www.uu.nl/medewerkers/DCHuijser&quot;&gt;Dorien Huijser&lt;/a&gt;, &lt;a href=&quot;https://www.openscience.nl/en/marta-teperek&quot;&gt;Marta Teperek&lt;/a&gt;, &lt;a href=&quot;https://www.tudelft.nl/library/research-data-management/r/support/data-stewardship/contact/bjoern-bartholdy&quot;&gt;Bjørn Bartholdy&lt;/a&gt; &amp;#x26; &lt;a href=&quot;https://www.universiteitleiden.nl/en/staffmembers/ana-parron-cabanero#tab-1&quot;&gt;Ana Parrón Cabañero&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;During the Open Science Festival in Maastricht on 22 October 2024, we gathered a full room for the session &lt;em&gt;&lt;a href=&quot;http://web.archive.org/web/20241107150720/https://www.opensciencefestival.nl/en/programme/tracking-research-objects-levelling-the-playing-field-in-research-assessment&quot;&gt;&lt;em&gt;Tracking Research Objects: Levelling the playing field in research assessment&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;! This was a topic that eScience Fellows Meron Vermaas and Esther Plomp were interested in investigating as a part of their &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;&lt;em&gt;eScience Center Fellowship&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; project. Read on to find out how you can investigate this using their methods!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How much research output is really open, and how can we tell?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-much-research-output-is-really-open--20fe968e.cQyvYruU_Z1kYsox.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@maplerockdesign?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Richard Bell&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We currently know a lot about how much research is published in Open Access publications for the Netherlands, to the degree that there are complete data and percentages available. For example, &lt;a href=&quot;https://www.tudelft.nl/en/library/support/library-for-researchers/publishing-outreach/creating-your-publishing-strategy/open-access-publishing&quot;&gt;TU Delft researchers published 98% of their publications Open Access in 2023&lt;/a&gt;. How much of the other research outputs are published openly remains a wild guess, as it is a lot more difficult to measure research objects such as datasets, software repositories, protocols, podcasts, community outreach projects and so forth.&lt;/p&gt;
&lt;p&gt;Just because these research objects are difficult to measure, does not necessarily mean they should not be measured. Being able to measure the degree of Open Access has led to positive attention for research outputs being openly available, and measuring this for other research objects may also result in increased sharing and recognition of these efforts.&lt;/p&gt;
&lt;p&gt;We therefore started our session with some case studies on how other research objects can be made more visible. Esther presented on a project from TU Delft, and Meron presented on two projects he has been involved with from the Vrije Universiteit Amsterdam and the HvA. See &lt;a href=&quot;https://doi.org/10.5281/zenodo.13952611&quot;&gt;their slides&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How much research output is really open, and how can we tell?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;671&quot; height=&quot;138&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-much-research-output-is-really-open--9a0295d3.4X1PY1Tg_1gzJm9.webp&quot; srcset=&quot;&quot;&gt;
Esther and Meron worked together during their eScience Fellowship projects with &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/ewan-cahen/&quot;&gt;Ewan Cahen&lt;/a&gt; from the Netherlands eScience Center to set up a workflow that could deduce from the DOIs of a journal article whether accompanying research objects are available. It turns out that it is possible to measure this fairly easily with a script that Ewan worked on, as long as the research objects are cited within the publication. This &lt;a href=&quot;https://github.com/EstherPlomp/TNW-Tracking/blob/main/main.py&quot;&gt;script is available on GitHub&lt;/a&gt; for others to try out and reuse.&lt;/p&gt;
&lt;p&gt;According to this data/script, the amount of shared research objects for the TU Delft Faculty of Applied Sciences in the period 2020–2023 range from 0–28%. This is likely to be an underestimate, as not all researchers cite the underlying/associated research objects within the article. The next steps for this project are to set up guidelines for researchers to make them aware why citation of these research objects are important, as well as perform text scraping to see how many other research objects are overlooked if we only look at cited research objects within the articles. For this, they will use a workflow that Meron has previously worked on during his &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/meron-vermaas/&quot;&gt;eScience Fellowship&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Meron and Ewan created a workflow to find code repositories created by researchers at the VU. Because it is not yet possible to track these in a straightforward way, they found them by looking into mentions of software repositories in scientific papers. While around 70% of the researchers mention the use of a research software (such as Python or R), only ~10% mention a code repository. However, mentioning a code repository does not automatically mean the code was created by the authors of the paper. Thus, this is probably an overestimation of the amount of software that was actually produced and published by researchers from the VU. As a next step &lt;a href=&quot;https://github.com/meronvermaas/PURE_fulltext_analysis&quot;&gt;the scripts (available on GitHub&lt;/a&gt;) also searched through the code repositories and checked if the contributors are affiliated to the VU. This allows for finding and then reaching out to researchers who shared their code, so that support can be offered to make the code repositories more FAIR. Getting in touch with those researchers is an ongoing effort.&lt;/p&gt;
&lt;h3 id=&quot;community-input-on-research-object-tracking&quot;&gt;Community input on research object tracking&lt;/h3&gt;
&lt;p&gt;After a presentation on these efforts, the group split into six groups that discussed questions related to research object tracking for ~ 15 minutes, and at the end of the session we reported back to the full group on our findings. Below follows a short summary for each of the groups:&lt;/p&gt;
&lt;p&gt;Group 1: Should we track research objects (what are the disadvantages?)?**&lt;/p&gt;
&lt;p&gt;This group thought it would be beneficial to track research objects and did not discuss any disadvantages. The group thought it was important for recognising the work, as well as the possibility of validating and verifying research. Careful attention should be paid to the gamification of this system, however, as well as the costs that may be involved in making these research objects available in a reusable and trackable manner. There needs to be incentives for the researchers and professional staff involved in these efforts to make it worthwhile.&lt;/p&gt;
&lt;p&gt;It also needs to be clearer what the definition of a research object is and what the scope is. Potentially every research output can be considered a research object — even non-digital objects such as physical samples (blood samples, synthetic materials, or geological samples).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 2: In what way would tracking of research objects nurture a culture of sharing research outputs?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By tracking research objects individuals involved in research can be made aware of the benefits of sharing research objects: the visibility and accessibility of research outputs are important. To promote sharing practices we can develop and provide workshops and share recommended practices (research objects need a DOI, be registered in CRIS (current research information system), and/or made discoverable via preprint servers or data repositories).&lt;/p&gt;
&lt;p&gt;Nevertheless, sharing research objects may be discipline dependent, and may not apply to all disciplines, or may apply differently (what about law and history?). Not all research may result in research objects that are trackable!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 3: What (existing) technological infrastructure would be needed to effectively track research objects?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This group discussed how ORCID could also be used to automatically track research objects. ORCID has options to connect with existing research-object infrastructures and automatically add the publications, protocols and software to a researcher’s profiles. Since ORCID is not widely used for tracking research objects, more awareness of these capabilities may be needed.&lt;/p&gt;
&lt;p&gt;For data and software sharing the existing infrastructure are already available. For example, there are hosting services that make use of Git such as GitHub, or open source alternatives such as GitLab and GitTea, in combination with data repositories. For the sharing of protocols, there are protocols servers that can be used such as &lt;a href=&quot;http://protocols.io&quot;&gt;protocols.io&lt;/a&gt;, or open source alternatives such as &lt;a href=&quot;https://osf.io/&quot;&gt;OSF&lt;/a&gt;. Since the infrastructure already exists for many purposes, the limiting factor seems to be the awareness of the resources available, and the practical implementation of citing research objects in publications. An example is the self-citation needed to automatically detect shared research objects (as done in the case study described by Esther). To solve this problem, the group came up with an idea of a tool where researchers can upload their text of a version of their article (before submitting to a journal!), that will analyse the text content and check for missing links and DOIs (for example: “you mentioned a GitHub repository but no DOI for data was found” or “no data repository was found, did you know you can upload your data free of charge to 4TU.ReseachData”). This way, researchers are automatically notified about any missing links or citations to research objects. Currently, there is a proposal (by a group not part of the session) to develop a software called “&lt;a href=&quot;https://osf.io/z3tr9&quot;&gt;Transparency Check&lt;/a&gt;” that will provide an automatic assessment and suggestions for the improvement of the transparency of data and methods in research reports before they are published.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 4: How can we balance quantitative metrics and qualitative indicators in the evaluation of research objects?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;They also discussed the dangers of quantitative metrics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Counting outputs can lead to prioritising quantity over quality (such as splitting up a dataset and publishing the subsets to have “more” datasets published).&lt;/li&gt;
&lt;li&gt;Quantitative metrics are subjected to circumventing, hacking and gaming.&lt;/li&gt;
&lt;li&gt;Quantitative metrics do not describe how the funding was used throughout the project and provide little context.&lt;/li&gt;
&lt;li&gt;It is difficult to quantify open science related work.&lt;/li&gt;
&lt;li&gt;Comparing metrics between institutes may lead to counterproductive competition and not be representative of the actual work that went into the outputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Group 5: What would you use research object tracking for? How can tracking research objects promote equity and inclusion within the research community?**&lt;/p&gt;
&lt;p&gt;This group noted that tracking research objects can be helpful to measure impact of research, and may also be very relevant to funders. It can also help to provide input for policies and to provide ways to guide support distribution, as it would be possible to establish targeted support based on the tracking research objects. Tracking research objects could promote equity and inclusion within the research community as it would provide recognition for all research outputs, not just papers, also datasets, podcasts and other research objects. This could include recognition for all staff involved in research, also professional staff.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Group 6: How do we track research objects in a way that helps us to understand how behaviour changes over time?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The last group came up with their own question to address, and focused on working backwards from what type of behaviour we would like to track or change. The end goal is not to track research objects: we want the broader adoption of open science practices. The group pondered how the why behind all of this could be changing — why would researchers want to share their research objects? What research objects could they create, and which of those are being tracked? They also discussed whether Data Management Plans could be a tool to change behaviour, and whether monitoring data management plans would be helpful: are Data Management Plans updated — when and why?&lt;/p&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;
&lt;p&gt;We also distributed a survey/form with 9 respondents to collect examples of best practices across the Dutch and international landscape:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which infrastructures are used in your organisation to track research objects?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The majority (8 out of 9) mentioned their current research information system (CRIS), generally PURE. Three cases mention tracking the use of &lt;a href=&quot;http://www.isaac.nwo.nl/en&quot;&gt;ISAAC&lt;/a&gt;, &lt;a href=&quot;https://dataverse.nl/&quot;&gt;dataverse&lt;/a&gt;, &lt;a href=&quot;https://data.4tu.nl/&quot;&gt;the inhouse repository&lt;/a&gt; and &lt;a href=&quot;https://openalex.org/&quot;&gt;OpenAlex&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which research objects are being tracked?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Considering the majority using PURE as their main tracking system, it does not come as a surprise that publications are also the main research object being tracked. Six also mention datasets and there are isolated occurrences of tracking code, media appearances, supervised theses, keynote lectures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What does your organisation use research object tracking for?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Most responses mention reporting, evaluation and assessment. Also the ambition to use it to effectively recognise and reward non traditional research outputs.One institute responded that descriptive reports on scientific activities at departmental level are used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you know of other successful examples of research object tracking?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Positive responses were sparse in this question. The &lt;a href=&quot;https://theplosblog.plos.org/2023/06/open-science-indicators-update-q1-2023/&quot;&gt;PLOS Open Science Indicators&lt;/a&gt; were mentioned and a &lt;a href=&quot;https://fairdashboard.helmholtz-metadaten.de/en/data_in_helmholtz&quot;&gt;FAIR dashboard &lt;/a&gt;was shared. A promising outlook into the future was mentioned where an institute is working on creating a platform to keep track of the research outputs (as well as the Research Data Management &amp;#x26; Open Science compliance documents such as Data Management Plans, Software Management Plans, Privacy and Ethics). In the session slide initiatives such as &lt;a href=&quot;https://quest-dashboard.charite.de/&quot;&gt;Charité Metrics Dashboard&lt;/a&gt;, &lt;a href=&quot;https://frenchopensciencemonitor.esr.gouv.fr/&quot;&gt;French Open Science monitor&lt;/a&gt; and the &lt;a href=&quot;https://open-science-monitoring.org/&quot;&gt;Open Science Monitoring Initiative&lt;/a&gt; were mentioned.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Collaborative initiatives can create a more equitable research assessment framework that recognizes diverse contributions to science. If you’re passionate about advancing Open Science and interested in contributing to similar community projects, consider applying for the &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;eScience Center Fellowship program&lt;/a&gt;. The Fellowship gives researchers and supporters the opportunity to work on technical solutions for open science challenges while collaborating with experts in the field.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-much-research-output-is-really-open--20fe968e.cQyvYruU.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>How is research software managed at UMCs? Insights from a first meetup</title><link>https://blog2.esciencecenter.nl/posts/2024-12-05---how-is-research-software-managed-at-umcs-insights-from-a-fir</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-12-05---how-is-research-software-managed-at-umcs-insights-from-a-fir</guid><description>&lt;p&gt;Written by eScience Center Fellow &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/thomas-pronk/&quot;&gt;Thomas Pronk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On October 7th, 2024, the Digital Competence Centers (DCCs) of the seven Dutch University Medical Centers (UMCs) had a meetup, joined by representatives from Health-RI, ELIXIR-NL, The Netherlands eScience Center, and TDCC-LSH. We discussed Research Software Management (RSM) in the context of Dutch UMCs, identifying shared challenges, opportunities for collaboration, and how we could connect with the broader landscape of organizations, communities, and networks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How is research software managed at UMCs? Insights from a first meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;559&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-is-research-software-managed-at-umcs-df70a4a2.DUuGwGrS_1mHgx2.webp&quot; srcset=&quot;&quot;&gt;
We discussed Research Software Management (RSM) in the context of Dutch UMCs, identifying shared challenges, opportunities for collaboration, and how we could connect with the broader landscape of organizations, communities, and networks.&lt;/p&gt;
&lt;p&gt;Medical research often concerns highly sensitive data and interventions that impact lives. Consequently, we put stringent demands on privacy, security, quality, and reproducibility. In pursuit of meeting these demands, the Dutch UMCs have developed a strong tradition of collaboration and expertise in data stewardship. Our RSM approaches have drawn from these, along with well-established software development practices. However, the institution-wide introduction of RSM policies is relatively new. Correspondingly, RSM at Dutch UMCs is currently at a formative stage. We have the opportunity to jointly address the challenges that come with introducing RSM and we are well-equipped to do so.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How is research software managed at UMCs? Insights from a first meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-is-research-software-managed-at-umcs-39265be3.DxWHpVV5_Z17sfJL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@zhenh2424?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Zhen H&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To get started, we each listed our top three challenges, opportunities, and projects to know about, in a survey. Based on the results, we jointly identified five focus areas in pursuing joint RSM:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Distill guidelines from decentral expertise.** There is already substantial expertise in research software spread out over departments at Dutch UMCs. At the central level, we can learn from this experience to develop good practice guidelines that are attuned with practice, can be developed into policies, and are aligned with national and international efforts such as the&lt;a href=&quot;https://tdcc.nl/projects/tdcc-lsh-project-initiatives/&quot;&gt; TDCC-LSH FAIR Tool framework&lt;/a&gt;,&lt;a href=&quot;https://everse.software/&quot;&gt; EOSC EVERSE&lt;/a&gt; and&lt;a href=&quot;https://openebench.bsc.es/&quot;&gt; OpenEBench&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standardize Software Management Plans (SMPs).&lt;/strong&gt; By working together to standardize on a common format, we can link SMP sections to common support materials and offer default answers based on common best practices. Recognizing the variety of software types and roles, the standard could be made adaptive to its use cases (e.g.,&lt;a href=&quot;https://doi.org/10.5281/zenodo.7248877&quot;&gt; Practical Guide to SMPs&lt;/a&gt;,&lt;a href=&quot;https://smw.dsw.elixir-europe.org/wizard/&quot;&gt; ELIXIR Software Management Wizard&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Develop intermediate-level training.&lt;/strong&gt; Basic research software training can draw from existing initiatives such as those from the eScience Center, LCRDM, and The Carpentries (see&lt;a href=&quot;https://researchsoftwaretraining.nl/resources/&quot;&gt; Research Software Training NL&lt;/a&gt;). However, there is a need for intermediate training that focuses on more advanced skills and best practices adapted to the specific needs of medical research. The intermediate training could take a variety of forms, such as&lt;a href=&quot;https://www.reprohack.org/&quot;&gt; ReproHacks&lt;/a&gt;,&lt;a href=&quot;https://code-cafes-nl.github.io/cafe_playbook/&quot;&gt; Programming CAFEs&lt;/a&gt;, and mentoring schemes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Define research software-related job profiles.&lt;/strong&gt; Embedding RSM on an institutional level requires a range of new roles with well-defined responsibilities. Here, we can draw inspiration from work on Data Stewardship (e.g.,&lt;a href=&quot;https://zenodo.org/records/2669150&quot;&gt; Ingeborg et al., 2019&lt;/a&gt;;&lt;a href=&quot;https://zenodo.org/records/3490855&quot;&gt; Scholtens, 2019&lt;/a&gt;) and Research Software Engineering (e.g., eScience Center RSE&lt;a href=&quot;https://doi.org/10.5281/zenodo.7805870&quot;&gt; Job Role Descriptions&lt;/a&gt; and&lt;a href=&quot;https://zenodo.org/records/7805870&quot;&gt; Job Profiles&lt;/a&gt;,&lt;a href=&quot;https://rsetoolkit.github.io/rse-competencies-toolkit/&quot;&gt; Research Software Competencies Toolkit&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect to national and international networks.&lt;/strong&gt; In pursuit of the above, we seek to align our output with internationally recognized standards, tools, and platforms for (biomedical, life sciences, and health) research software. Natural candidates are offered by our membership of the European ELIXIR network, for instance, the RDM Toolkit&lt;a href=&quot;https://rdmkit.elixir-europe.org/tool_assembly&quot;&gt; tool assemblies&lt;/a&gt; and&lt;a href=&quot;https://rdmkit.elixir-europe.org/nl_resources&quot;&gt; regional resource index&lt;/a&gt;, the ELIXIR&lt;a href=&quot;https://elixir-europe.org/platforms/tools&quot;&gt; Tools Platform&lt;/a&gt;,&lt;a href=&quot;https://tess.elixir-europe.org/&quot;&gt; TeSS training platform,&lt;/a&gt; &lt;a href=&quot;https://everse.software/&quot;&gt;EOSC EVERSE&lt;/a&gt; and&lt;a href=&quot;https://elixir-europe.org/about-us/how-funded/eu-projects/steers&quot;&gt; ELIXIR-STEERS&lt;/a&gt;. Other relevant networks for research software are the national research software engineer (RSE) network (&lt;a href=&quot;https://nl-rse.org/&quot;&gt;NL-RSE&lt;/a&gt;) and the various regional and national &lt;a href=&quot;https://society-rse.org/international-rse-organisations/&quot;&gt;RSE organizations around the globe&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This meeting was made possible by funding from the eScience Center for the Fellowship Project &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/thomas-pronk/&quot;&gt;Implementing software management plans in medical science to improve science and safety*&lt;/a&gt;. If any of the focus areas above strike your fancy, then you might make a great &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;eScience Center Fellow&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 05 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Written by eScience Center Fellow &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/thomas-pronk/&quot;&gt;Thomas Pronk&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On October 7th, 2024, the Digital Competence Centers (DCCs) of the seven Dutch University Medical Centers (UMCs) had a meetup, joined by representatives from Health-RI, ELIXIR-NL, The Netherlands eScience Center, and TDCC-LSH. We discussed Research Software Management (RSM) in the context of Dutch UMCs, identifying shared challenges, opportunities for collaboration, and how we could connect with the broader landscape of organizations, communities, and networks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How is research software managed at UMCs? Insights from a first meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;559&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-is-research-software-managed-at-umcs-df70a4a2.DUuGwGrS_1mHgx2.webp&quot; srcset=&quot;&quot;&gt;
We discussed Research Software Management (RSM) in the context of Dutch UMCs, identifying shared challenges, opportunities for collaboration, and how we could connect with the broader landscape of organizations, communities, and networks.&lt;/p&gt;
&lt;p&gt;Medical research often concerns highly sensitive data and interventions that impact lives. Consequently, we put stringent demands on privacy, security, quality, and reproducibility. In pursuit of meeting these demands, the Dutch UMCs have developed a strong tradition of collaboration and expertise in data stewardship. Our RSM approaches have drawn from these, along with well-established software development practices. However, the institution-wide introduction of RSM policies is relatively new. Correspondingly, RSM at Dutch UMCs is currently at a formative stage. We have the opportunity to jointly address the challenges that come with introducing RSM and we are well-equipped to do so.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How is research software managed at UMCs? Insights from a first meetup&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-is-research-software-managed-at-umcs-39265be3.DxWHpVV5_Z17sfJL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@zhenh2424?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Zhen H&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To get started, we each listed our top three challenges, opportunities, and projects to know about, in a survey. Based on the results, we jointly identified five focus areas in pursuing joint RSM:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Distill guidelines from decentral expertise.** There is already substantial expertise in research software spread out over departments at Dutch UMCs. At the central level, we can learn from this experience to develop good practice guidelines that are attuned with practice, can be developed into policies, and are aligned with national and international efforts such as the&lt;a href=&quot;https://tdcc.nl/projects/tdcc-lsh-project-initiatives/&quot;&gt; TDCC-LSH FAIR Tool framework&lt;/a&gt;,&lt;a href=&quot;https://everse.software/&quot;&gt; EOSC EVERSE&lt;/a&gt; and&lt;a href=&quot;https://openebench.bsc.es/&quot;&gt; OpenEBench&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standardize Software Management Plans (SMPs).&lt;/strong&gt; By working together to standardize on a common format, we can link SMP sections to common support materials and offer default answers based on common best practices. Recognizing the variety of software types and roles, the standard could be made adaptive to its use cases (e.g.,&lt;a href=&quot;https://doi.org/10.5281/zenodo.7248877&quot;&gt; Practical Guide to SMPs&lt;/a&gt;,&lt;a href=&quot;https://smw.dsw.elixir-europe.org/wizard/&quot;&gt; ELIXIR Software Management Wizard&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Develop intermediate-level training.&lt;/strong&gt; Basic research software training can draw from existing initiatives such as those from the eScience Center, LCRDM, and The Carpentries (see&lt;a href=&quot;https://researchsoftwaretraining.nl/resources/&quot;&gt; Research Software Training NL&lt;/a&gt;). However, there is a need for intermediate training that focuses on more advanced skills and best practices adapted to the specific needs of medical research. The intermediate training could take a variety of forms, such as&lt;a href=&quot;https://www.reprohack.org/&quot;&gt; ReproHacks&lt;/a&gt;,&lt;a href=&quot;https://code-cafes-nl.github.io/cafe_playbook/&quot;&gt; Programming CAFEs&lt;/a&gt;, and mentoring schemes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Define research software-related job profiles.&lt;/strong&gt; Embedding RSM on an institutional level requires a range of new roles with well-defined responsibilities. Here, we can draw inspiration from work on Data Stewardship (e.g.,&lt;a href=&quot;https://zenodo.org/records/2669150&quot;&gt; Ingeborg et al., 2019&lt;/a&gt;;&lt;a href=&quot;https://zenodo.org/records/3490855&quot;&gt; Scholtens, 2019&lt;/a&gt;) and Research Software Engineering (e.g., eScience Center RSE&lt;a href=&quot;https://doi.org/10.5281/zenodo.7805870&quot;&gt; Job Role Descriptions&lt;/a&gt; and&lt;a href=&quot;https://zenodo.org/records/7805870&quot;&gt; Job Profiles&lt;/a&gt;,&lt;a href=&quot;https://rsetoolkit.github.io/rse-competencies-toolkit/&quot;&gt; Research Software Competencies Toolkit&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect to national and international networks.&lt;/strong&gt; In pursuit of the above, we seek to align our output with internationally recognized standards, tools, and platforms for (biomedical, life sciences, and health) research software. Natural candidates are offered by our membership of the European ELIXIR network, for instance, the RDM Toolkit&lt;a href=&quot;https://rdmkit.elixir-europe.org/tool_assembly&quot;&gt; tool assemblies&lt;/a&gt; and&lt;a href=&quot;https://rdmkit.elixir-europe.org/nl_resources&quot;&gt; regional resource index&lt;/a&gt;, the ELIXIR&lt;a href=&quot;https://elixir-europe.org/platforms/tools&quot;&gt; Tools Platform&lt;/a&gt;,&lt;a href=&quot;https://tess.elixir-europe.org/&quot;&gt; TeSS training platform,&lt;/a&gt; &lt;a href=&quot;https://everse.software/&quot;&gt;EOSC EVERSE&lt;/a&gt; and&lt;a href=&quot;https://elixir-europe.org/about-us/how-funded/eu-projects/steers&quot;&gt; ELIXIR-STEERS&lt;/a&gt;. Other relevant networks for research software are the national research software engineer (RSE) network (&lt;a href=&quot;https://nl-rse.org/&quot;&gt;NL-RSE&lt;/a&gt;) and the various regional and national &lt;a href=&quot;https://society-rse.org/international-rse-organisations/&quot;&gt;RSE organizations around the globe&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This meeting was made possible by funding from the eScience Center for the Fellowship Project &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/thomas-pronk/&quot;&gt;Implementing software management plans in medical science to improve science and safety*&lt;/a&gt;. If any of the focus areas above strike your fancy, then you might make a great &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;eScience Center Fellow&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-is-research-software-managed-at-umcs-df70a4a2.DUuGwGrS.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Tackling Advent of Code</title><link>https://blog2.esciencecenter.nl/posts/2024-12-03---tackling-advent-of-code</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-12-03---tackling-advent-of-code</guid><description>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/ewan-cahen/&quot;&gt;Ewan Cahen&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://adventofcode.com/2024&quot;&gt;&lt;em&gt;Advent of Code 2024&lt;/em&gt;&lt;/a&gt;* has started this week! If you are not familiar with Advent of Code, it’s an annual coding challenge created by Eric Wastl. It’s like an &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Advent_calendar&quot;&gt;&lt;em&gt;advent calendar&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; for coding challenges containing 25 daily programming puzzles, released once a day between December 1–25. You can still join this year’s edition, and even join our Dutch research community leaderboard when you sign up &lt;em&gt;&lt;a href=&quot;https://forms.office.com/e/fr8wAeNRin&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Tackling Advent of Code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-b3260b36.C86THPBM_2guL0r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@markusspiske?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Markus Spiske&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Whether you’re new to Advent of Code or if you want to brush up on your programming skills, below you can find a list of useful tricks, data structures and algorithms that are often needed when solving the challenges. Some of these are accompanied with links on how to use them in a few popular programming languages.&lt;/p&gt;
&lt;p&gt;Note, the list is rather large. We recommend only picking a few items where you think your knowledge is lacking.&lt;/p&gt;
&lt;h3 id=&quot;parsing-the-input&quot;&gt;Parsing the input**&lt;/h3&gt;
&lt;p&gt;In almost every exercise, you are given input, presented as plain text, that you have to parse (i.e. transform it into some structure that is useful for solving the problem). There are a few techniques you can use to accomplish this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read the input line by line into a list (&lt;a href=&quot;https://www.w3schools.com/python/ref_file_readlines.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://www.statology.org/readlines-in-r/&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://medium.com/@AlexanderObregon/javas-files-readalllines-method-explained-14312314c1c4&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;split a string, useful if data is delimited by e.g. whitespace or a comma (&lt;a href=&quot;https://www.w3schools.com/python/ref_string_split.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://builtin.com/articles/strsplit&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/ref_string_split.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;parsing a string to an integer (&lt;a href=&quot;https://www.w3schools.com/python/ref_func_int.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://stat.ethz.ch/R-manual/R-devel/library/base/html/strtoi.html&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Integer.html#parseInt(java.lang.String)&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;(Java only) use &lt;a href=&quot;https://www.w3schools.com/java/java_user_input.asp&quot;&gt;Java’s Scanner&lt;/a&gt; to easily parse various types of data&lt;/li&gt;
&lt;li&gt;(advanced) use regular expressions to parse the input (&lt;a href=&quot;https://www.w3schools.com/python/python_regex.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://www.datacamp.com/tutorial/regex-r-regular-expressions-guide&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_regex.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Tackling Advent of Code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-f19971cc.7M8QaTuk_ZFVrqi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@chrisliverani?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Chris Liverani&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;integer-division-and-modular-arithmetic&quot;&gt;Integer division and modular arithmetic&lt;/h3&gt;
&lt;p&gt;In Advent of Code, you’ll often have to use integer division (where e.g. &lt;code&gt;11 / 4 = 2&lt;/code&gt; instead of &lt;code&gt;2.75&lt;/code&gt;). For Python, have a look at the &lt;a href=&quot;https://www.learndatasci.com/solutions/python-double-slash-operator-floor-division/&quot;&gt;double slash operator&lt;/a&gt; (&lt;code&gt;//&lt;/code&gt;) and for R use &lt;code&gt;%/%&lt;/code&gt; (see &lt;a href=&quot;https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Operators&quot;&gt;R operators&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;You’ll also have to use modular arithmetic, where you want to know the remainder after integer division (e.g. &lt;code&gt;11 % 4 = 3&lt;/code&gt;, because 4 fits 2 times into 11 and then you have 3 remaining). You’ll use these when, for example, you have to “wrap around” an array, i.e., when you reach the end of an array, you have to return to the start of the array. For Python, use the&lt;a href=&quot;https://realpython.com/python-modulo-operator/&quot;&gt; modulo operator&lt;/a&gt; &lt;code&gt;%&lt;/code&gt;, for R use &lt;code&gt;[%%](https://www.datacamp.com/doc/r/operators)&lt;/code&gt; and for Java use&lt;code&gt;[%](https://www.baeldung.com/modulo-java)&lt;/code&gt;. Also look up how your language behaves when any of the numbers is negative.&lt;/p&gt;
&lt;h3 id=&quot;working-with-large-integers&quot;&gt;Working with large integers&lt;/h3&gt;
&lt;p&gt;Sometimes, you need to handle large integers (especially when multiplying numbers). In some languages, where there are several integer types of several sizes, you need to prevent&lt;a href=&quot;https://www.acunetix.com/blog/web-security-zone/what-is-integer-overflow/&quot;&gt; integer overflow&lt;/a&gt;. This is sometimes a problem when working with &lt;a href=&quot;https://en.wikipedia.org/wiki/32-bit_computing&quot;&gt;32 bit integers&lt;/a&gt;. Usually, using 64 bit integers (keyword: &lt;code&gt;long&lt;/code&gt;) is sufficient for Advent of Code. In Python, this is &lt;a href=&quot;https://docs.python.org/3/c-api/long.html#integer-objects&quot;&gt;not needed&lt;/a&gt;, as it supports arbitrary large integers. For R, have a look at &lt;a href=&quot;https://www.stats.bris.ac.uk/R/web/packages/bit64/index.html&quot;&gt;this package&lt;/a&gt; for 64 bit integers. For Java, use the&lt;a href=&quot;https://www.w3schools.com/java/java_data_types.asp&quot;&gt; long type&lt;/a&gt; or, if that is not sufficient, use the &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/math/BigInteger.html&quot;&gt;BigInteger&lt;/a&gt; class.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Tackling Advent of Code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-72c97208.18Q3hMhL_Z2wONXy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@sortino?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Joshua Sortino&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;data-structures&quot;&gt;Data structures&lt;/h3&gt;
&lt;p&gt;Using the right data structure is crucial to solving the problems. These are the most commonly used ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_arrays.php&quot;&gt;array&lt;/a&gt;: An array is a fixed-size, ordered data structure, consisting of multiple entries of the same type in a row. You can save and retrieve data in an array by using an index (usually a number from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;n — 1&lt;/code&gt; (inclusive) if the array has length n. While Python’s standard library doesn’t have built-in arrays, the &lt;a href=&quot;https://numpy.org/&quot;&gt;NumPy&lt;/a&gt; library provides a powerful array implementation that’s widely considered a de-facto standard for numerical computing in Python. In R, one-dimensional arrays are referred to as vectors, and are indexed starting from &lt;code&gt;1&lt;/code&gt; (so you can index a number from &lt;code&gt;1 to n&lt;/code&gt;). Used when storing data without further requirements or when the order of the data is important. (&lt;a href=&quot;https://www.w3schools.com/r/r_arrays.asp&quot;&gt;R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_arrays.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;list (vector): A data structure that stores multiple entries of (usually) the same type in a row, with dynamic size that grows automatically as needed. While lists offer flexibility, arrays generally provide better performance due to their fixed size and contiguous memory allocation. Arrays are particularly advantageous in Python when using NumPy, as they enable efficient vectorized operations that can significantly speed up numerical computations. Choose arrays when performance and vectorization are priorities, and lists when frequent size changes are required. (&lt;a href=&quot;https://www.w3schools.com/python/python_lists.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/r/r_lists.asp&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_arraylist.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_hashmaps.php&quot;&gt;dictionary/(hash)map&lt;/a&gt;: A data structure that stores key-value pairs. If you want to store/retrieve data by something more complex than an index (as with arrays and lists), like a string, this is the data structure to use. While R does not technically have a dictionary data structure, you can often use a named vector as a quick-and-dirty replacement (&lt;a href=&quot;https://www.w3schools.com/python/python_dictionaries.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://chryswoods.com/beginning_r/dictionaries.html&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_hashmap.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_hashsets.php&quot;&gt;(hash)set&lt;/a&gt;: An unordered data structure that cannot contain duplicates of an element. Useful when you often need to check if some element is present in a data structure (often used in graph traversal algorithms, see below). (&lt;a href=&quot;https://www.w3schools.com/python/python_sets.asp&quot;&gt;Python&lt;/a&gt;, R has external libraries, such as &lt;a href=&quot;https://cran.r-project.org/web/packages/r2r/index.html&quot;&gt;r2r&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_hashset.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_queues.php&quot;&gt;queue&lt;/a&gt;: A first in, first out (FIFO) data structure where elements are added to the end and removed from the front. While Python lists can be used as queues, this is inefficient due to their underlying array implementation — removing from the front requires shifting all remaining elements. For better performance, use Python’s &lt;code&gt;collections.deque&lt;/code&gt; which is optimized for both front and back operations. Lists are better suited as stacks (last in, first out). Queues are commonly used in breadth-first search algorithms in graphs (see section on graphs below). (for&lt;a href=&quot;https://www.w3schools.com/python/python_lists.asp&quot;&gt; Python&lt;/a&gt; and&lt;a href=&quot;https://www.w3schools.com/r/r_lists.asp&quot;&gt; R&lt;/a&gt;, you can use the list as a queue, or you can use &lt;a href=&quot;https://realpython.com/python-deque/&quot;&gt;Python’s deque&lt;/a&gt;,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Queue.html&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_stacks.php&quot;&gt;stack&lt;/a&gt;: A last* in, first out data structure, meaning you can add and/or remove elements to the front of the stack only. Used in &lt;em&gt;depth-first search&lt;/em&gt; algorithms (see below). (see queue for Python and R,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Deque.html&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;(advanced) &lt;a href=&quot;https://www.programiz.com/dsa/priority-queue&quot;&gt;priority queue/heap&lt;/a&gt;: Similar to a queue, except that the elements in the queue have a &lt;em&gt;priority&lt;/em&gt;, and the element with the highest priority will always be served first when retrieving/removing an element, independent of the order in which the elements where added. Used in Dijkstra’s algorithm (see below). (&lt;a href=&quot;https://www.geeksforgeeks.org/heap-queue-or-heapq-in-python/&quot;&gt;Python&lt;/a&gt;, look for external packages for R,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/PriorityQueue.html&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;algorithms&quot;&gt;Algorithms&lt;/h3&gt;
&lt;p&gt;Many problems can be solved with (a variation of) a well known algorithm. Below are listed some commonly needed algorithms for Advent of Code. This is by no means an exhaustive list. Furthermore, you are encouraged to do more research on these algorithms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sorting an array/list: You don’t have to implement your own sorting algorithm, but you have to know how to call the built-in sorting functionality of your language, sometimes using a custom sort function/comparator. (&lt;a href=&quot;https://www.w3schools.com/python/python_lists_sort.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://r-coder.com/sort-r/&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/ref_arrays_sort.asp&quot;&gt; Java arrays&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_sort_list.asp&quot;&gt; Java lists&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Breadth-first_search&quot;&gt;breadth-first search&lt;/a&gt;: An algorithm for finding a node in a graph with a certain property. Used for example when looking for the shortest path between two nodes in a graph, when all edge weights have the same value. This uses a queue.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Depth-first_search&quot;&gt;depth-first search&lt;/a&gt;: An algorithm for finding a node in a graph with a certain property. Used for example when the node(s) you’re looking for in a graph are far away from the starting point. This uses a stack.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_algo_graphs_dijkstra.php&quot;&gt;Dijkstra’s algorithm&lt;/a&gt;: An algorithm for finding a shortest path from a fixed starting point to every other node in a graph, when the edge costs have varying values.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_ref_memoization.php&quot;&gt;memoization&lt;/a&gt;: Not an algorithm, but rather a technique, in which you store (cache) intermediate results so that you don’t have to recompute these over and over again. These intermediate results are usually stored in a dictionary/(hash)map.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;️-closing-words-️&quot;&gt;❄️ Closing words ❄️&lt;/h2&gt;
&lt;p&gt;I hope this overview is useful to you. I’m not that well-versed in the Python or R ecosystem, so if you know of better resources or techniques on any of the topics presented, please let me know.&lt;/p&gt;
&lt;p&gt;Is your favourite technique/algorithm/programming language missing? Feel free to add it below!&lt;/p&gt;
&lt;p&gt;Good luck this year!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Raoul Schram and Bj&lt;/em&gt;ø&lt;em&gt;rn Bartholdy for comments&lt;/em&gt;&lt;/p&gt;</description><pubDate>Tue, 03 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/ewan-cahen/&quot;&gt;Ewan Cahen&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://adventofcode.com/2024&quot;&gt;&lt;em&gt;Advent of Code 2024&lt;/em&gt;&lt;/a&gt;* has started this week! If you are not familiar with Advent of Code, it’s an annual coding challenge created by Eric Wastl. It’s like an &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Advent_calendar&quot;&gt;&lt;em&gt;advent calendar&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; for coding challenges containing 25 daily programming puzzles, released once a day between December 1–25. You can still join this year’s edition, and even join our Dutch research community leaderboard when you sign up &lt;em&gt;&lt;a href=&quot;https://forms.office.com/e/fr8wAeNRin&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Tackling Advent of Code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-b3260b36.C86THPBM_2guL0r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@markusspiske?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Markus Spiske&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Whether you’re new to Advent of Code or if you want to brush up on your programming skills, below you can find a list of useful tricks, data structures and algorithms that are often needed when solving the challenges. Some of these are accompanied with links on how to use them in a few popular programming languages.&lt;/p&gt;
&lt;p&gt;Note, the list is rather large. We recommend only picking a few items where you think your knowledge is lacking.&lt;/p&gt;
&lt;h3 id=&quot;parsing-the-input&quot;&gt;Parsing the input**&lt;/h3&gt;
&lt;p&gt;In almost every exercise, you are given input, presented as plain text, that you have to parse (i.e. transform it into some structure that is useful for solving the problem). There are a few techniques you can use to accomplish this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;read the input line by line into a list (&lt;a href=&quot;https://www.w3schools.com/python/ref_file_readlines.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://www.statology.org/readlines-in-r/&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://medium.com/@AlexanderObregon/javas-files-readalllines-method-explained-14312314c1c4&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;split a string, useful if data is delimited by e.g. whitespace or a comma (&lt;a href=&quot;https://www.w3schools.com/python/ref_string_split.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://builtin.com/articles/strsplit&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/ref_string_split.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;parsing a string to an integer (&lt;a href=&quot;https://www.w3schools.com/python/ref_func_int.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://stat.ethz.ch/R-manual/R-devel/library/base/html/strtoi.html&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Integer.html#parseInt(java.lang.String)&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;(Java only) use &lt;a href=&quot;https://www.w3schools.com/java/java_user_input.asp&quot;&gt;Java’s Scanner&lt;/a&gt; to easily parse various types of data&lt;/li&gt;
&lt;li&gt;(advanced) use regular expressions to parse the input (&lt;a href=&quot;https://www.w3schools.com/python/python_regex.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://www.datacamp.com/tutorial/regex-r-regular-expressions-guide&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_regex.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;Tackling Advent of Code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-f19971cc.7M8QaTuk_ZFVrqi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@chrisliverani?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Chris Liverani&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;integer-division-and-modular-arithmetic&quot;&gt;Integer division and modular arithmetic&lt;/h3&gt;
&lt;p&gt;In Advent of Code, you’ll often have to use integer division (where e.g. &lt;code&gt;11 / 4 = 2&lt;/code&gt; instead of &lt;code&gt;2.75&lt;/code&gt;). For Python, have a look at the &lt;a href=&quot;https://www.learndatasci.com/solutions/python-double-slash-operator-floor-division/&quot;&gt;double slash operator&lt;/a&gt; (&lt;code&gt;//&lt;/code&gt;) and for R use &lt;code&gt;%/%&lt;/code&gt; (see &lt;a href=&quot;https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Operators&quot;&gt;R operators&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;You’ll also have to use modular arithmetic, where you want to know the remainder after integer division (e.g. &lt;code&gt;11 % 4 = 3&lt;/code&gt;, because 4 fits 2 times into 11 and then you have 3 remaining). You’ll use these when, for example, you have to “wrap around” an array, i.e., when you reach the end of an array, you have to return to the start of the array. For Python, use the&lt;a href=&quot;https://realpython.com/python-modulo-operator/&quot;&gt; modulo operator&lt;/a&gt; &lt;code&gt;%&lt;/code&gt;, for R use &lt;code&gt;[%%](https://www.datacamp.com/doc/r/operators)&lt;/code&gt; and for Java use&lt;code&gt;[%](https://www.baeldung.com/modulo-java)&lt;/code&gt;. Also look up how your language behaves when any of the numbers is negative.&lt;/p&gt;
&lt;h3 id=&quot;working-with-large-integers&quot;&gt;Working with large integers&lt;/h3&gt;
&lt;p&gt;Sometimes, you need to handle large integers (especially when multiplying numbers). In some languages, where there are several integer types of several sizes, you need to prevent&lt;a href=&quot;https://www.acunetix.com/blog/web-security-zone/what-is-integer-overflow/&quot;&gt; integer overflow&lt;/a&gt;. This is sometimes a problem when working with &lt;a href=&quot;https://en.wikipedia.org/wiki/32-bit_computing&quot;&gt;32 bit integers&lt;/a&gt;. Usually, using 64 bit integers (keyword: &lt;code&gt;long&lt;/code&gt;) is sufficient for Advent of Code. In Python, this is &lt;a href=&quot;https://docs.python.org/3/c-api/long.html#integer-objects&quot;&gt;not needed&lt;/a&gt;, as it supports arbitrary large integers. For R, have a look at &lt;a href=&quot;https://www.stats.bris.ac.uk/R/web/packages/bit64/index.html&quot;&gt;this package&lt;/a&gt; for 64 bit integers. For Java, use the&lt;a href=&quot;https://www.w3schools.com/java/java_data_types.asp&quot;&gt; long type&lt;/a&gt; or, if that is not sufficient, use the &lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/math/BigInteger.html&quot;&gt;BigInteger&lt;/a&gt; class.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Tackling Advent of Code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-72c97208.18Q3hMhL_Z2wONXy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@sortino?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Joshua Sortino&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;data-structures&quot;&gt;Data structures&lt;/h3&gt;
&lt;p&gt;Using the right data structure is crucial to solving the problems. These are the most commonly used ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_arrays.php&quot;&gt;array&lt;/a&gt;: An array is a fixed-size, ordered data structure, consisting of multiple entries of the same type in a row. You can save and retrieve data in an array by using an index (usually a number from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;n — 1&lt;/code&gt; (inclusive) if the array has length n. While Python’s standard library doesn’t have built-in arrays, the &lt;a href=&quot;https://numpy.org/&quot;&gt;NumPy&lt;/a&gt; library provides a powerful array implementation that’s widely considered a de-facto standard for numerical computing in Python. In R, one-dimensional arrays are referred to as vectors, and are indexed starting from &lt;code&gt;1&lt;/code&gt; (so you can index a number from &lt;code&gt;1 to n&lt;/code&gt;). Used when storing data without further requirements or when the order of the data is important. (&lt;a href=&quot;https://www.w3schools.com/r/r_arrays.asp&quot;&gt;R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_arrays.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;list (vector): A data structure that stores multiple entries of (usually) the same type in a row, with dynamic size that grows automatically as needed. While lists offer flexibility, arrays generally provide better performance due to their fixed size and contiguous memory allocation. Arrays are particularly advantageous in Python when using NumPy, as they enable efficient vectorized operations that can significantly speed up numerical computations. Choose arrays when performance and vectorization are priorities, and lists when frequent size changes are required. (&lt;a href=&quot;https://www.w3schools.com/python/python_lists.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/r/r_lists.asp&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_arraylist.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_hashmaps.php&quot;&gt;dictionary/(hash)map&lt;/a&gt;: A data structure that stores key-value pairs. If you want to store/retrieve data by something more complex than an index (as with arrays and lists), like a string, this is the data structure to use. While R does not technically have a dictionary data structure, you can often use a named vector as a quick-and-dirty replacement (&lt;a href=&quot;https://www.w3schools.com/python/python_dictionaries.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://chryswoods.com/beginning_r/dictionaries.html&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_hashmap.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_hashsets.php&quot;&gt;(hash)set&lt;/a&gt;: An unordered data structure that cannot contain duplicates of an element. Useful when you often need to check if some element is present in a data structure (often used in graph traversal algorithms, see below). (&lt;a href=&quot;https://www.w3schools.com/python/python_sets.asp&quot;&gt;Python&lt;/a&gt;, R has external libraries, such as &lt;a href=&quot;https://cran.r-project.org/web/packages/r2r/index.html&quot;&gt;r2r&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_hashset.asp&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_queues.php&quot;&gt;queue&lt;/a&gt;: A first in, first out (FIFO) data structure where elements are added to the end and removed from the front. While Python lists can be used as queues, this is inefficient due to their underlying array implementation — removing from the front requires shifting all remaining elements. For better performance, use Python’s &lt;code&gt;collections.deque&lt;/code&gt; which is optimized for both front and back operations. Lists are better suited as stacks (last in, first out). Queues are commonly used in breadth-first search algorithms in graphs (see section on graphs below). (for&lt;a href=&quot;https://www.w3schools.com/python/python_lists.asp&quot;&gt; Python&lt;/a&gt; and&lt;a href=&quot;https://www.w3schools.com/r/r_lists.asp&quot;&gt; R&lt;/a&gt;, you can use the list as a queue, or you can use &lt;a href=&quot;https://realpython.com/python-deque/&quot;&gt;Python’s deque&lt;/a&gt;,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Queue.html&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_data_stacks.php&quot;&gt;stack&lt;/a&gt;: A last* in, first out data structure, meaning you can add and/or remove elements to the front of the stack only. Used in &lt;em&gt;depth-first search&lt;/em&gt; algorithms (see below). (see queue for Python and R,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Deque.html&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;(advanced) &lt;a href=&quot;https://www.programiz.com/dsa/priority-queue&quot;&gt;priority queue/heap&lt;/a&gt;: Similar to a queue, except that the elements in the queue have a &lt;em&gt;priority&lt;/em&gt;, and the element with the highest priority will always be served first when retrieving/removing an element, independent of the order in which the elements where added. Used in Dijkstra’s algorithm (see below). (&lt;a href=&quot;https://www.geeksforgeeks.org/heap-queue-or-heapq-in-python/&quot;&gt;Python&lt;/a&gt;, look for external packages for R,&lt;a href=&quot;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/PriorityQueue.html&quot;&gt; Java&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;algorithms&quot;&gt;Algorithms&lt;/h3&gt;
&lt;p&gt;Many problems can be solved with (a variation of) a well known algorithm. Below are listed some commonly needed algorithms for Advent of Code. This is by no means an exhaustive list. Furthermore, you are encouraged to do more research on these algorithms.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sorting an array/list: You don’t have to implement your own sorting algorithm, but you have to know how to call the built-in sorting functionality of your language, sometimes using a custom sort function/comparator. (&lt;a href=&quot;https://www.w3schools.com/python/python_lists_sort.asp&quot;&gt;Python&lt;/a&gt;,&lt;a href=&quot;https://r-coder.com/sort-r/&quot;&gt; R&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/ref_arrays_sort.asp&quot;&gt; Java arrays&lt;/a&gt;,&lt;a href=&quot;https://www.w3schools.com/java/java_sort_list.asp&quot;&gt; Java lists&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Breadth-first_search&quot;&gt;breadth-first search&lt;/a&gt;: An algorithm for finding a node in a graph with a certain property. Used for example when looking for the shortest path between two nodes in a graph, when all edge weights have the same value. This uses a queue.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Depth-first_search&quot;&gt;depth-first search&lt;/a&gt;: An algorithm for finding a node in a graph with a certain property. Used for example when the node(s) you’re looking for in a graph are far away from the starting point. This uses a stack.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_algo_graphs_dijkstra.php&quot;&gt;Dijkstra’s algorithm&lt;/a&gt;: An algorithm for finding a shortest path from a fixed starting point to every other node in a graph, when the edge costs have varying values.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/dsa/dsa_ref_memoization.php&quot;&gt;memoization&lt;/a&gt;: Not an algorithm, but rather a technique, in which you store (cache) intermediate results so that you don’t have to recompute these over and over again. These intermediate results are usually stored in a dictionary/(hash)map.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;️-closing-words-️&quot;&gt;❄️ Closing words ❄️&lt;/h2&gt;
&lt;p&gt;I hope this overview is useful to you. I’m not that well-versed in the Python or R ecosystem, so if you know of better resources or techniques on any of the topics presented, please let me know.&lt;/p&gt;
&lt;p&gt;Is your favourite technique/algorithm/programming language missing? Feel free to add it below!&lt;/p&gt;
&lt;p&gt;Good luck this year!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Raoul Schram and Bj&lt;/em&gt;ø&lt;em&gt;rn Bartholdy for comments&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/tackling-advent-of-code-b3260b36.C86THPBM.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>The ‘do-it-yourself’ Computed Tomography scanner</title><link>https://blog2.esciencecenter.nl/posts/2024-12-03---the-do-it-yourself-computed-tomography-scanner</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-12-03---the-do-it-yourself-computed-tomography-scanner</guid><description>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/francien-bossema/&quot;&gt;Francien Bossema&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Researchers developed a method to use existing X-ray imaging facilities for Computed Tomography (CT) scanning&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;598&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-69f18984.CF1BWYP4_Z2chW3l.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@socalcaral?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Cara Shelton&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a cross-post from our fellow &lt;a href=&quot;https://www.linkedin.com/in/francien-bossema-a587b012a/&quot;&gt;Dr. Francien Bossema&lt;/a&gt;. Originally published on the &lt;a href=&quot;https://www.cwi.nl/en/news/the-do-it-yourself-ct-scanner/&quot;&gt;CWI website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;More information on our Fellowship programme &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;What if you could saw a wooden sculpture through to look at the tree rings? Could a clay sculpture be hollow? What type of instruments were used to craft art objects? These questions could be answered by X-ray imaging. In particular, CT-scans are useful to investigate historical art objects on the inside. The CT-scans that are suitable for this application are however not easily accessible for researchers and quite expensive to acquire. An international team of researchers led by CWI, the Dutch national research center for mathematics and computer science, has therefore developed a method to use existing X-ray imaging facilities for CT scanning. The results have been published &lt;a href=&quot;https://www.nature.com/articles/s41467-024-48102-w&quot;&gt;on the 14th of May in Nature Communications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Research facilities of large museums, such as the Rijksmuseum in Amsterdam, often house an X-ray imaging machine, with which they can perform live inspection of objects. This works in the same way as when you have to have an X-ray image taken at the hospital because of a broken bone. On such an image the bone can be seen, because it has a higher density than the muscles and tissue surrounding it. Usually, a few images are taken, so that the fracture can be inspected from different sides. For more complex problems, a CT scan is made. The technique behind CT scans is similar to X-ray images. For a CT scan hundreds of X-ray images are taken from different angles and then combined into a 3D image using reconstruction algorithms. This 3D image can then be ‘sliced open’ to obtain cross sections showing the interior.&lt;/p&gt;
&lt;p&gt;Over the past years, this technique has been increasingly applied to art objects, because it gives the possibility to investigate the interior without damaging the object. It is possible to date wooden objects by looking at the tree rings, assess the internal damage by an insect infestation or search for clues about the techniques used by the artist.&lt;/p&gt;
&lt;h2 id=&quot;no-ct-scanner-no-problem&quot;&gt;No CT scanner? No problem!&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;559&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-7f9418ba.CA__ftPK_c8ACr.webp&quot; srcset=&quot;&quot;&gt;
CT scans provide more information than X-ray images. In museums, however, simple X-ray imaging setups are more common. The components of the machine are similar (an X-ray tube, rotation stage and a detector), but for a CT scan the positions of these components during the scan need to be known very accurately. The researchers from CWI have therefore developed a method to calculate these positions after a data acquisition, with nothing more than a few small metal balls. These balls are put in a piece of foam and scanned alongside the object. Based on the location of the balls on the X-ray images, all the necessary positions can be calculated. These are then used to obtain a CT-scan.&lt;/p&gt;
&lt;p&gt;This unique project is a collaboration between a team of international researchers from CWI (Amsterdam), Leiden Institute of Advanced Computer Science (Leiden), Rijksmuseum (Amsterdam), The British Museum (London, UK) and the J. Paul Getty Museum (Los Angeles, USA). The X-ray imaging facilities of each of these museums, as well as the FleX-ray laboratory at CWI, have been used to test the new method and compare results in different facilities. The X-ray setups at the Rijksmuseum and the J. Paul Getty museum have been used for CT scans for the first time.&lt;/p&gt;
&lt;p&gt;The first author of the associated Nature Communications article &lt;a href=&quot;https://www.cwi.nl/en/people/francien-bossema/&quot;&gt;Francien Bossema&lt;/a&gt; will defend her PhD thesis at Leiden University on the topic of CT scanning for cultural heritage on the 23rd of May.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can do something that was not possible before. CT scanning is an important imaging method for museums, because researchers can digitally cut open an object without damaging it. Our method makes it possible to further integrate this technique into research practices in the museum, without obtaining new hardware. We only use small metal balls of the type you also have in the pedals of your bike and algorithms specifically designed for this purpose. This means no extra investments are needed, while still providing an additional imaging technique.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Francien Bossema, CWI&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;new-method-gives-insights-into-the-making-process-of-a-sculpture&quot;&gt;New method gives insights into the making process of a sculpture&lt;/h2&gt;
&lt;p&gt;After the development of this technique, a sculpture made of plaster from the J. Paul Getty Museum was studied: &lt;em&gt;Python Killing a Gnu&lt;/em&gt;, by Antoine-Louis Barye (J. Paul Getty Museum, 85.SE.48). The sculpture originally had a different configuration, it was smaller and more compact because it was initially used as a model for a group of sculptures that was displayed on a dining table. The artist later decided to change the model to open and enlarge the arrangement and turn it into a stand-alone sculpture. The possibility to CT-scan the object was welcomed by the conservator who was investigating this object, Madeline Corona (Getty Museum): ‘On the X-ray images, we could see that areas had been broken, altered, and filled but it was difficult to understand exactly how the artist made these changes because there were too many overlapping features. The CT-scan gave us an incredible opportunity to obtain clearer and more detailed images of these areas of change. In the end, it provided important insights that allowed us to confirm some of our hypotheses about Barye’s working methods, something we could not have done without this technique.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-db1b697e.C0e1gOve_Z2g08pl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;326&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-66c789e0.BgsP8rXT_Z2vQbdT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information&quot;&gt;More information&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Article &lt;a href=&quot;https://www.nature.com/articles/s41467-024-48102-w&quot;&gt;&lt;em&gt;Enabling 3D CT-scanning of cultural heritage objects using only in-house 2D X-ray equipment in museums&lt;/em&gt;&lt;/a&gt; in Nature Communications 14 May 2024.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/people/francien-bossema/&quot;&gt;Francien Bossema&lt;/a&gt; (CWI/Rijksmuseum), &lt;a href=&quot;mailto:bossema@cwi.nl&quot;&gt;bossema@cwi.nl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/people/joost-batenburg/&quot;&gt;Prof. dr. Joost Batenburg&lt;/a&gt; (LIACS), &lt;a href=&quot;mailto:k.j.batenburg@liacs.leidenuniv.nl&quot;&gt;k.j.batenburg@liacs.leidenuniv.nl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.getty.edu/author/corona-madeline/&quot;&gt;Madeline Corona&lt;/a&gt; (Getty Museum), &lt;a href=&quot;mailto:MCorona@getty.edu&quot;&gt;MCorona@getty.edu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/collaboration/labs/flex-ray-lab/&quot;&gt;FleX-ray CT lab at CWI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/groups/computational-imaging/&quot;&gt;Computational Imaging group at CWI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Tue, 03 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/francien-bossema/&quot;&gt;Francien Bossema&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Researchers developed a method to use existing X-ray imaging facilities for Computed Tomography (CT) scanning&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;598&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-69f18984.CF1BWYP4_Z2chW3l.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@socalcaral?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Cara Shelton&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a cross-post from our fellow &lt;a href=&quot;https://www.linkedin.com/in/francien-bossema-a587b012a/&quot;&gt;Dr. Francien Bossema&lt;/a&gt;. Originally published on the &lt;a href=&quot;https://www.cwi.nl/en/news/the-do-it-yourself-ct-scanner/&quot;&gt;CWI website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;More information on our Fellowship programme &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;What if you could saw a wooden sculpture through to look at the tree rings? Could a clay sculpture be hollow? What type of instruments were used to craft art objects? These questions could be answered by X-ray imaging. In particular, CT-scans are useful to investigate historical art objects on the inside. The CT-scans that are suitable for this application are however not easily accessible for researchers and quite expensive to acquire. An international team of researchers led by CWI, the Dutch national research center for mathematics and computer science, has therefore developed a method to use existing X-ray imaging facilities for CT scanning. The results have been published &lt;a href=&quot;https://www.nature.com/articles/s41467-024-48102-w&quot;&gt;on the 14th of May in Nature Communications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Research facilities of large museums, such as the Rijksmuseum in Amsterdam, often house an X-ray imaging machine, with which they can perform live inspection of objects. This works in the same way as when you have to have an X-ray image taken at the hospital because of a broken bone. On such an image the bone can be seen, because it has a higher density than the muscles and tissue surrounding it. Usually, a few images are taken, so that the fracture can be inspected from different sides. For more complex problems, a CT scan is made. The technique behind CT scans is similar to X-ray images. For a CT scan hundreds of X-ray images are taken from different angles and then combined into a 3D image using reconstruction algorithms. This 3D image can then be ‘sliced open’ to obtain cross sections showing the interior.&lt;/p&gt;
&lt;p&gt;Over the past years, this technique has been increasingly applied to art objects, because it gives the possibility to investigate the interior without damaging the object. It is possible to date wooden objects by looking at the tree rings, assess the internal damage by an insect infestation or search for clues about the techniques used by the artist.&lt;/p&gt;
&lt;h2 id=&quot;no-ct-scanner-no-problem&quot;&gt;No CT scanner? No problem!&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;559&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-7f9418ba.CA__ftPK_c8ACr.webp&quot; srcset=&quot;&quot;&gt;
CT scans provide more information than X-ray images. In museums, however, simple X-ray imaging setups are more common. The components of the machine are similar (an X-ray tube, rotation stage and a detector), but for a CT scan the positions of these components during the scan need to be known very accurately. The researchers from CWI have therefore developed a method to calculate these positions after a data acquisition, with nothing more than a few small metal balls. These balls are put in a piece of foam and scanned alongside the object. Based on the location of the balls on the X-ray images, all the necessary positions can be calculated. These are then used to obtain a CT-scan.&lt;/p&gt;
&lt;p&gt;This unique project is a collaboration between a team of international researchers from CWI (Amsterdam), Leiden Institute of Advanced Computer Science (Leiden), Rijksmuseum (Amsterdam), The British Museum (London, UK) and the J. Paul Getty Museum (Los Angeles, USA). The X-ray imaging facilities of each of these museums, as well as the FleX-ray laboratory at CWI, have been used to test the new method and compare results in different facilities. The X-ray setups at the Rijksmuseum and the J. Paul Getty museum have been used for CT scans for the first time.&lt;/p&gt;
&lt;p&gt;The first author of the associated Nature Communications article &lt;a href=&quot;https://www.cwi.nl/en/people/francien-bossema/&quot;&gt;Francien Bossema&lt;/a&gt; will defend her PhD thesis at Leiden University on the topic of CT scanning for cultural heritage on the 23rd of May.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can do something that was not possible before. CT scanning is an important imaging method for museums, because researchers can digitally cut open an object without damaging it. Our method makes it possible to further integrate this technique into research practices in the museum, without obtaining new hardware. We only use small metal balls of the type you also have in the pedals of your bike and algorithms specifically designed for this purpose. This means no extra investments are needed, while still providing an additional imaging technique.*&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Francien Bossema, CWI&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;new-method-gives-insights-into-the-making-process-of-a-sculpture&quot;&gt;New method gives insights into the making process of a sculpture&lt;/h2&gt;
&lt;p&gt;After the development of this technique, a sculpture made of plaster from the J. Paul Getty Museum was studied: &lt;em&gt;Python Killing a Gnu&lt;/em&gt;, by Antoine-Louis Barye (J. Paul Getty Museum, 85.SE.48). The sculpture originally had a different configuration, it was smaller and more compact because it was initially used as a model for a group of sculptures that was displayed on a dining table. The artist later decided to change the model to open and enlarge the arrangement and turn it into a stand-alone sculpture. The possibility to CT-scan the object was welcomed by the conservator who was investigating this object, Madeline Corona (Getty Museum): ‘On the X-ray images, we could see that areas had been broken, altered, and filled but it was difficult to understand exactly how the artist made these changes because there were too many overlapping features. The CT-scan gave us an incredible opportunity to obtain clearer and more detailed images of these areas of change. In the end, it provided important insights that allowed us to confirm some of our hypotheses about Barye’s working methods, something we could not have done without this technique.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-db1b697e.C0e1gOve_Z2g08pl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The ‘do-it-yourself’ Computed Tomography scanner&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;326&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-66c789e0.BgsP8rXT_Z2vQbdT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information&quot;&gt;More information&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Article &lt;a href=&quot;https://www.nature.com/articles/s41467-024-48102-w&quot;&gt;&lt;em&gt;Enabling 3D CT-scanning of cultural heritage objects using only in-house 2D X-ray equipment in museums&lt;/em&gt;&lt;/a&gt; in Nature Communications 14 May 2024.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/people/francien-bossema/&quot;&gt;Francien Bossema&lt;/a&gt; (CWI/Rijksmuseum), &lt;a href=&quot;mailto:bossema@cwi.nl&quot;&gt;bossema@cwi.nl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/people/joost-batenburg/&quot;&gt;Prof. dr. Joost Batenburg&lt;/a&gt; (LIACS), &lt;a href=&quot;mailto:k.j.batenburg@liacs.leidenuniv.nl&quot;&gt;k.j.batenburg@liacs.leidenuniv.nl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.getty.edu/author/corona-madeline/&quot;&gt;Madeline Corona&lt;/a&gt; (Getty Museum), &lt;a href=&quot;mailto:MCorona@getty.edu&quot;&gt;MCorona@getty.edu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/collaboration/labs/flex-ray-lab/&quot;&gt;FleX-ray CT lab at CWI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cwi.nl/en/groups/computational-imaging/&quot;&gt;Computational Imaging group at CWI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/the-do-it-yourself-computed-tomography-s-7f9418ba.CA__ftPK.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Is scientific software the new land grab?</title><link>https://blog2.esciencecenter.nl/posts/2024-11-27---is-scientific-software-the-new-land-grab</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-11-27---is-scientific-software-the-new-land-grab</guid><description>&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;Scientific software platforms are not always as open as they look at first sight. Avoid getting locked in with this advice!&lt;/p&gt;
&lt;p&gt;“Do you know what CodeOcean is? Should I do this?” As a Research Software Engineer you often advise on all sorts of stuff, but I hadn’t heard this one before. In this case from a professor I work with, who’d sent a paper to Nature (as you do) and was asked by the editor to put the corresponding code in “CodeOcean”. Do I have an opinion on this?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-d0106fc2.-gtIOeaw_1S2f01.webp&quot; srcset=&quot;&quot;&gt;
You mean this could be my office? Photo by &lt;a href=&quot;https://unsplash.com/@oulashin?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Sean Oulashin&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;I’d never heard of CodeOcean. Data lakes, yes, and Wind River Systems, but CodeOcean? Never heard of. Fortunately, a web search found it quickly. I started reading.&lt;/p&gt;
&lt;p&gt;CodeOcean is a cloud-based workflow execution and data storage platform. You can make an account, and then upload your scientific data and scripts into the system. Because the script is in containers in the cloud, the script’s environment never changes, so it will always run and your research will be easily reproducible by other researchers, who will be able to comfortably find it when they next log in. You and others can then compose &lt;em&gt;workflows&lt;/em&gt;, step-by-step procedures for processing data, using your own software and that of others.&lt;/p&gt;
&lt;p&gt;Sounds great, right?&lt;/p&gt;
&lt;p&gt;Well, not to me actually, for reasons practical but mostly political. Let’s have a look at what’s really going on here.&lt;/p&gt;
&lt;h2 id=&quot;reproducing-and-reusing&quot;&gt;Reproducing and reusing&lt;/h2&gt;
&lt;p&gt;First, workflows. Workflows have been around for a long time. The idea of a workflow is that you can use a graphical editor to click together a series of steps that the computer is to perform, so that you can do custom processing without having to learn programming.&lt;/p&gt;
&lt;p&gt;This sounds nice in theory, but has its limitations. Steps can only be combined by feeding output from one step into the next. This is done through files, which is slow, and it’s limited in that you cannot send data back and forth between different programs.&lt;/p&gt;
&lt;p&gt;Graphical, drag-and-drop approaches, while easy to understand at first, quickly become overly complex in real-world scenarios. Because of this, scripting, where you describe what you want in text, is more popular and increasingly widely taught at universities. So a workflow system is not necessarily what people actually need, even if it looks good on screen.&lt;/p&gt;
&lt;p&gt;Furthermore, the story above cuts some corners. Reproducibility is not the same as reusability, and a script is not the same as a reusable software package. Putting your script in the system and getting it into a container and running is probably doable in most cases, and will create reproducibility, at least for a while depending on how complicated the thing is you’re trying to do.&lt;/p&gt;
&lt;p&gt;Science is more than just reproducing results though. We want to build on them, and we don’t want to have to re-implement everything that has already been researched. Instead, we’d like to reuse the work of our predecessors, so that we can get started right away. So we need &lt;em&gt;reusability&lt;/em&gt; as well as reproducibility.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;We need reusability as well as reproducibility&lt;/p&gt;
&lt;p&gt;For reusability to work, a lot more work is needed. Researchers will have to convert their script, which is designed to run just once, on specific input data, with its author at hand to handle any issues as they arise, into a reusable workflow step that can run many times, handle a range of inputs, and solve any issues by itself or at least give an error that is understandable by someone who doesn’t know the software. This is a lot of work, and it takes a lot more skill and experience than creating a script.&lt;/p&gt;
&lt;p&gt;Setting up a workflow system in the cloud is one thing (especially if you pull a ready-made Open Source one off the Internet, as CodeOcean has to their credit done), but it needs to be populated with reusable software to be a useful workflow development platform, and that is difficult and time-consuming.&lt;/p&gt;
&lt;p&gt;So, will a system like this actually be useful? We have some existing workflow systems in science that are well used in particular communities, like &lt;a href=&quot;https://en.wikipedia.org/wiki/KNIME&quot;&gt;KNIME&lt;/a&gt;, so it’ll likely be of some use, but I don’t see this being the great solution to reusing scientific software. I do see something else, however: lock-in.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-420cacda.BYhmxsm-_ZLWveT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@reskp?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Jametlene Reskp&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-next-landgrab&quot;&gt;The next landgrab&lt;/h2&gt;
&lt;p&gt;CodeOcean claim that their platform is open. You can put your software and data on there, and everyone else can download it. And since the workflow engine they use, Apache Airflow, is Open Source, you may even be able to use the downloaded bits to put together a workflow locally.&lt;/p&gt;
&lt;p&gt;Doing that in practice is going to be quite a bit of work, and unlike with other repositories you need an account just to download anything. So there’s a network effect here: if most of the data and software you want is on this platform, then adding the rest is easier than getting the data and software out and running somewhere else.&lt;/p&gt;
&lt;p&gt;The login requirement also raises a barrier: I can easily grab data from a public server from a script, but with CodeOcean I have to go to my browser and do it by hand. Unless of course, I put my script into their platform.&lt;/p&gt;
&lt;p&gt;For a workflow platform like this to be truly open, it would have to be able to use data sets and compute steps from other platforms in its workflows, and allow other platforms (or local scripts) to use data and steps available on it. That would leave users free to choose any platform (or their own laptop) to put their data and software on, as well as to compose workflows on, because it ensures that we all can work together regardless of which product we choose to use.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The downside of a federated system is that it’s more difficult to make money off of it.&lt;/p&gt;
&lt;p&gt;The downside of a federated system is that it’s more difficult to make money off of it. Without a network effect, multiple providers could compete, and users would be free to switch. Such a free market would reduce prices, and that would be good for us eternally cash-strapped scientists, but investors in these companies would get less profit.&lt;/p&gt;
&lt;p&gt;So, if I ran a company like CodeOcean and wanted to make good money, I’d do something else. I’d require people to sign up to use the service, I would make it so that you could only combine data and software from different sources if all the data and all the software is in my system, and then I would make deals with some high-ranking journals to get them to push scientists to put their data and software on my platform.&lt;/p&gt;
&lt;p&gt;Other scientists are likely to want to use those high-profile data sets and software modules, and to do so, I’d make them sign up first. I would then design my user interface to push people towards using the data and software on my site, rather than downloading them and using them locally.&lt;/p&gt;
&lt;p&gt;They’d add their software and data to my platform, this being easier than getting things to run on their own computers, which encourages others to join as well, and the whole thing will snowball.&lt;/p&gt;
&lt;p&gt;Then, having obtained many users, I would have a look at the email addresses with which they signed up. I’d contact the universities they work for, and explain politely that many of their employees are using my service. I’d tell them that free accounts are going to go away, and that the university will have to pay an annual fee.&lt;/p&gt;
&lt;p&gt;If they refuse, I’d block their scientists from my platform. The scientists would then protest their university administration because, without their data and software, they cannot work. The university would then pay me, I’d re-enable access, and subsequently retire to a tropical beach to sip cocktails and add more features to my scientific software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;861&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-53a82e4a.BuANbNvh_ZDhgk3.webp&quot; srcset=&quot;&quot;&gt;
I’ll need to order a cup holder for my laptop… Photo by &lt;a href=&quot;https://unsplash.com/@whitney_wright?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Whitney Wright&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;déja-vu&quot;&gt;Déja vu&lt;/h2&gt;
&lt;p&gt;Am I a brilliant business strategist? Of course not. This business model, in which society pays people with public money to produce scientific output, which is then appropriated by a commercial platform and sold back to the public, is what Open Access has fought hard against.&lt;/p&gt;
&lt;p&gt;It’s taken a long time to get to a point where we are now mostly publishing Open Access (even in Nature, if you’re rich), and much of our publicly funded work is still locked away behind paywalls, but overall I’d say it’s been a success. That doesn’t deter people from trying to pull us back into the same trap however, this time for data and software. Instead of fighting our way out, maybe this time we should avoid falling into it in the first place.&lt;/p&gt;
&lt;p&gt;The good news is, we can! Instead of putting your data set on CodeOcean or a similar locked-in platform, put it on &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt; or &lt;a href=&quot;https://figshare.com/&quot;&gt;Figshare&lt;/a&gt;. These platforms allow anyone to download your data without an account, enabling them to use it anywhere. Scripts can go there too, and like data, they’ll get a DOI so that you can refer to them from your Open Access paper.&lt;/p&gt;
&lt;p&gt;No one installs reusable software from Zenodo, so if you make a reusable program then it’s best to publish it to the standard repository for the programming language you’re using. Python should go on PyPI and into conda-forge, the latter is also good for packages in C, C++, and Fortran, and Julia, Rust, R, and Java all have their standard places too.&lt;/p&gt;
&lt;p&gt;These repositories are open, allowing anyone to install and use your software anywhere without getting locked into something. For development, you can use GitLab (your own or one in the cloud) or GitHub, which also allows anyone to clone your repository without signing up or putting their own software in there.&lt;/p&gt;
&lt;p&gt;Of course running these platforms isn’t free. Zenodo is paid for by CERN, the particle physics lab in Switzerland. Figshare is run by a company. The conda package manager is mostly developed by Anaconda Inc. (another company), conda-forge runs on spare cloud resources donated by Microsoft, GitHub is owned by Microsoft and GitLab is run by the company with the same name.&lt;/p&gt;
&lt;p&gt;The difference is that conda is open source and so are conda-forge’s scripts and bots, and that git is an independent open source program, so that I can trivially clone a git repository off of GitHub and push it onto GitLab or vice versa.&lt;/p&gt;
&lt;p&gt;Issues and pull requests are harder to move, and there is somewhat of a network effect on these latter platforms for developers, who need to have an account for security reasons, but you don’t get locked in just to run anything, and it’s still easy to combine software and data from different sources.&lt;/p&gt;
&lt;p&gt;Sometimes it’s useful to put something in the cloud. Scientific software is often poorly engineered and difficult to install, and it can be nice to share an entire pre-installed environment sometimes, for demonstration purposes for example.&lt;/p&gt;
&lt;p&gt;If that’s what you want, go talk to your academic computing center! SURF for example here in The Netherlands have the &lt;a href=&quot;https://www.surf.nl/en/services/surf-research-cloud&quot;&gt;SURF Research Cloud&lt;/a&gt;, an environment in which you can create virtual machine images with your software, which other people can then run and use on SURF infrastructure.&lt;/p&gt;
&lt;p&gt;This does require an account (a standard SURFconext one that you use for their other services too), but at least it’s an account with a not-for-profit whose task it is to provide these resources to scientists. In short, SURF are working for you, not for a return on investment.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-a2a5337a.BLFLgvCk_qumPd.webp&quot; srcset=&quot;&quot;&gt;
Example of a researcher using the SURF Research Cloud. Photo by &lt;a href=&quot;https://unsplash.com/@timmossholder?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Tim Mossholder&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-short&quot;&gt;In short&lt;/h2&gt;
&lt;p&gt;If someone invites you to put your scientific software onto their platform then you should have a good look first to see what this platform is for. Is this publicly funded infrastructure set up to make science more open and to support open collaboration? Then go right ahead. Is it commercial? Then it could still be okay, if it’s open enough. But beware of companies trying to appropriate your publicly funded work. We don’t need to fall into that trap again.&lt;/p&gt;</description><pubDate>Wed, 27 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;Scientific software platforms are not always as open as they look at first sight. Avoid getting locked in with this advice!&lt;/p&gt;
&lt;p&gt;“Do you know what CodeOcean is? Should I do this?” As a Research Software Engineer you often advise on all sorts of stuff, but I hadn’t heard this one before. In this case from a professor I work with, who’d sent a paper to Nature (as you do) and was asked by the editor to put the corresponding code in “CodeOcean”. Do I have an opinion on this?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-d0106fc2.-gtIOeaw_1S2f01.webp&quot; srcset=&quot;&quot;&gt;
You mean this could be my office? Photo by &lt;a href=&quot;https://unsplash.com/@oulashin?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Sean Oulashin&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;I’d never heard of CodeOcean. Data lakes, yes, and Wind River Systems, but CodeOcean? Never heard of. Fortunately, a web search found it quickly. I started reading.&lt;/p&gt;
&lt;p&gt;CodeOcean is a cloud-based workflow execution and data storage platform. You can make an account, and then upload your scientific data and scripts into the system. Because the script is in containers in the cloud, the script’s environment never changes, so it will always run and your research will be easily reproducible by other researchers, who will be able to comfortably find it when they next log in. You and others can then compose &lt;em&gt;workflows&lt;/em&gt;, step-by-step procedures for processing data, using your own software and that of others.&lt;/p&gt;
&lt;p&gt;Sounds great, right?&lt;/p&gt;
&lt;p&gt;Well, not to me actually, for reasons practical but mostly political. Let’s have a look at what’s really going on here.&lt;/p&gt;
&lt;h2 id=&quot;reproducing-and-reusing&quot;&gt;Reproducing and reusing&lt;/h2&gt;
&lt;p&gt;First, workflows. Workflows have been around for a long time. The idea of a workflow is that you can use a graphical editor to click together a series of steps that the computer is to perform, so that you can do custom processing without having to learn programming.&lt;/p&gt;
&lt;p&gt;This sounds nice in theory, but has its limitations. Steps can only be combined by feeding output from one step into the next. This is done through files, which is slow, and it’s limited in that you cannot send data back and forth between different programs.&lt;/p&gt;
&lt;p&gt;Graphical, drag-and-drop approaches, while easy to understand at first, quickly become overly complex in real-world scenarios. Because of this, scripting, where you describe what you want in text, is more popular and increasingly widely taught at universities. So a workflow system is not necessarily what people actually need, even if it looks good on screen.&lt;/p&gt;
&lt;p&gt;Furthermore, the story above cuts some corners. Reproducibility is not the same as reusability, and a script is not the same as a reusable software package. Putting your script in the system and getting it into a container and running is probably doable in most cases, and will create reproducibility, at least for a while depending on how complicated the thing is you’re trying to do.&lt;/p&gt;
&lt;p&gt;Science is more than just reproducing results though. We want to build on them, and we don’t want to have to re-implement everything that has already been researched. Instead, we’d like to reuse the work of our predecessors, so that we can get started right away. So we need &lt;em&gt;reusability&lt;/em&gt; as well as reproducibility.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;We need reusability as well as reproducibility&lt;/p&gt;
&lt;p&gt;For reusability to work, a lot more work is needed. Researchers will have to convert their script, which is designed to run just once, on specific input data, with its author at hand to handle any issues as they arise, into a reusable workflow step that can run many times, handle a range of inputs, and solve any issues by itself or at least give an error that is understandable by someone who doesn’t know the software. This is a lot of work, and it takes a lot more skill and experience than creating a script.&lt;/p&gt;
&lt;p&gt;Setting up a workflow system in the cloud is one thing (especially if you pull a ready-made Open Source one off the Internet, as CodeOcean has to their credit done), but it needs to be populated with reusable software to be a useful workflow development platform, and that is difficult and time-consuming.&lt;/p&gt;
&lt;p&gt;So, will a system like this actually be useful? We have some existing workflow systems in science that are well used in particular communities, like &lt;a href=&quot;https://en.wikipedia.org/wiki/KNIME&quot;&gt;KNIME&lt;/a&gt;, so it’ll likely be of some use, but I don’t see this being the great solution to reusing scientific software. I do see something else, however: lock-in.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-420cacda.BYhmxsm-_ZLWveT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@reskp?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Jametlene Reskp&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-next-landgrab&quot;&gt;The next landgrab&lt;/h2&gt;
&lt;p&gt;CodeOcean claim that their platform is open. You can put your software and data on there, and everyone else can download it. And since the workflow engine they use, Apache Airflow, is Open Source, you may even be able to use the downloaded bits to put together a workflow locally.&lt;/p&gt;
&lt;p&gt;Doing that in practice is going to be quite a bit of work, and unlike with other repositories you need an account just to download anything. So there’s a network effect here: if most of the data and software you want is on this platform, then adding the rest is easier than getting the data and software out and running somewhere else.&lt;/p&gt;
&lt;p&gt;The login requirement also raises a barrier: I can easily grab data from a public server from a script, but with CodeOcean I have to go to my browser and do it by hand. Unless of course, I put my script into their platform.&lt;/p&gt;
&lt;p&gt;For a workflow platform like this to be truly open, it would have to be able to use data sets and compute steps from other platforms in its workflows, and allow other platforms (or local scripts) to use data and steps available on it. That would leave users free to choose any platform (or their own laptop) to put their data and software on, as well as to compose workflows on, because it ensures that we all can work together regardless of which product we choose to use.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The downside of a federated system is that it’s more difficult to make money off of it.&lt;/p&gt;
&lt;p&gt;The downside of a federated system is that it’s more difficult to make money off of it. Without a network effect, multiple providers could compete, and users would be free to switch. Such a free market would reduce prices, and that would be good for us eternally cash-strapped scientists, but investors in these companies would get less profit.&lt;/p&gt;
&lt;p&gt;So, if I ran a company like CodeOcean and wanted to make good money, I’d do something else. I’d require people to sign up to use the service, I would make it so that you could only combine data and software from different sources if all the data and all the software is in my system, and then I would make deals with some high-ranking journals to get them to push scientists to put their data and software on my platform.&lt;/p&gt;
&lt;p&gt;Other scientists are likely to want to use those high-profile data sets and software modules, and to do so, I’d make them sign up first. I would then design my user interface to push people towards using the data and software on my site, rather than downloading them and using them locally.&lt;/p&gt;
&lt;p&gt;They’d add their software and data to my platform, this being easier than getting things to run on their own computers, which encourages others to join as well, and the whole thing will snowball.&lt;/p&gt;
&lt;p&gt;Then, having obtained many users, I would have a look at the email addresses with which they signed up. I’d contact the universities they work for, and explain politely that many of their employees are using my service. I’d tell them that free accounts are going to go away, and that the university will have to pay an annual fee.&lt;/p&gt;
&lt;p&gt;If they refuse, I’d block their scientists from my platform. The scientists would then protest their university administration because, without their data and software, they cannot work. The university would then pay me, I’d re-enable access, and subsequently retire to a tropical beach to sip cocktails and add more features to my scientific software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;861&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-53a82e4a.BuANbNvh_ZDhgk3.webp&quot; srcset=&quot;&quot;&gt;
I’ll need to order a cup holder for my laptop… Photo by &lt;a href=&quot;https://unsplash.com/@whitney_wright?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Whitney Wright&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;déja-vu&quot;&gt;Déja vu&lt;/h2&gt;
&lt;p&gt;Am I a brilliant business strategist? Of course not. This business model, in which society pays people with public money to produce scientific output, which is then appropriated by a commercial platform and sold back to the public, is what Open Access has fought hard against.&lt;/p&gt;
&lt;p&gt;It’s taken a long time to get to a point where we are now mostly publishing Open Access (even in Nature, if you’re rich), and much of our publicly funded work is still locked away behind paywalls, but overall I’d say it’s been a success. That doesn’t deter people from trying to pull us back into the same trap however, this time for data and software. Instead of fighting our way out, maybe this time we should avoid falling into it in the first place.&lt;/p&gt;
&lt;p&gt;The good news is, we can! Instead of putting your data set on CodeOcean or a similar locked-in platform, put it on &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt; or &lt;a href=&quot;https://figshare.com/&quot;&gt;Figshare&lt;/a&gt;. These platforms allow anyone to download your data without an account, enabling them to use it anywhere. Scripts can go there too, and like data, they’ll get a DOI so that you can refer to them from your Open Access paper.&lt;/p&gt;
&lt;p&gt;No one installs reusable software from Zenodo, so if you make a reusable program then it’s best to publish it to the standard repository for the programming language you’re using. Python should go on PyPI and into conda-forge, the latter is also good for packages in C, C++, and Fortran, and Julia, Rust, R, and Java all have their standard places too.&lt;/p&gt;
&lt;p&gt;These repositories are open, allowing anyone to install and use your software anywhere without getting locked into something. For development, you can use GitLab (your own or one in the cloud) or GitHub, which also allows anyone to clone your repository without signing up or putting their own software in there.&lt;/p&gt;
&lt;p&gt;Of course running these platforms isn’t free. Zenodo is paid for by CERN, the particle physics lab in Switzerland. Figshare is run by a company. The conda package manager is mostly developed by Anaconda Inc. (another company), conda-forge runs on spare cloud resources donated by Microsoft, GitHub is owned by Microsoft and GitLab is run by the company with the same name.&lt;/p&gt;
&lt;p&gt;The difference is that conda is open source and so are conda-forge’s scripts and bots, and that git is an independent open source program, so that I can trivially clone a git repository off of GitHub and push it onto GitLab or vice versa.&lt;/p&gt;
&lt;p&gt;Issues and pull requests are harder to move, and there is somewhat of a network effect on these latter platforms for developers, who need to have an account for security reasons, but you don’t get locked in just to run anything, and it’s still easy to combine software and data from different sources.&lt;/p&gt;
&lt;p&gt;Sometimes it’s useful to put something in the cloud. Scientific software is often poorly engineered and difficult to install, and it can be nice to share an entire pre-installed environment sometimes, for demonstration purposes for example.&lt;/p&gt;
&lt;p&gt;If that’s what you want, go talk to your academic computing center! SURF for example here in The Netherlands have the &lt;a href=&quot;https://www.surf.nl/en/services/surf-research-cloud&quot;&gt;SURF Research Cloud&lt;/a&gt;, an environment in which you can create virtual machine images with your software, which other people can then run and use on SURF infrastructure.&lt;/p&gt;
&lt;p&gt;This does require an account (a standard SURFconext one that you use for their other services too), but at least it’s an account with a not-for-profit whose task it is to provide these resources to scientists. In short, SURF are working for you, not for a return on investment.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Is scientific software the new land grab?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-a2a5337a.BLFLgvCk_qumPd.webp&quot; srcset=&quot;&quot;&gt;
Example of a researcher using the SURF Research Cloud. Photo by &lt;a href=&quot;https://unsplash.com/@timmossholder?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Tim Mossholder&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-short&quot;&gt;In short&lt;/h2&gt;
&lt;p&gt;If someone invites you to put your scientific software onto their platform then you should have a good look first to see what this platform is for. Is this publicly funded infrastructure set up to make science more open and to support open collaboration? Then go right ahead. Is it commercial? Then it could still be okay, if it’s open enough. But beware of companies trying to appropriate your publicly funded work. We don’t need to fall into that trap again.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/is-scientific-software-the-new-land-grab-d0106fc2.-gtIOeaw.jpg" medium="image"/><author>Lourens Veen</author></item><item><title>From Pandemic Response to Package Development</title><link>https://blog2.esciencecenter.nl/posts/2024-11-26---from-pandemic-response-to-package-development</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-11-26---from-pandemic-response-to-package-development</guid><description>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/fenne-riemslagh/&quot;&gt;Fenne Riemslagh&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We had the pleasure of sitting down with &lt;a href=&quot;http://www.linkedin.com/in/kirsten-bulsink&quot;&gt;Kirsten Bulsink&lt;/a&gt;, a data scientist at the Dutch National Institute for Public Health and the Environment (&lt;a href=&quot;http://www.rivm.nl&quot;&gt;RIVM&lt;/a&gt;). Our discussion covered her journey from pandemic response to R-package development and how the Netherlands eScience Center played a part in creating a crucial part of tooling at RIVM. Her story demonstrates the importance of collaborative work in research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Pandemic Response to Package Development&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-32f8ae64.B6ocEb2n_Zt1Q8v.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@chesnutt?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Eran Menashri&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Q: Can you tell us about your background and current role at RIVM?**&lt;/p&gt;
&lt;p&gt;A: I’ve been working at RIVM for a little over three years now. My background is in psychology, with a master’s in neuroscience. During my Research Master’s, I discovered my passion for data analysis and finding answers through data. This led me to pursue a minor in data science.&lt;/p&gt;
&lt;p&gt;I started working at RIVM during the COVID-19 pandemic. Initially, it was a chaotic time, with researchers working overtime to analyze and report data quickly. When I joined, there was already a semi-automatic data pipeline in place, but we still had to tackle complex challenges, like calculating vaccination rates with data from a selected group (because of opt-out).&lt;/p&gt;
&lt;p&gt;As our team grew to about 9 to 10 people, we started organizing workshops to reflect on our processes. We asked ourselves what worked well and what we’d do differently if we could start over. This reflection led to the development of new tools and approaches.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“…we started organizing workshops to reflect on our processes. We asked ourselves what worked well and what we’d do differently if we could start over. This reflection led to the development of new tools and approaches.”&lt;/p&gt;
&lt;p&gt;Before the pandemic, processes and methods differed for different infectious diseases. As a result, researchers at RIVM had to perform many actions manually, and these processes could differ per infectious disease. The pandemic necessitated more knowledge sharing and collaboration. We started standardizing and automating data transformation and reporting for infectious diseases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: We understand that you and your colleague participated in the R-packaging workshop organized by the eScience Center. Can you tell us about that experience and the R-package your team developed?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, that’s correct. One of my colleagues actually took the &lt;a href=&quot;https://carpentries-incubator.github.io/lesson-R-packaging/&quot;&gt;R-packaging workshop&lt;/a&gt; offered by the eScience Center before I did. Later, I also had the opportunity to take the same course.&lt;/p&gt;
&lt;p&gt;The package, which now serves as a core tool for epidemiological pipelines at RIVM, provides functionality for loading, cleaning, and reporting data, with various checks in place. It also includes functions to create graphs in RIVM colors and style.&lt;/p&gt;
&lt;p&gt;For example, during the COVID-19 pandemic, we used analysis methods to process data on positive cases, calculate the number of cases over time, and generate reports. Now, we use the package for monitoring and reporting on various infectious diseases like &lt;a href=&quot;https://www.rivm.nl/soa/cijfers-en-rapportages-soa&quot;&gt;sexually transmitted infections&lt;/a&gt; and &lt;a href=&quot;https://www.rivm.nl/luchtweginfecties/actuele-cijfers&quot;&gt;respiratory infections&lt;/a&gt;, not just COVID-19.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Pandemic Response to Package Development&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-64e59eb1.DcKWcbN2_Z18Wl75.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@f12r?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Fahim Muntashir&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;**&lt;/p&gt;
&lt;p&gt;How did the R-packaging workshop help professionalize your package?**&lt;/p&gt;
&lt;p&gt;After joining the workshop at the Netherlands eScience Center, I organized a session for my team to share what I had learned. While my colleagues had already done a great job, the workshop helped us improve consistency in managing dependencies. We also enhanced our documentation. The package improvements made it easier for others to use the package. Installation became smoother, and users no longer had to figure out why they needed to install extra packages.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“The package improvements made it easier for others to use the package. Installation became smoother, and users no longer had to figure out why they needed to install extra packages.”&lt;/p&gt;
&lt;p&gt;Later on, I also took the &lt;a href=&quot;https://carpentries-incubator.github.io/python-intermediate-development/&quot;&gt;Python software development course&lt;/a&gt; offered by the eScience Center, which was really eye-opening. I learned about tools like linters, virtual environments, testing, coverage, and CI/CD pipelines. This knowledge made us realize we needed to implement these practices in our R-package as well.&lt;/p&gt;
&lt;p&gt;After gaining all this knowledge from the eScience Center courses, we felt ready to take our package to the next level. We decided to organize hackathons to focus on implementing best practices and improving our package structure.&lt;/p&gt;
&lt;p&gt;Our first main goal was to internally demonstrate that we had a high-quality product, especially since many analyses of infectious disease data rely on this package. Our second goal was to share our methodology with external parties like the GGD (Municipal Health Services), even if we couldn’t share the actual data.&lt;/p&gt;
&lt;p&gt;We reached out to the eScience Center training team for support, and they connected us with &lt;a href=&quot;https://www.esciencecenter.nl/team/pablo-rodriguez-sanchez/&quot;&gt;Pablo Rodríguez Sánchez&lt;/a&gt; (one of the eScience Center’s Research Software Engineers (RSEs) and main author of the R-packaging course, ed.) to consult during our hackathon. This collaboration was very valuable in guiding our efforts and providing expert insights.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Pandemic Response to Package Development&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-f8e29e49.CecW0r8P_USIcj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@kommumikation?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mika Baumeister&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;strong&gt;Q: What were the outcomes of the hackathons?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We had two hackathons. In the first one, we focused on testing and documentation. We increased our test coverage and improved our package documentation, including creating a vignette with examples.&lt;/p&gt;
&lt;p&gt;The second hackathon was about splitting our large package into smaller, more manageable ones. We also worked on establishing a workflow for potentially publishing the package on GitHub while keeping our main development on RIVM’s internal GitLab.&lt;/p&gt;
&lt;p&gt;Pablo provided a fresh perspective and helped us confirm that we were on the right track. His expertise was particularly valuable in the second hackathon when we were making decisions about package structure and workflow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“Pablo Rodríguez-Sánchez, Research Software Engineer (RSE) at the Netherlands eScience Center, provided a fresh perspective and helped us confirm that we were on the right track. His expertise was particularly valuable in the second hackathon when we were making decisions about package structure and workflow.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How has this experience changed your team’s way of working?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the past year, we’ve started to work much more like a software development team. We now use a Kanban board for project management and have implemented CI/CD pipelines, which have made our development process much smoother. The package split has made everything more manageable, and it’s easier to see where we need certain tests or improvements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What’s next for your package and team?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We’re planning to release some of our packages in GitHub in the next couple of months, which will allow external users to download and use them. We’re also focusing on internal knowledge sharing and running workshops about our tooling.&lt;/p&gt;
&lt;p&gt;We value having the eScience Center as a sparring partner for tackling these technical challenges.&lt;/p&gt;
&lt;p&gt;In my current role I now have a nice combination of technical skills and advisory tasks. We advise and make other people at RIVM enthusiastic about our tools. Our recent experience in developing this R package has been invaluable.&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center would like to thank Kirsten for her time for the interview . We look forward to continuing our collaboration. If you want to learn more about collaborating with the eScience Center or are interested in our training programme, please visit &lt;a href=&quot;https://www.esciencecenter.nl/digital-skills/&quot;&gt;Training &amp;#x26; Workshops — eScience Center&lt;/a&gt;. If you are interested in receiving consulting like Kirsten did, you may be interested in our &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;Fellowship Programme&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Tue, 26 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/fenne-riemslagh/&quot;&gt;Fenne Riemslagh&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We had the pleasure of sitting down with &lt;a href=&quot;http://www.linkedin.com/in/kirsten-bulsink&quot;&gt;Kirsten Bulsink&lt;/a&gt;, a data scientist at the Dutch National Institute for Public Health and the Environment (&lt;a href=&quot;http://www.rivm.nl&quot;&gt;RIVM&lt;/a&gt;). Our discussion covered her journey from pandemic response to R-package development and how the Netherlands eScience Center played a part in creating a crucial part of tooling at RIVM. Her story demonstrates the importance of collaborative work in research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Pandemic Response to Package Development&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-32f8ae64.B6ocEb2n_Zt1Q8v.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@chesnutt?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Eran Menashri&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Q: Can you tell us about your background and current role at RIVM?**&lt;/p&gt;
&lt;p&gt;A: I’ve been working at RIVM for a little over three years now. My background is in psychology, with a master’s in neuroscience. During my Research Master’s, I discovered my passion for data analysis and finding answers through data. This led me to pursue a minor in data science.&lt;/p&gt;
&lt;p&gt;I started working at RIVM during the COVID-19 pandemic. Initially, it was a chaotic time, with researchers working overtime to analyze and report data quickly. When I joined, there was already a semi-automatic data pipeline in place, but we still had to tackle complex challenges, like calculating vaccination rates with data from a selected group (because of opt-out).&lt;/p&gt;
&lt;p&gt;As our team grew to about 9 to 10 people, we started organizing workshops to reflect on our processes. We asked ourselves what worked well and what we’d do differently if we could start over. This reflection led to the development of new tools and approaches.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“…we started organizing workshops to reflect on our processes. We asked ourselves what worked well and what we’d do differently if we could start over. This reflection led to the development of new tools and approaches.”&lt;/p&gt;
&lt;p&gt;Before the pandemic, processes and methods differed for different infectious diseases. As a result, researchers at RIVM had to perform many actions manually, and these processes could differ per infectious disease. The pandemic necessitated more knowledge sharing and collaboration. We started standardizing and automating data transformation and reporting for infectious diseases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: We understand that you and your colleague participated in the R-packaging workshop organized by the eScience Center. Can you tell us about that experience and the R-package your team developed?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, that’s correct. One of my colleagues actually took the &lt;a href=&quot;https://carpentries-incubator.github.io/lesson-R-packaging/&quot;&gt;R-packaging workshop&lt;/a&gt; offered by the eScience Center before I did. Later, I also had the opportunity to take the same course.&lt;/p&gt;
&lt;p&gt;The package, which now serves as a core tool for epidemiological pipelines at RIVM, provides functionality for loading, cleaning, and reporting data, with various checks in place. It also includes functions to create graphs in RIVM colors and style.&lt;/p&gt;
&lt;p&gt;For example, during the COVID-19 pandemic, we used analysis methods to process data on positive cases, calculate the number of cases over time, and generate reports. Now, we use the package for monitoring and reporting on various infectious diseases like &lt;a href=&quot;https://www.rivm.nl/soa/cijfers-en-rapportages-soa&quot;&gt;sexually transmitted infections&lt;/a&gt; and &lt;a href=&quot;https://www.rivm.nl/luchtweginfecties/actuele-cijfers&quot;&gt;respiratory infections&lt;/a&gt;, not just COVID-19.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Pandemic Response to Package Development&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-64e59eb1.DcKWcbN2_Z18Wl75.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@f12r?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Fahim Muntashir&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;**&lt;/p&gt;
&lt;p&gt;How did the R-packaging workshop help professionalize your package?**&lt;/p&gt;
&lt;p&gt;After joining the workshop at the Netherlands eScience Center, I organized a session for my team to share what I had learned. While my colleagues had already done a great job, the workshop helped us improve consistency in managing dependencies. We also enhanced our documentation. The package improvements made it easier for others to use the package. Installation became smoother, and users no longer had to figure out why they needed to install extra packages.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“The package improvements made it easier for others to use the package. Installation became smoother, and users no longer had to figure out why they needed to install extra packages.”&lt;/p&gt;
&lt;p&gt;Later on, I also took the &lt;a href=&quot;https://carpentries-incubator.github.io/python-intermediate-development/&quot;&gt;Python software development course&lt;/a&gt; offered by the eScience Center, which was really eye-opening. I learned about tools like linters, virtual environments, testing, coverage, and CI/CD pipelines. This knowledge made us realize we needed to implement these practices in our R-package as well.&lt;/p&gt;
&lt;p&gt;After gaining all this knowledge from the eScience Center courses, we felt ready to take our package to the next level. We decided to organize hackathons to focus on implementing best practices and improving our package structure.&lt;/p&gt;
&lt;p&gt;Our first main goal was to internally demonstrate that we had a high-quality product, especially since many analyses of infectious disease data rely on this package. Our second goal was to share our methodology with external parties like the GGD (Municipal Health Services), even if we couldn’t share the actual data.&lt;/p&gt;
&lt;p&gt;We reached out to the eScience Center training team for support, and they connected us with &lt;a href=&quot;https://www.esciencecenter.nl/team/pablo-rodriguez-sanchez/&quot;&gt;Pablo Rodríguez Sánchez&lt;/a&gt; (one of the eScience Center’s Research Software Engineers (RSEs) and main author of the R-packaging course, ed.) to consult during our hackathon. This collaboration was very valuable in guiding our efforts and providing expert insights.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Pandemic Response to Package Development&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-f8e29e49.CecW0r8P_USIcj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@kommumikation?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mika Baumeister&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;strong&gt;Q: What were the outcomes of the hackathons?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We had two hackathons. In the first one, we focused on testing and documentation. We increased our test coverage and improved our package documentation, including creating a vignette with examples.&lt;/p&gt;
&lt;p&gt;The second hackathon was about splitting our large package into smaller, more manageable ones. We also worked on establishing a workflow for potentially publishing the package on GitHub while keeping our main development on RIVM’s internal GitLab.&lt;/p&gt;
&lt;p&gt;Pablo provided a fresh perspective and helped us confirm that we were on the right track. His expertise was particularly valuable in the second hackathon when we were making decisions about package structure and workflow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“Pablo Rodríguez-Sánchez, Research Software Engineer (RSE) at the Netherlands eScience Center, provided a fresh perspective and helped us confirm that we were on the right track. His expertise was particularly valuable in the second hackathon when we were making decisions about package structure and workflow.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: How has this experience changed your team’s way of working?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the past year, we’ve started to work much more like a software development team. We now use a Kanban board for project management and have implemented CI/CD pipelines, which have made our development process much smoother. The package split has made everything more manageable, and it’s easier to see where we need certain tests or improvements.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What’s next for your package and team?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We’re planning to release some of our packages in GitHub in the next couple of months, which will allow external users to download and use them. We’re also focusing on internal knowledge sharing and running workshops about our tooling.&lt;/p&gt;
&lt;p&gt;We value having the eScience Center as a sparring partner for tackling these technical challenges.&lt;/p&gt;
&lt;p&gt;In my current role I now have a nice combination of technical skills and advisory tasks. We advise and make other people at RIVM enthusiastic about our tools. Our recent experience in developing this R package has been invaluable.&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center would like to thank Kirsten for her time for the interview . We look forward to continuing our collaboration. If you want to learn more about collaborating with the eScience Center or are interested in our training programme, please visit &lt;a href=&quot;https://www.esciencecenter.nl/digital-skills/&quot;&gt;Training &amp;#x26; Workshops — eScience Center&lt;/a&gt;. If you are interested in receiving consulting like Kirsten did, you may be interested in our &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;Fellowship Programme&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/from-pandemic-response-to-package-develo-32f8ae64.B6ocEb2n.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Why should you care about reproducible code — and how to get started?</title><link>https://blog2.esciencecenter.nl/posts/2024-11-14---why-should-you-care-about-reproducible-code-and-how-to-get-s</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-11-14---why-should-you-care-about-reproducible-code-and-how-to-get-s</guid><description>&lt;h2 id=&quot;on-23-april-2024-the-first-national-research-software-day-took-place-in-hilversum-the-netherlands-during-the-unconference-part-of-the-program-eduard-klapwijk-ran-the-session-about-the-importance-of-reproducible-code&quot;&gt;On 23 April 2024, the first ‘&lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day&lt;/a&gt;’ took place in Hilversum, the Netherlands. During the unconference part of the program, &lt;a href=&quot;https://www.universiteitleiden.nl/medewerkers/eduard-klapwijk#tab-1&quot;&gt;Eduard Klapwijk&lt;/a&gt; ran the session about the importance of reproducible code.&lt;/h2&gt;
&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why should you care about reproducible code — and how to get started?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;495&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-should-you-care-about-reproducible-c-984b86bd.CiHwM2go_2vr8Xa.webp&quot; srcset=&quot;&quot;&gt;
Credit: &lt;a href=&quot;https://the-turing-way.netlify.app/_images/reproducibility.jpg&quot;&gt;The Turing Way&lt;/a&gt;&lt;em&gt;Authors: Diana I. Bocancea¹, Daniela Gawehns², Julian Lopez Gordillo³, Sam Langton¹, Katinka Rus¹, Sally Hogenboom⁴, Iris Spruit⁵, Eduard Klapwijk⁶&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Despite the increased awareness regarding reproducibility in recent years, most research results are not &lt;a href=&quot;https://book.the-turing-way.org/reproducible-research/overview/overview-definitions&quot;&gt;computationally reproducible&lt;/a&gt;: they cannot be independently reproduced. The main reason for this is that in most cases, data and code are not shared publicly. But even when a researcher openly shares their data and code with the public, reviewers or research colleagues, their findings can rarely be reproduced in their entirety. Perhaps the code cannot be executed, only parts of the results are generated, or perhaps the results produced are totally different from the published study. Reproducibility can even be a challenge internally. As any programmer will know, just because your code runs perfectly today, it does not mean it will run perfectly in five years’ time (or even five days’ time!).&lt;/p&gt;
&lt;p&gt;But why does writing reproducible code even matter, and how might you as a researcher get started on this journey toward reproducible research?&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-working-reproducibly&quot;&gt;&lt;em&gt;Benefits of working reproducibly&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;One reason is that it will make your life as a researcher easier! Many of the components that make a piece of research reproducible — well-documented, clearly written code, containerised environments, properly organized data — are also things that save a lot of time. These activities ensure that when you return to code six months later, the scripts still run, and you don’t have to spend three days debugging them. It also means that your code can be shared and reused by your colleagues, saving them time, and giving you credit (e.g., authorship) in the process. There are other reasons too, including reputational benefits and advantages during peer review. You can read more about ‘selfish’ reasons to make your research reproducible &lt;a href=&quot;https://genomebiology.biomedcentral.com/articles/10.1186/s13059-015-0850-7%22%20%EF%B7%9FHYPERLINK%20%22https://doi.org/10.1186/s13059-015-0850-7&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What about the scientific community? We are currently in a situation where a large proportion of research is not reproducible. This situation threatens the integrity of scientific research, weakens our evidence base, and ultimately might lessen public trust in science. The main method for scrutinising and sharing scientific results — peer-reviewed journals — are slowly adapting to this realisation. Increasingly, researchers are encouraged, if not expected, to provide their data, code and other materials used alongside the publication itself. In time, we could see reproducibility move from being an optional bonus to becoming a mandatory part of the research (and publication) process. Adapting to this change early will bring you all the benefits noted above (e.g., timesaving, code reuse) but will also prepare you for the future.&lt;/p&gt;
&lt;h2 id=&quot;reproducible-tools-as-a-contribution-to-science&quot;&gt;&lt;em&gt;Reproducible tools as a contribution to science&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;On that note, the changing perspective on the importance of reproducibility is bringing new career paths with it. For example, beyond the fundamental tools that enable reproducible research (such as git for version control), other higher-level tools are appearing to address certain challenges particular to some scientific domains. Usually, they are aimed at solving well-known problems for researchers from a certain field, problems not well-known outside of one niche. They might revolve around workflow management and experiment design or standardisation of certain procedures within the community. In many cases, the developers behind those software tools and resources are… the researchers themselves. They might have struggled with these issues in their own research and decided to take up the task of developing the tools that they wished they had (for example, extensive Python-based processing pipelines such as &lt;a href=&quot;https://doi.org/10.1038/s41592-018-0235-4&quot;&gt;fmriprep&lt;/a&gt; in the neuroimaging field, and thousands of R packages ranging from complex statistical modelling packages such as &lt;a href=&quot;https://doi.org/10.18637/jss.v080.i01&quot;&gt;brms&lt;/a&gt; for Bayesian regression to packages to help you formatting manuscripts such as &lt;a href=&quot;https://cran.r-project.org/web/packages/papaja/index.html&quot;&gt;papaja&lt;/a&gt;). In doing so, they shifted their focus from their original subject domain to the mission of making research within that domain reproducible. This typically takes the form of developing the software libraries that make that possible and integrating them with the standard software used within the domain.&lt;/p&gt;
&lt;p&gt;The whole scientific community can benefit from such tools! Newer research can be built on top of them, without the need to solve common reproducibility issues from scratch. These software developments can be just as valuable a contribution to the research domain as other research findings, and as such, they should be recognised accordingly. And just like it is possible to publish your research findings, it should be possible to publish your code contributions when they are significant enough. A good example of this idea put into practice is the &lt;a href=&quot;https://joss.theoj.org/&quot;&gt;Journal of Open Source Sofware&lt;/a&gt; (JOSS), where the submitted code takes the main stage in the review process (as opposed to be required as “supplementary material”). Initiatives like JOSS showcase developments around reproducible research as a meaningful contribution to science and a viable development path, both of which are powerful incentives for researchers to get interested in the topic.&lt;/p&gt;
&lt;p&gt;In time, with all these smaller and bigger changes, scientific research can become more trustworthy, more reliable, and in turn, more impactful.&lt;/p&gt;
&lt;h2 id=&quot;how-to-get-started&quot;&gt;How to get started*&lt;/h2&gt;
&lt;p&gt;The inevitable question that follows is then: how to get started with reproducibility? One answer is training. Luckily, there are a lot of initiatives for training that will help you to get started, both nationally and internationally. For example, a lot of institutions organize Software and Data &lt;a href=&quot;https://carpentries.org/&quot;&gt;Carpentries&lt;/a&gt; that offer foundational coding and data science skills.&lt;/p&gt;
&lt;p&gt;One way senior academics can make a difference — as group leaders, supervisors, and grant reviewers — is to give (junior) colleagues the time and incentives to value and practice reproducibility. For instance, supervisors could have all PhD students replicate and extend an existing analysis as part of their initial research. The process of reproducing an existing work will familiarize the student with the common challenges that come with doing good science. The work of reproducing someone else’s work might entail finding and understanding a certain dataset (sometimes difficult to even get access to), as well as the software (e.g. scripts or packages) that was used to produce the results. Running the previous analysis, often on a different computer and at a later time (when software dependencies have likely changed) would check the computational reproducibility of the previous work, and in doing so, be a valuable learning experience for the student.&lt;/p&gt;
&lt;p&gt;Group leaders benefit from reproducible workflows as it prevents (PhD) students from re-writing the same piece of software again and again. While learning the ropes is important for any junior scholar, it is not very efficient if every new generation of students re-writes code for basic operations or frequently used analysis methods.&lt;/p&gt;
&lt;p&gt;In addition to the benefits of an academic career, researchers themselves also increase their employability outside of academia by learning digital skills (such as version control or programming reusable pieces of code) that are valued in many different (industry) jobs.&lt;/p&gt;
&lt;p&gt;In modern science, computational methods are the norm in almost every discipline. Yet attempts at reproducibility are almost always unsuccessful due to missing materials and/or lack of skills. Part of this problem can be mitigated by learning how to produce reproducible code: how to write documentation, perform version control, and manage packages. Doing so will benefit you as a researcher, but also your colleagues, and the wider scientific community, because your (coding) efforts will become reusable. Increasing the use of reproducible workflows is in the interest of many stakeholders in academia — increasing the reproducibility of research is key for a broader change in how we do science.&lt;/p&gt;
&lt;p&gt;Footnotes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amc.nl/web/home.htm&quot;&gt;Amsterdam UMC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.umcg.nl/&quot;&gt;University Medical Center Groningen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.naturalis.nl/en&quot;&gt;Naturalis Biodiversity Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ou.nl/en/home&quot;&gt;Open Universiteit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.universiteitleiden.nl/en&quot;&gt;Universiteit Leiden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.eur.nl/en/essb&quot;&gt;Erasmus School of Social and Behavioural Sciences&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 14 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;on-23-april-2024-the-first-national-research-software-day-took-place-in-hilversum-the-netherlands-during-the-unconference-part-of-the-program-eduard-klapwijk-ran-the-session-about-the-importance-of-reproducible-code&quot;&gt;On 23 April 2024, the first ‘&lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day&lt;/a&gt;’ took place in Hilversum, the Netherlands. During the unconference part of the program, &lt;a href=&quot;https://www.universiteitleiden.nl/medewerkers/eduard-klapwijk#tab-1&quot;&gt;Eduard Klapwijk&lt;/a&gt; ran the session about the importance of reproducible code.&lt;/h2&gt;
&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why should you care about reproducible code — and how to get started?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;495&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-should-you-care-about-reproducible-c-984b86bd.CiHwM2go_2vr8Xa.webp&quot; srcset=&quot;&quot;&gt;
Credit: &lt;a href=&quot;https://the-turing-way.netlify.app/_images/reproducibility.jpg&quot;&gt;The Turing Way&lt;/a&gt;&lt;em&gt;Authors: Diana I. Bocancea¹, Daniela Gawehns², Julian Lopez Gordillo³, Sam Langton¹, Katinka Rus¹, Sally Hogenboom⁴, Iris Spruit⁵, Eduard Klapwijk⁶&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Despite the increased awareness regarding reproducibility in recent years, most research results are not &lt;a href=&quot;https://book.the-turing-way.org/reproducible-research/overview/overview-definitions&quot;&gt;computationally reproducible&lt;/a&gt;: they cannot be independently reproduced. The main reason for this is that in most cases, data and code are not shared publicly. But even when a researcher openly shares their data and code with the public, reviewers or research colleagues, their findings can rarely be reproduced in their entirety. Perhaps the code cannot be executed, only parts of the results are generated, or perhaps the results produced are totally different from the published study. Reproducibility can even be a challenge internally. As any programmer will know, just because your code runs perfectly today, it does not mean it will run perfectly in five years’ time (or even five days’ time!).&lt;/p&gt;
&lt;p&gt;But why does writing reproducible code even matter, and how might you as a researcher get started on this journey toward reproducible research?&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-working-reproducibly&quot;&gt;&lt;em&gt;Benefits of working reproducibly&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;One reason is that it will make your life as a researcher easier! Many of the components that make a piece of research reproducible — well-documented, clearly written code, containerised environments, properly organized data — are also things that save a lot of time. These activities ensure that when you return to code six months later, the scripts still run, and you don’t have to spend three days debugging them. It also means that your code can be shared and reused by your colleagues, saving them time, and giving you credit (e.g., authorship) in the process. There are other reasons too, including reputational benefits and advantages during peer review. You can read more about ‘selfish’ reasons to make your research reproducible &lt;a href=&quot;https://genomebiology.biomedcentral.com/articles/10.1186/s13059-015-0850-7%22%20%EF%B7%9FHYPERLINK%20%22https://doi.org/10.1186/s13059-015-0850-7&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What about the scientific community? We are currently in a situation where a large proportion of research is not reproducible. This situation threatens the integrity of scientific research, weakens our evidence base, and ultimately might lessen public trust in science. The main method for scrutinising and sharing scientific results — peer-reviewed journals — are slowly adapting to this realisation. Increasingly, researchers are encouraged, if not expected, to provide their data, code and other materials used alongside the publication itself. In time, we could see reproducibility move from being an optional bonus to becoming a mandatory part of the research (and publication) process. Adapting to this change early will bring you all the benefits noted above (e.g., timesaving, code reuse) but will also prepare you for the future.&lt;/p&gt;
&lt;h2 id=&quot;reproducible-tools-as-a-contribution-to-science&quot;&gt;&lt;em&gt;Reproducible tools as a contribution to science&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;On that note, the changing perspective on the importance of reproducibility is bringing new career paths with it. For example, beyond the fundamental tools that enable reproducible research (such as git for version control), other higher-level tools are appearing to address certain challenges particular to some scientific domains. Usually, they are aimed at solving well-known problems for researchers from a certain field, problems not well-known outside of one niche. They might revolve around workflow management and experiment design or standardisation of certain procedures within the community. In many cases, the developers behind those software tools and resources are… the researchers themselves. They might have struggled with these issues in their own research and decided to take up the task of developing the tools that they wished they had (for example, extensive Python-based processing pipelines such as &lt;a href=&quot;https://doi.org/10.1038/s41592-018-0235-4&quot;&gt;fmriprep&lt;/a&gt; in the neuroimaging field, and thousands of R packages ranging from complex statistical modelling packages such as &lt;a href=&quot;https://doi.org/10.18637/jss.v080.i01&quot;&gt;brms&lt;/a&gt; for Bayesian regression to packages to help you formatting manuscripts such as &lt;a href=&quot;https://cran.r-project.org/web/packages/papaja/index.html&quot;&gt;papaja&lt;/a&gt;). In doing so, they shifted their focus from their original subject domain to the mission of making research within that domain reproducible. This typically takes the form of developing the software libraries that make that possible and integrating them with the standard software used within the domain.&lt;/p&gt;
&lt;p&gt;The whole scientific community can benefit from such tools! Newer research can be built on top of them, without the need to solve common reproducibility issues from scratch. These software developments can be just as valuable a contribution to the research domain as other research findings, and as such, they should be recognised accordingly. And just like it is possible to publish your research findings, it should be possible to publish your code contributions when they are significant enough. A good example of this idea put into practice is the &lt;a href=&quot;https://joss.theoj.org/&quot;&gt;Journal of Open Source Sofware&lt;/a&gt; (JOSS), where the submitted code takes the main stage in the review process (as opposed to be required as “supplementary material”). Initiatives like JOSS showcase developments around reproducible research as a meaningful contribution to science and a viable development path, both of which are powerful incentives for researchers to get interested in the topic.&lt;/p&gt;
&lt;p&gt;In time, with all these smaller and bigger changes, scientific research can become more trustworthy, more reliable, and in turn, more impactful.&lt;/p&gt;
&lt;h2 id=&quot;how-to-get-started&quot;&gt;How to get started*&lt;/h2&gt;
&lt;p&gt;The inevitable question that follows is then: how to get started with reproducibility? One answer is training. Luckily, there are a lot of initiatives for training that will help you to get started, both nationally and internationally. For example, a lot of institutions organize Software and Data &lt;a href=&quot;https://carpentries.org/&quot;&gt;Carpentries&lt;/a&gt; that offer foundational coding and data science skills.&lt;/p&gt;
&lt;p&gt;One way senior academics can make a difference — as group leaders, supervisors, and grant reviewers — is to give (junior) colleagues the time and incentives to value and practice reproducibility. For instance, supervisors could have all PhD students replicate and extend an existing analysis as part of their initial research. The process of reproducing an existing work will familiarize the student with the common challenges that come with doing good science. The work of reproducing someone else’s work might entail finding and understanding a certain dataset (sometimes difficult to even get access to), as well as the software (e.g. scripts or packages) that was used to produce the results. Running the previous analysis, often on a different computer and at a later time (when software dependencies have likely changed) would check the computational reproducibility of the previous work, and in doing so, be a valuable learning experience for the student.&lt;/p&gt;
&lt;p&gt;Group leaders benefit from reproducible workflows as it prevents (PhD) students from re-writing the same piece of software again and again. While learning the ropes is important for any junior scholar, it is not very efficient if every new generation of students re-writes code for basic operations or frequently used analysis methods.&lt;/p&gt;
&lt;p&gt;In addition to the benefits of an academic career, researchers themselves also increase their employability outside of academia by learning digital skills (such as version control or programming reusable pieces of code) that are valued in many different (industry) jobs.&lt;/p&gt;
&lt;p&gt;In modern science, computational methods are the norm in almost every discipline. Yet attempts at reproducibility are almost always unsuccessful due to missing materials and/or lack of skills. Part of this problem can be mitigated by learning how to produce reproducible code: how to write documentation, perform version control, and manage packages. Doing so will benefit you as a researcher, but also your colleagues, and the wider scientific community, because your (coding) efforts will become reusable. Increasing the use of reproducible workflows is in the interest of many stakeholders in academia — increasing the reproducibility of research is key for a broader change in how we do science.&lt;/p&gt;
&lt;p&gt;Footnotes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amc.nl/web/home.htm&quot;&gt;Amsterdam UMC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.umcg.nl/&quot;&gt;University Medical Center Groningen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.naturalis.nl/en&quot;&gt;Naturalis Biodiversity Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ou.nl/en/home&quot;&gt;Open Universiteit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.universiteitleiden.nl/en&quot;&gt;Universiteit Leiden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.eur.nl/en/essb&quot;&gt;Erasmus School of Social and Behavioural Sciences&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/why-should-you-care-about-reproducible-c-984b86bd.CiHwM2go.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Variables, Records, Values and Objects</title><link>https://blog2.esciencecenter.nl/posts/2024-11-07---variables-records-values-and-objects</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-11-07---variables-records-values-and-objects</guid><description>&lt;p&gt;14&lt;/p&gt;
&lt;p&gt;The Engineering Corner&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A blog-within-a-blog on the transition from writing simple scripts for yourself to writing larger programs with and for others. TEC appears on an irregular schedule driven by workload and inspiration. (&lt;/em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;&lt;em&gt;TEC1&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, &lt;em&gt;&lt;a href=&quot;https://medium.com/escience-center/procedural-programming-f1d8cdef7540&quot;&gt;&lt;em&gt;TEC2&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;-3-variables-records-values-and-objects&quot;&gt;№ 3: Variables, Records, Values and Objects&lt;/h2&gt;
&lt;p&gt;Last time, we talked about the actions taken by scripts, and how they could be organised hierarchically using procedures. This makes it possible to split up a big problem into clearly delineated blocks with well-defined interfaces. These blocks can then be glued together into a hierarchical structure that gets complex things done in a well-organised way.&lt;/p&gt;
&lt;p&gt;However, actions are only one half of the programming equation. Procedures give us verbs, but we’re still missing nouns: data, or state. In Python, and many other languages, data is stored in &lt;em&gt;variables&lt;/em&gt;. Variables connect a name to a memory location holding a value. This connection is created by an &lt;em&gt;assignment&lt;/em&gt;. The statement &lt;code&gt;x = 1&lt;/code&gt; will create a new memory location, associate it with the name &lt;code&gt;x&lt;/code&gt;, and write the number &lt;code&gt;1&lt;/code&gt; in it. Other examples of Python values are the string &lt;code&gt;&quot;The Engineering Corner”&lt;/code&gt; and the boolean value &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Variables, Records, Values and Objects&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/variables-records-values-and-objects-ec9ee01b.CmSLy2Cc_ZHJSTb.webp&quot; srcset=&quot;&quot;&gt;
Values spilling out of a variable? Could there be a memory leak? Photo by &lt;a href=&quot;https://unsplash.com/@napender?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Napendra Singh&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Variables can be used in different ways. Often, they store the data that we are processing; after we read it from an input file, halfway through a calculation, and before we write it out again. But we also have variables that are used to control the execution of the script: loop variables, flags that keep track of whether something has happened, and so on. Sometimes, data is used to make decisions as well (“if x is negative, do this, else do that”).&lt;/p&gt;
&lt;p&gt;At any point during its execution, a program has a &lt;em&gt;state&lt;/em&gt;, which is simply the collection of all existing variables, plus an indication of the next statement to execute. Together with any future inputs, this state will determine what the program is going to do. Which branch of an if-statement is taken, how many loops a for-statement executes, it all depends on the state.&lt;/p&gt;
&lt;p&gt;As your script gets bigger it will get more and more variables, until it becomes difficult to keep track of them all. As with the actions, the solution is to organise the variables hierarchically. There are two ways to do that actually, &lt;em&gt;scopes&lt;/em&gt; and &lt;em&gt;records&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;scopes&quot;&gt;Scopes&lt;/h3&gt;
&lt;p&gt;Scopes come for free once you start making functions (procedures in &lt;a href=&quot;https://medium.com/escience-center/procedural-programming-f1d8cdef7540&quot;&gt;TEC 2&lt;/a&gt;, we’re switching back to Python terminology here and call them functions). Variables created within a function are &lt;em&gt;local&lt;/em&gt; to that function, which means that they’re only visible to statements inside of the function. In other words, they are &lt;em&gt;in the function’s scope&lt;/em&gt;. Variables that aren’t created within a function are &lt;em&gt;global&lt;/em&gt; variables, and are &lt;em&gt;in the global scope&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So, if you make functions, you’ll notice that most of your variables will end up being local variables. In fact, if you design these functions well and have them only communicate with other functions via parameters and return values, then the only global variables you’ll have are at the top level of your Python script. In Python, you &lt;em&gt;can&lt;/em&gt; actually read those global variables from inside a function, but something funny happens if you write to them:&lt;/p&gt;
&lt;p&gt;global_variable = 42&lt;/p&gt;
&lt;p&gt;def my_function() -&gt; None:
print(global_variable) # prints 42
global_variable = 43
print(global_variable) # prints 43&lt;/p&gt;
&lt;p&gt;my_function()&lt;/p&gt;
&lt;p&gt;print(global_variable) # prints 42The way this works is that if you try to use a variable, it is first looked up in the local scope you’re in. If it’s not found there, then the global scope is tried. So the first time &lt;code&gt;global_variable&lt;/code&gt; is read in &lt;code&gt;my_function&lt;/code&gt;, this is what happens. Assignment however is not affected, so on the next line a &lt;em&gt;new&lt;/em&gt; variable is made in the &lt;em&gt;local&lt;/em&gt; scope, which is called &lt;code&gt;global_variable&lt;/code&gt; and given the value 43.&lt;/p&gt;
&lt;p&gt;On the next line, this local variable is found first and its value is printed. Note that the global variable named &lt;code&gt;global_variable&lt;/code&gt; is now invisible from within &lt;code&gt;my_function&lt;/code&gt;, as it is masked or &lt;em&gt;shadowed&lt;/em&gt; by the local variable of the same name. The print statement at the end of the script isn’t in &lt;code&gt;my_function&lt;/code&gt;’s scope, so, it sees the global version of the variable, which still has the value 42.&lt;/p&gt;
&lt;p&gt;Scopes are very, very good to have when you’re making larger programs, because they decouple different parts of the state from each other. If your functions are of a reasonable length, then all the code that can possibly affect a local variable is on your screen at once, and easy to have a picture of in your head. This makes it much easier to reason about the code, something that is very important if you’re writing code that will run on someone else’s computer while you’re not around.&lt;/p&gt;
&lt;p&gt;You can in fact write to a global variable from inside of a function, but you’d have to have some very very good reasons to do so. It’s almost never good design, so I’m not going to tell you how to do it. Instead, let’s talk about records.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Variables, Records, Values and Objects&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/variables-records-values-and-objects-56480c6a.GzOIlrrD_ZwEkjh.webp&quot; srcset=&quot;&quot;&gt;
A record record has a record company, catalog number, artist, and title. Photo by &lt;a href=&quot;https://unsplash.com/@rocinante_11?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mick Haupt&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;records&quot;&gt;Records&lt;/h3&gt;
&lt;p&gt;Sometimes, one variable just isn’t enough to contain all the information you want to store about a particular thing. For example, if you need to keep track of a person, you’ll want to store their name, but maybe also their date of birth, email address, and whatever other properties are of interest to your application. And speaking of dates, those consist of a day, month and year &lt;a href=&quot;#2459&quot;&gt;[0]&lt;/a&gt;. So it seems that some way of grouping multiple variables together would be a useful language feature.&lt;/p&gt;
&lt;p&gt;Fortunately, language designers have come to the same conclusion, and have added records* (Pascal) and &lt;em&gt;structs&lt;/em&gt; (C and C++) to languages. More recent languages like Python tend to have classes instead (more on those in a future instalment), but the closest equivalents in Python would be a &lt;em&gt;dataclass&lt;/em&gt; [1]:&lt;/p&gt;
&lt;p&gt;from dataclass import dataclass&lt;/p&gt;
&lt;p&gt;@dataclass
class Date:
day: int
month: int
year: int&lt;/p&gt;
&lt;p&gt;@dataclass
class Person:
name: str
date_of_birth: DateHere we have a statement that creates a class named &lt;code&gt;Date&lt;/code&gt;, containing &lt;code&gt;day&lt;/code&gt;, &lt;code&gt;month&lt;/code&gt; and &lt;code&gt;year&lt;/code&gt; fields all of type &lt;code&gt;int&lt;/code&gt;. What does that mean? One way of looking at a class or a record is that it is a description of the structure of a certain type of complex values. So here we are saying that any value of type &lt;code&gt;Date&lt;/code&gt; must contain three subvalues with the given names, each of type &lt;code&gt;int&lt;/code&gt;. These subvalues can themselves be complex objects, as we see in class &lt;code&gt;Person&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And so here is a hierarchy again, but a different one than the hierarchy of functions. That one lets us describe complex actions as a combination of simpler actions, while this one lets us describe complex objects as combinations of simpler parts. Together, they make it possible to describe very complex programs in such a way that we can understand them one piece at a time.&lt;/p&gt;
&lt;p&gt;There’s one thing still missing though. A class is just a description of what a particular type of value looks like. In order to actually do something, we need some variables containing such values (they’re often called &lt;em&gt;objects&lt;/em&gt;). Fortunately, Python’s &lt;code&gt;@dataclass&lt;/code&gt; annotation automatically creates a function with the same name as the class, which takes as arguments the values contained in the class, and returns a value containing them [2]. Some code shows it more clearly:&lt;/p&gt;
&lt;p&gt;p = Person(
name=‘Albert Einstein’,
date_of_birth=Date(
day=14, month=3, year=1879))&lt;/p&gt;
&lt;p&gt;p2 = Person(
name=‘Emmy Noether’,
date_of_birth=Date(
day=23, month=3, year=1882))&lt;/p&gt;
&lt;p&gt;p3 = p2
print(p3.date_of_birth.month)Here we create some values of class &lt;code&gt;Person&lt;/code&gt; by calling the correspondingly named function, and assign them to variables. To create a &lt;code&gt;Date&lt;/code&gt;, we have to call that function instead, and pass appropriate arguments.&lt;/p&gt;
&lt;p&gt;Once we have these complex values, we can use them as a whole, like in the assignment &lt;code&gt;p3 = p2&lt;/code&gt;, or we can access some detail inside of them using the &lt;code&gt;.&lt;/code&gt; operator, as in the &lt;code&gt;print&lt;/code&gt; statement. And just like that, we’re talking about complex things like people and calendar dates!&lt;/p&gt;
&lt;p&gt;One more thing before we go. In &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;TEC 1&lt;/a&gt;, we talked about type annotations, which you can use to specify which types function arguments must have, and what the type of the return value will be. Records and (data)classes are in fact types, and you can use them to annotate functions. So given the above, you can write a function&lt;/p&gt;
&lt;p&gt;def update_date_of_birth(p: Person, d: Date) -&gt; None:
p.date_of_birth = d&lt;/p&gt;
&lt;p&gt;update_date_of_birth(p2, Date(day=23, month=3, year=1982))and have mypy check that it’s being called correctly.&lt;/p&gt;
&lt;p&gt;If you go and play around a bit with this code, you may notice that there’s some really funny business going on when you assign using whole objects and also parts of them. In the next instalment, we’ll take a look behind the scenes to see what’s actually happening inside of the computer when we make variables and complex values, and clear all that up.&lt;/p&gt;
&lt;p&gt;← &lt;a href=&quot;https://blog2.esciencecenter.nl/procedural-programming-f1d8cdef7540&quot;&gt;TEC 2: Procedural programming &lt;/a&gt;— TEC 4: &amp;#x3C;Stay tuned!&gt; →&lt;/p&gt;
&lt;p&gt;[0] At least with the calendar system currently used in the western world. There have been many calendar systems over the course of history, it’s a fascinating subject actually. If you’re ever bored, look into it!&lt;/p&gt;
&lt;p&gt;[1] Or a NamedTuple or perhaps even a dict, but a data class is the most straightforward and provides for a good starting point when we talk about classes later.&lt;/p&gt;
&lt;p&gt;[2] It’s actually a bit more complicated than that, more in a future instalment on Object Oriented Programming.&lt;/p&gt;</description><pubDate>Thu, 07 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;14&lt;/p&gt;
&lt;p&gt;The Engineering Corner&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A blog-within-a-blog on the transition from writing simple scripts for yourself to writing larger programs with and for others. TEC appears on an irregular schedule driven by workload and inspiration. (&lt;/em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;&lt;em&gt;TEC1&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, &lt;em&gt;&lt;a href=&quot;https://medium.com/escience-center/procedural-programming-f1d8cdef7540&quot;&gt;&lt;em&gt;TEC2&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;-3-variables-records-values-and-objects&quot;&gt;№ 3: Variables, Records, Values and Objects&lt;/h2&gt;
&lt;p&gt;Last time, we talked about the actions taken by scripts, and how they could be organised hierarchically using procedures. This makes it possible to split up a big problem into clearly delineated blocks with well-defined interfaces. These blocks can then be glued together into a hierarchical structure that gets complex things done in a well-organised way.&lt;/p&gt;
&lt;p&gt;However, actions are only one half of the programming equation. Procedures give us verbs, but we’re still missing nouns: data, or state. In Python, and many other languages, data is stored in &lt;em&gt;variables&lt;/em&gt;. Variables connect a name to a memory location holding a value. This connection is created by an &lt;em&gt;assignment&lt;/em&gt;. The statement &lt;code&gt;x = 1&lt;/code&gt; will create a new memory location, associate it with the name &lt;code&gt;x&lt;/code&gt;, and write the number &lt;code&gt;1&lt;/code&gt; in it. Other examples of Python values are the string &lt;code&gt;&quot;The Engineering Corner”&lt;/code&gt; and the boolean value &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Variables, Records, Values and Objects&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/variables-records-values-and-objects-ec9ee01b.CmSLy2Cc_ZHJSTb.webp&quot; srcset=&quot;&quot;&gt;
Values spilling out of a variable? Could there be a memory leak? Photo by &lt;a href=&quot;https://unsplash.com/@napender?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Napendra Singh&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Variables can be used in different ways. Often, they store the data that we are processing; after we read it from an input file, halfway through a calculation, and before we write it out again. But we also have variables that are used to control the execution of the script: loop variables, flags that keep track of whether something has happened, and so on. Sometimes, data is used to make decisions as well (“if x is negative, do this, else do that”).&lt;/p&gt;
&lt;p&gt;At any point during its execution, a program has a &lt;em&gt;state&lt;/em&gt;, which is simply the collection of all existing variables, plus an indication of the next statement to execute. Together with any future inputs, this state will determine what the program is going to do. Which branch of an if-statement is taken, how many loops a for-statement executes, it all depends on the state.&lt;/p&gt;
&lt;p&gt;As your script gets bigger it will get more and more variables, until it becomes difficult to keep track of them all. As with the actions, the solution is to organise the variables hierarchically. There are two ways to do that actually, &lt;em&gt;scopes&lt;/em&gt; and &lt;em&gt;records&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;scopes&quot;&gt;Scopes&lt;/h3&gt;
&lt;p&gt;Scopes come for free once you start making functions (procedures in &lt;a href=&quot;https://medium.com/escience-center/procedural-programming-f1d8cdef7540&quot;&gt;TEC 2&lt;/a&gt;, we’re switching back to Python terminology here and call them functions). Variables created within a function are &lt;em&gt;local&lt;/em&gt; to that function, which means that they’re only visible to statements inside of the function. In other words, they are &lt;em&gt;in the function’s scope&lt;/em&gt;. Variables that aren’t created within a function are &lt;em&gt;global&lt;/em&gt; variables, and are &lt;em&gt;in the global scope&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So, if you make functions, you’ll notice that most of your variables will end up being local variables. In fact, if you design these functions well and have them only communicate with other functions via parameters and return values, then the only global variables you’ll have are at the top level of your Python script. In Python, you &lt;em&gt;can&lt;/em&gt; actually read those global variables from inside a function, but something funny happens if you write to them:&lt;/p&gt;
&lt;p&gt;global_variable = 42&lt;/p&gt;
&lt;p&gt;def my_function() -&gt; None:
print(global_variable) # prints 42
global_variable = 43
print(global_variable) # prints 43&lt;/p&gt;
&lt;p&gt;my_function()&lt;/p&gt;
&lt;p&gt;print(global_variable) # prints 42The way this works is that if you try to use a variable, it is first looked up in the local scope you’re in. If it’s not found there, then the global scope is tried. So the first time &lt;code&gt;global_variable&lt;/code&gt; is read in &lt;code&gt;my_function&lt;/code&gt;, this is what happens. Assignment however is not affected, so on the next line a &lt;em&gt;new&lt;/em&gt; variable is made in the &lt;em&gt;local&lt;/em&gt; scope, which is called &lt;code&gt;global_variable&lt;/code&gt; and given the value 43.&lt;/p&gt;
&lt;p&gt;On the next line, this local variable is found first and its value is printed. Note that the global variable named &lt;code&gt;global_variable&lt;/code&gt; is now invisible from within &lt;code&gt;my_function&lt;/code&gt;, as it is masked or &lt;em&gt;shadowed&lt;/em&gt; by the local variable of the same name. The print statement at the end of the script isn’t in &lt;code&gt;my_function&lt;/code&gt;’s scope, so, it sees the global version of the variable, which still has the value 42.&lt;/p&gt;
&lt;p&gt;Scopes are very, very good to have when you’re making larger programs, because they decouple different parts of the state from each other. If your functions are of a reasonable length, then all the code that can possibly affect a local variable is on your screen at once, and easy to have a picture of in your head. This makes it much easier to reason about the code, something that is very important if you’re writing code that will run on someone else’s computer while you’re not around.&lt;/p&gt;
&lt;p&gt;You can in fact write to a global variable from inside of a function, but you’d have to have some very very good reasons to do so. It’s almost never good design, so I’m not going to tell you how to do it. Instead, let’s talk about records.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Variables, Records, Values and Objects&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/variables-records-values-and-objects-56480c6a.GzOIlrrD_ZwEkjh.webp&quot; srcset=&quot;&quot;&gt;
A record record has a record company, catalog number, artist, and title. Photo by &lt;a href=&quot;https://unsplash.com/@rocinante_11?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mick Haupt&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;records&quot;&gt;Records&lt;/h3&gt;
&lt;p&gt;Sometimes, one variable just isn’t enough to contain all the information you want to store about a particular thing. For example, if you need to keep track of a person, you’ll want to store their name, but maybe also their date of birth, email address, and whatever other properties are of interest to your application. And speaking of dates, those consist of a day, month and year &lt;a href=&quot;#2459&quot;&gt;[0]&lt;/a&gt;. So it seems that some way of grouping multiple variables together would be a useful language feature.&lt;/p&gt;
&lt;p&gt;Fortunately, language designers have come to the same conclusion, and have added records* (Pascal) and &lt;em&gt;structs&lt;/em&gt; (C and C++) to languages. More recent languages like Python tend to have classes instead (more on those in a future instalment), but the closest equivalents in Python would be a &lt;em&gt;dataclass&lt;/em&gt; [1]:&lt;/p&gt;
&lt;p&gt;from dataclass import dataclass&lt;/p&gt;
&lt;p&gt;@dataclass
class Date:
day: int
month: int
year: int&lt;/p&gt;
&lt;p&gt;@dataclass
class Person:
name: str
date_of_birth: DateHere we have a statement that creates a class named &lt;code&gt;Date&lt;/code&gt;, containing &lt;code&gt;day&lt;/code&gt;, &lt;code&gt;month&lt;/code&gt; and &lt;code&gt;year&lt;/code&gt; fields all of type &lt;code&gt;int&lt;/code&gt;. What does that mean? One way of looking at a class or a record is that it is a description of the structure of a certain type of complex values. So here we are saying that any value of type &lt;code&gt;Date&lt;/code&gt; must contain three subvalues with the given names, each of type &lt;code&gt;int&lt;/code&gt;. These subvalues can themselves be complex objects, as we see in class &lt;code&gt;Person&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And so here is a hierarchy again, but a different one than the hierarchy of functions. That one lets us describe complex actions as a combination of simpler actions, while this one lets us describe complex objects as combinations of simpler parts. Together, they make it possible to describe very complex programs in such a way that we can understand them one piece at a time.&lt;/p&gt;
&lt;p&gt;There’s one thing still missing though. A class is just a description of what a particular type of value looks like. In order to actually do something, we need some variables containing such values (they’re often called &lt;em&gt;objects&lt;/em&gt;). Fortunately, Python’s &lt;code&gt;@dataclass&lt;/code&gt; annotation automatically creates a function with the same name as the class, which takes as arguments the values contained in the class, and returns a value containing them [2]. Some code shows it more clearly:&lt;/p&gt;
&lt;p&gt;p = Person(
name=‘Albert Einstein’,
date_of_birth=Date(
day=14, month=3, year=1879))&lt;/p&gt;
&lt;p&gt;p2 = Person(
name=‘Emmy Noether’,
date_of_birth=Date(
day=23, month=3, year=1882))&lt;/p&gt;
&lt;p&gt;p3 = p2
print(p3.date_of_birth.month)Here we create some values of class &lt;code&gt;Person&lt;/code&gt; by calling the correspondingly named function, and assign them to variables. To create a &lt;code&gt;Date&lt;/code&gt;, we have to call that function instead, and pass appropriate arguments.&lt;/p&gt;
&lt;p&gt;Once we have these complex values, we can use them as a whole, like in the assignment &lt;code&gt;p3 = p2&lt;/code&gt;, or we can access some detail inside of them using the &lt;code&gt;.&lt;/code&gt; operator, as in the &lt;code&gt;print&lt;/code&gt; statement. And just like that, we’re talking about complex things like people and calendar dates!&lt;/p&gt;
&lt;p&gt;One more thing before we go. In &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;TEC 1&lt;/a&gt;, we talked about type annotations, which you can use to specify which types function arguments must have, and what the type of the return value will be. Records and (data)classes are in fact types, and you can use them to annotate functions. So given the above, you can write a function&lt;/p&gt;
&lt;p&gt;def update_date_of_birth(p: Person, d: Date) -&gt; None:
p.date_of_birth = d&lt;/p&gt;
&lt;p&gt;update_date_of_birth(p2, Date(day=23, month=3, year=1982))and have mypy check that it’s being called correctly.&lt;/p&gt;
&lt;p&gt;If you go and play around a bit with this code, you may notice that there’s some really funny business going on when you assign using whole objects and also parts of them. In the next instalment, we’ll take a look behind the scenes to see what’s actually happening inside of the computer when we make variables and complex values, and clear all that up.&lt;/p&gt;
&lt;p&gt;← &lt;a href=&quot;https://blog2.esciencecenter.nl/procedural-programming-f1d8cdef7540&quot;&gt;TEC 2: Procedural programming &lt;/a&gt;— TEC 4: &amp;#x3C;Stay tuned!&gt; →&lt;/p&gt;
&lt;p&gt;[0] At least with the calendar system currently used in the western world. There have been many calendar systems over the course of history, it’s a fascinating subject actually. If you’re ever bored, look into it!&lt;/p&gt;
&lt;p&gt;[1] Or a NamedTuple or perhaps even a dict, but a data class is the most straightforward and provides for a good starting point when we talk about classes later.&lt;/p&gt;
&lt;p&gt;[2] It’s actually a bit more complicated than that, more in a future instalment on Object Oriented Programming.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/variables-records-values-and-objects-ec9ee01b.CmSLy2Cc.jpg" medium="image"/><author>Lourens Veen</author></item><item><title>Beyond research</title><link>https://blog2.esciencecenter.nl/posts/2024-10-30---beyond-research</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-10-30---beyond-research</guid><description>&lt;h1 id=&quot;beyond-research&quot;&gt;&lt;strong&gt;Beyond research&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;‘Beyond research’ is a new mini-series we are starting on the eScience Center blog. We want to give you some insight into the interests, hobbies and accomplishments of our colleagues. Learn more about the writers behind our blogs and get to know them beyond the research. This first post features &lt;a href=&quot;https://blog2.esciencecenter.nl/beyond-research-e220eb18f8b4#41d4&quot;&gt;Walter Baccinelli&lt;/a&gt;, &lt;a href=&quot;https://blog2.esciencecenter.nl/beyond-research-e220eb18f8b4#0155&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; and &lt;a href=&quot;https://blog2.esciencecenter.nl/beyond-research-e220eb18f8b4#4a75&quot;&gt;Olga Lyashevska&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Walter Baccinelli: wrestling and words of wisdom**&lt;/p&gt;
&lt;p&gt;I started my path in martial arts a long time ago when I was six and had no pain in my joints. I would love, at this point, to tell an inspiring and moving story about how I found my way to the dojo and “the gentle way” (aka, Judo), but I have none. The truth is that my older sister was already practicing Judo and the gym was close by, so I joined in. It was very convenient. What is incredible is that I never left this amazing world. Judo has been my first love and a very important part of my life, but I’ve been exploring, with more or less commitment, other disciplines like Sambo, Muay Thay, Wrestling, Kung Fu, as well as traditional fighting like Shuai Jiao and Qazaq Kuresi.&lt;/p&gt;
&lt;p&gt;Since I began practicing martial arts, there have been many moments that I am proud of and that have impacted me. I started competing for fun as a kid, and more seriously as a teenager and into adulthood. I had the chance to take part in countless competitions at different levels, from very fun amateur to European and World championships and, very recently, the &lt;a href=&quot;https://worldnomadgames.kz/en&quot;&gt;World Nomad Games&lt;/a&gt; as part of the Italian national team. Regardless of the level of the competition, stepping on the mat always takes a lot of courage, and I’m proud of myself every time I decide to put on my Gi (Judo uniform) and challenge myself by fighting. Even before the fight itself, the path is hard and it takes commitment, self-sacrifice, passion and a bit of craziness. It requires constant training, always pushing yourself to your limit. It requires suffering through the fatigue and, sometimes, the injuries. It requires adjusting your whole lifestyle, fasting and resting instead of partying. It requires being ready to win, but, even more, being ready to lose despite all the work.&lt;/p&gt;
&lt;p&gt;This may sounds like an awful life. Why would any sane person consciously decide to do this? Well, it also comes with joy. Firstly, it gives you the awareness that you have what it takes to reach the goals that you set, and some self-awareness never hurts. Secondly, reaching those goals is extremely satisfying. Entering the arena wearing the colors of your nation, hearing the cheering of your teammates and winning an important medal. That’s priceless.&lt;/p&gt;
&lt;p&gt;It is clear that sport, for me, was not just a hobby or a complementary part of my life, but a totalizing activity and a way of living. Having had the privilege of experiencing the athlete’s life shaped my character and taught me a lot of lessons largely applicable to my private and work life. And no, I’m not speaking only about how to correctly punch the keyboard when a test fails with my code. Martial arts has taught me the immense value of respect. Respect for the people you train with, your teammates but even more for your opponent. I learned that an opponent is not an enemy. I learned that I cannot achieve my goals without the support of other people and that my support is fundamental for other people to reach their own goals. In Judo, you cannot train alone and you and your “Uke” (sparring partner) need each other to improve together. It’s all about collaboration and learning from other people. I learned that the higher my goals are, the harder the route to fulfill them. Failure and frustration (as well as accepting these emotions) are a part of the process, and commitment, hard work and patience (and sometimes also a bit of luck) are the tools with which I must be equipped.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beyond research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/beyond-research-1f31515b.pyM2re2S_2drxV8.webp&quot; srcset=&quot;&quot;&gt;
Walter during the World Nomad Games&lt;a href=&quot;#0155&quot;&gt;&lt;strong&gt;Carlos Martinez-Ortiz: Kendo and committing to curiosity&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I started kendo a few years ago. One of my friends had started a few weeks before and it sounded like a fun thing to do, so I joined him. A few months later, my friend stopped, because he started doing something else, but I just liked it enough to stay. Initially, I really liked the external part of it: it is very dynamic, and explosive — lots of shouting and running around. You get to wear cool armour and feel like a samurai. But over time there were other aspects that I enjoyed more — the aspect of long-term improvement and leaving the rest of the world outside when I practice.&lt;/p&gt;
&lt;p&gt;I think kendo for me has shown me some aspects of my own character.&lt;/p&gt;
&lt;p&gt;A couple of years ago, when I was preparing for a kendo exam, one of my seniors gave me some feedback on things I should improve — not only in terms of technique but also in terms of my attitude. Around the same time, I had my yearly appraisal with my line manager, and his feedback was very similar. From my perspective, what I needed to learn in kendo was the same thing I needed to learn for my personal development.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beyond research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;526&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/beyond-research-79ee2d04.89kj2-n0_Z1Yjz3k.webp&quot; srcset=&quot;&quot;&gt;
Olga Lyashevska: my Jiu-jitsu journey**&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is not about how good you get but about what you do for the community — *Carlson Gracie Jr.&lt;/p&gt;
&lt;p&gt;My jiu-jitsu journey began back in 2005 when I was at university. One day, I noticed a group of students running around in what looked like white pajamas, jumping, rolling, and clearly having fun. Intrigued, I decided to check it out since I had some free time that week.&lt;/p&gt;
&lt;p&gt;When I arrived at the gym, I figured I’d just sit back and watch a session, but to my surprise, I wasn’t allowed. “You’ve got to join in,” the teacher said. So, without much hesitation, I grabbed one of those white ‘pajamas,’ which I later learned was called a &lt;em&gt;gi&lt;/em&gt;, and picked out a random belt from a box in the corner.&lt;/p&gt;
&lt;p&gt;The class started, and we jumped right into running, tumbling, and falling all over the mats. I had no clue what I was doing. At some point, the teacher noticed the belt I had tied around my waist — it was one meant for higher-ranked students. He looked at me with a puzzled expression and asked, “What belt are you?” I hadn’t the slightest idea what to say because I hadn’t earned any belt yet, let alone the one I was wearing. It was awkward and funny, but at that moment something kickstarted in me.&lt;/p&gt;
&lt;p&gt;From that day forward, I never stopped training. Jiu -itsu became much more than just a hobby — it transformed how I approached challenges, relationships and ultimately, how I saw myself. What started as an accidental introduction became a lifelong passion that continues to shape who I am today.&lt;/p&gt;
&lt;p&gt;As time passed, my training intensified. I found myself training up to six days a week, balancing my time between judo and jiu-jitsu, and competing and refereeing in both disciplines. Along the way, I’ve had many moments I’m proud of — from winning the World and European Championships to refereeing big competitions with some of the best competitors in the world.&lt;/p&gt;
&lt;p&gt;But as much as those achievements mean to me, they pale in comparison to the joy of watching my students grow. There’s nothing quite like seeing the transformation in people. I’ve seen shy individuals blossom into confident athletes, not only excelling on the mats but also gaining a new sense of self. I’ve worked with women who’ve faced difficult challenges, and through jiu-jitsu, they’ve found strength, empowerment and a community that supports them.&lt;/p&gt;
&lt;p&gt;Recently, one such moment after a women-only jiu-jitsu class I teach in Amsterdam, as students left with smiles and a sense of accomplishment, my teacher hugged me and whispered, “you’re changing lives.”&lt;/p&gt;
&lt;p&gt;I will be competing again, and the medals and titles are great, but the real reward comes from knowing that, through jiu-jitsu, I’ve been able to help others discover their own power and confidence.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beyond research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/beyond-research-23e5eec1.CnsubD7U_1FQ9Gy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</description><pubDate>Wed, 30 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;beyond-research&quot;&gt;&lt;strong&gt;Beyond research&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;‘Beyond research’ is a new mini-series we are starting on the eScience Center blog. We want to give you some insight into the interests, hobbies and accomplishments of our colleagues. Learn more about the writers behind our blogs and get to know them beyond the research. This first post features &lt;a href=&quot;https://blog2.esciencecenter.nl/beyond-research-e220eb18f8b4#41d4&quot;&gt;Walter Baccinelli&lt;/a&gt;, &lt;a href=&quot;https://blog2.esciencecenter.nl/beyond-research-e220eb18f8b4#0155&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; and &lt;a href=&quot;https://blog2.esciencecenter.nl/beyond-research-e220eb18f8b4#4a75&quot;&gt;Olga Lyashevska&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Walter Baccinelli: wrestling and words of wisdom**&lt;/p&gt;
&lt;p&gt;I started my path in martial arts a long time ago when I was six and had no pain in my joints. I would love, at this point, to tell an inspiring and moving story about how I found my way to the dojo and “the gentle way” (aka, Judo), but I have none. The truth is that my older sister was already practicing Judo and the gym was close by, so I joined in. It was very convenient. What is incredible is that I never left this amazing world. Judo has been my first love and a very important part of my life, but I’ve been exploring, with more or less commitment, other disciplines like Sambo, Muay Thay, Wrestling, Kung Fu, as well as traditional fighting like Shuai Jiao and Qazaq Kuresi.&lt;/p&gt;
&lt;p&gt;Since I began practicing martial arts, there have been many moments that I am proud of and that have impacted me. I started competing for fun as a kid, and more seriously as a teenager and into adulthood. I had the chance to take part in countless competitions at different levels, from very fun amateur to European and World championships and, very recently, the &lt;a href=&quot;https://worldnomadgames.kz/en&quot;&gt;World Nomad Games&lt;/a&gt; as part of the Italian national team. Regardless of the level of the competition, stepping on the mat always takes a lot of courage, and I’m proud of myself every time I decide to put on my Gi (Judo uniform) and challenge myself by fighting. Even before the fight itself, the path is hard and it takes commitment, self-sacrifice, passion and a bit of craziness. It requires constant training, always pushing yourself to your limit. It requires suffering through the fatigue and, sometimes, the injuries. It requires adjusting your whole lifestyle, fasting and resting instead of partying. It requires being ready to win, but, even more, being ready to lose despite all the work.&lt;/p&gt;
&lt;p&gt;This may sounds like an awful life. Why would any sane person consciously decide to do this? Well, it also comes with joy. Firstly, it gives you the awareness that you have what it takes to reach the goals that you set, and some self-awareness never hurts. Secondly, reaching those goals is extremely satisfying. Entering the arena wearing the colors of your nation, hearing the cheering of your teammates and winning an important medal. That’s priceless.&lt;/p&gt;
&lt;p&gt;It is clear that sport, for me, was not just a hobby or a complementary part of my life, but a totalizing activity and a way of living. Having had the privilege of experiencing the athlete’s life shaped my character and taught me a lot of lessons largely applicable to my private and work life. And no, I’m not speaking only about how to correctly punch the keyboard when a test fails with my code. Martial arts has taught me the immense value of respect. Respect for the people you train with, your teammates but even more for your opponent. I learned that an opponent is not an enemy. I learned that I cannot achieve my goals without the support of other people and that my support is fundamental for other people to reach their own goals. In Judo, you cannot train alone and you and your “Uke” (sparring partner) need each other to improve together. It’s all about collaboration and learning from other people. I learned that the higher my goals are, the harder the route to fulfill them. Failure and frustration (as well as accepting these emotions) are a part of the process, and commitment, hard work and patience (and sometimes also a bit of luck) are the tools with which I must be equipped.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beyond research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;465&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/beyond-research-1f31515b.pyM2re2S_2drxV8.webp&quot; srcset=&quot;&quot;&gt;
Walter during the World Nomad Games&lt;a href=&quot;#0155&quot;&gt;&lt;strong&gt;Carlos Martinez-Ortiz: Kendo and committing to curiosity&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I started kendo a few years ago. One of my friends had started a few weeks before and it sounded like a fun thing to do, so I joined him. A few months later, my friend stopped, because he started doing something else, but I just liked it enough to stay. Initially, I really liked the external part of it: it is very dynamic, and explosive — lots of shouting and running around. You get to wear cool armour and feel like a samurai. But over time there were other aspects that I enjoyed more — the aspect of long-term improvement and leaving the rest of the world outside when I practice.&lt;/p&gt;
&lt;p&gt;I think kendo for me has shown me some aspects of my own character.&lt;/p&gt;
&lt;p&gt;A couple of years ago, when I was preparing for a kendo exam, one of my seniors gave me some feedback on things I should improve — not only in terms of technique but also in terms of my attitude. Around the same time, I had my yearly appraisal with my line manager, and his feedback was very similar. From my perspective, what I needed to learn in kendo was the same thing I needed to learn for my personal development.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beyond research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;526&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/beyond-research-79ee2d04.89kj2-n0_Z1Yjz3k.webp&quot; srcset=&quot;&quot;&gt;
Olga Lyashevska: my Jiu-jitsu journey**&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is not about how good you get but about what you do for the community — *Carlson Gracie Jr.&lt;/p&gt;
&lt;p&gt;My jiu-jitsu journey began back in 2005 when I was at university. One day, I noticed a group of students running around in what looked like white pajamas, jumping, rolling, and clearly having fun. Intrigued, I decided to check it out since I had some free time that week.&lt;/p&gt;
&lt;p&gt;When I arrived at the gym, I figured I’d just sit back and watch a session, but to my surprise, I wasn’t allowed. “You’ve got to join in,” the teacher said. So, without much hesitation, I grabbed one of those white ‘pajamas,’ which I later learned was called a &lt;em&gt;gi&lt;/em&gt;, and picked out a random belt from a box in the corner.&lt;/p&gt;
&lt;p&gt;The class started, and we jumped right into running, tumbling, and falling all over the mats. I had no clue what I was doing. At some point, the teacher noticed the belt I had tied around my waist — it was one meant for higher-ranked students. He looked at me with a puzzled expression and asked, “What belt are you?” I hadn’t the slightest idea what to say because I hadn’t earned any belt yet, let alone the one I was wearing. It was awkward and funny, but at that moment something kickstarted in me.&lt;/p&gt;
&lt;p&gt;From that day forward, I never stopped training. Jiu -itsu became much more than just a hobby — it transformed how I approached challenges, relationships and ultimately, how I saw myself. What started as an accidental introduction became a lifelong passion that continues to shape who I am today.&lt;/p&gt;
&lt;p&gt;As time passed, my training intensified. I found myself training up to six days a week, balancing my time between judo and jiu-jitsu, and competing and refereeing in both disciplines. Along the way, I’ve had many moments I’m proud of — from winning the World and European Championships to refereeing big competitions with some of the best competitors in the world.&lt;/p&gt;
&lt;p&gt;But as much as those achievements mean to me, they pale in comparison to the joy of watching my students grow. There’s nothing quite like seeing the transformation in people. I’ve seen shy individuals blossom into confident athletes, not only excelling on the mats but also gaining a new sense of self. I’ve worked with women who’ve faced difficult challenges, and through jiu-jitsu, they’ve found strength, empowerment and a community that supports them.&lt;/p&gt;
&lt;p&gt;Recently, one such moment after a women-only jiu-jitsu class I teach in Amsterdam, as students left with smiles and a sense of accomplishment, my teacher hugged me and whispered, “you’re changing lives.”&lt;/p&gt;
&lt;p&gt;I will be competing again, and the medals and titles are great, but the real reward comes from knowing that, through jiu-jitsu, I’ve been able to help others discover their own power and confidence.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Beyond research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/beyond-research-23e5eec1.CnsubD7U_1FQ9Gy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/beyond-research-1f31515b.pyM2re2S.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>From Corridor Coincidences to Cellular Cartography: The grlc Story</title><link>https://blog2.esciencecenter.nl/posts/2024-10-24---from-corridor-coincidences-to-cellular-cartography-the-grlc-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-10-24---from-corridor-coincidences-to-cellular-cartography-the-grlc-</guid><description>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;This is the story of &lt;a href=&quot;https://grlc.io/&quot;&gt;grlc&lt;/a&gt;, a tool that transforms complex linked data queries into user-friendly web interfaces. We interviewed grlc’s developers &lt;a href=&quot;https://github.com/albertmeronyo&quot;&gt;Albert Meroño-Peñuela&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt;, to explore grlc’s origins, development, and real-world impact. We’ll also hear from &lt;a href=&quot;https://github.com/bherr2&quot;&gt;Bruce Herr&lt;/a&gt;, a user from the &lt;a href=&quot;https://hubmapconsortium.org/&quot;&gt;HuBMAP&lt;/a&gt; software project who’s putting grlc to work in groundbreaking research. The story is a testament to the power of open-source collaboration and the unexpected journeys of software tools.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;515&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-cec5731c.3PE2AEFD_Z1FoTLM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@steverichey?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Steve Richey&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;part-1-in-conversation-with-grlc-developers&quot;&gt;Part 1: In Conversation with grlc Developers&lt;/h2&gt;
&lt;h3 id=&quot;q-lets-start-at-the-beginning-what-exactly-is-grlc-and-what-problem-does-it-solve-for-its-users&quot;&gt;Q: Let’s start at the beginning. What exactly is grlc, and what problem does it solve for its users?&lt;/h3&gt;
&lt;p&gt;Albert: grlc is a server that automates the publication of knowledge graph APIs. It takes SPARQL queries as input and generates a functional Open API specification without requiring any coding.&lt;/p&gt;
&lt;p&gt;Imagine you have a collection of linked data about music bands that you want to share with music enthusiasts who don’t know SPARQL. With grlc, you can write a SPARQL query to retrieve band information, put it on GitHub, and grlc will create an API that allows users to access this data using a simple URL. Users can even modify parameters in the URL to get information about different bands, effectively exploring your data without needing to understand the complexities of SPARQL.&lt;/p&gt;
&lt;p&gt;Here is a traditional SPARQL query for a linked dataset:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;598&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-2002d6ee.BSc4dvJ9_nDC9.webp&quot; srcset=&quot;&quot;&gt;
A traditional (complicated) SPARQL query without using grlcIf you are a researcher only interested in music genres, you may not have the time or energy to learn SPARQL. grlc makes it easy to do the same thing:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;581&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-5b2851f8.Bupe_3-B_1NF95P.webp&quot; srcset=&quot;&quot;&gt;
The grlc generated API for the same query displayed aboveThe output of this is a URL, through which you can view and download the data you are after:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;496&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-cc5687e2.BAA3ciX7_Z1cAtJu.webp&quot; srcset=&quot;&quot;&gt;
The URL that grlc generated through which you can access the data. You can view this data in your browser, but you can also use your favourite programming language to fetch and analyse data from different genres&lt;/p&gt;
&lt;h3 id=&quot;q-thats-quite-useful-how-did-the-idea-for-grlc-come-about&quot;&gt;Q: That’s quite useful. How did the idea for grlc come about?&lt;/h3&gt;
&lt;p&gt;Albert: The story of grlc begins in 2016. The original contributors were developers who frequently found themselves creating Open API specifications for SPARQL endpoints. Like many programmers, they were looking for ways to automate this repetitive task.&lt;/p&gt;
&lt;p&gt;While some tools existed at the time, they all had limitations — either requiring SPARQL queries to be buried in a database or failing to comply with the emerging Open API specification (then known as Swagger). Faced with these constraints, they decided to build a better solution themselves. This solution ended up becoming grlc.&lt;/p&gt;
&lt;h3 id=&quot;q-how-did-the-escience-center-play-a-role-in-the-development-of-grlc&quot;&gt;Q: How did the eScience Center play a role in the development of grlc?&lt;/h3&gt;
&lt;p&gt;Carlos: I was an eScience Center RSE at the time (now Community Manager, ed.), working on a digital humanities project, building a linked data exploration tool. The other team members on that project had diverse expertise, so they needed a way to separate concerns — front-end developers shouldn’t need to know about data storage, and data specialists shouldn’t have to worry about front-end presentation.&lt;/p&gt;
&lt;p&gt;That’s when I discovered grlc. Albert, the original grlc developer was coincidentally working just down the hall, but we had never met. I started contributing to improve the codebase, bridging the gap between our two teams.&lt;/p&gt;
&lt;p&gt;After that project concluded, another colleague at the eScience Center began &lt;a href=&quot;https://research-software-directory.org/projects/candygene&quot;&gt;candYgene&lt;/a&gt;: a life sciences project using linked data. I suggested using grlc, and as they reported issues and suggested improvements, we kept enhancing the tool. It’s been a rewarding cycle of continuous improvement driven by real-world use cases.&lt;/p&gt;
&lt;h3 id=&quot;q-its-fascinating-to-see-how-tools-evolve-in-practice-how-is-grlc-being-used-now-and-how-do-you-track-its-adoption&quot;&gt;Q: It’s fascinating to see how tools evolve in practice. How is grlc being used now, and how do you track its adoption?&lt;/h3&gt;
&lt;p&gt;Carlos: One of the exciting aspects of open-source development is seeing your creation take on a life of its own. We often discover new use cases when users report issues or reach out for support.&lt;/p&gt;
&lt;p&gt;A particularly interesting example is &lt;a href=&quot;https://hubmapconsortium.org&quot;&gt;HuBMAP&lt;/a&gt; (the Human Biomolecular Atlas Program) using grlc in their groundbreaking work. It’s rewarding to see our tool contributing to such important scientific endeavors, especially ones we never anticipated when we first started development.&lt;/p&gt;
&lt;h2 id=&quot;part-2-grlc-in-action--a-conversation-with-a-hubmap-user&quot;&gt;Part 2: grlc in Action — A Conversation with a HuBMAP User&lt;/h2&gt;
&lt;h3 id=&quot;q-can-you-tell-us-a-bit-about-what-hubmap-is-and-what-youre-working-on&quot;&gt;Q: Can you tell us a bit about what HuBMAP is and what you’re working on?&lt;/h3&gt;
&lt;p&gt;Bruce: &lt;a href=&quot;https://hubmapconsortium.org&quot;&gt;HuBMAP&lt;/a&gt;, or the Human Biomolecular Atlas Program, is an NIH-funded consortium with an ambitious goal: building a comprehensive map of the human body at the cellular level.&lt;/p&gt;
&lt;p&gt;I’m part of the &lt;a href=&quot;https://cns.iu.edu&quot;&gt;Indiana University&lt;/a&gt; Mapping Component, where we’re creating the &lt;a href=&quot;https://humanatlas.io/&quot;&gt;Human Reference Atlas&lt;/a&gt; (HRA). It’s a fascinating project that combines ontologies, expert-curated data (including 2D and 3D anatomical imagery), and experimental data from various providers. The end result is an interconnected map of the human body that’s opening new frontiers in biomedical research.&lt;/p&gt;
&lt;h3 id=&quot;q-that-sounds-like-complex-and-important-work-how-does-grlc-fit-into-this-picture&quot;&gt;Q: That sounds like complex and important work. How does grlc fit into this picture?&lt;/h3&gt;
&lt;p&gt;Bruce: grlc has become an important tool for us. The HRA is built as a &lt;a href=&quot;https://lod.humanatlas.io/&quot;&gt;set of RDF graphs&lt;/a&gt;, which allows us to represent complex relationships in our data. However, we often get requests for specific data from researchers who may not be familiar with SPARQL or RDF.&lt;/p&gt;
&lt;p&gt;This is where grlc comes in handy. We can write a SPARQL query to extract the requested data, and grlc transforms that into a user-friendly interface and API. It’s accessible to both programmers and non-programmers, which is crucial given the diverse backgrounds of our collaborators and data users.&lt;/p&gt;
&lt;h3 id=&quot;q-so-grlc-is-bridging-the-gap-between-your-complex-data-structure-and-the-end-users-who-need-that-data-what-specific-capabilities-has-grlc-unlocked-for-your-team&quot;&gt;Q: So grlc is bridging the gap between your complex data structure and the end-users who need that data. What specific capabilities has grlc unlocked for your team?&lt;/h3&gt;
&lt;p&gt;Bruce: The key advantage is that grlc allows us to maintain our data in a rich, expressive format (RDF) while still providing straightforward reports and interfaces for our end users. It’s lowered the barrier for getting derived data products out to folks who need them.&lt;/p&gt;
&lt;p&gt;Before grlc, there was often a tension between having a powerful, flexible data structure and providing easy access to that data. grlc helps resolve that tension. We can focus on creating comprehensive RDF graphs and writing powerful SPARQL queries and be confident that we can easily share the results with collaborators who might not have the same technical background.&lt;/p&gt;
&lt;h3 id=&quot;q-how-did-you-first-discover-grlc&quot;&gt;Q: How did you first discover grlc?&lt;/h3&gt;
&lt;p&gt;Bruce: It was actually through a collaboration. Around 2022, we were working with EBI (European Bioinformatics Institute), one of our partners. We noticed they were using this tool called grlc for their Ubergraph project. At the time, we had our own SPARQL server and were looking for better ways to share queries and data. After seeing how effectively EBI was using grlc, we decided to &lt;a href=&quot;https://github.com/hubmapconsortium/ccf-grlc/&quot;&gt;give it a try&lt;/a&gt;. Now we’re using it for sharing queries and data in our CCF (Common Coordinate Framework) project.&lt;/p&gt;
&lt;h3 id=&quot;q-looking-ahead-do-you-see-the-sustainability-of-tools-like-grlc-as-a-potential-consideration-for-large-scale-projects-like-hubmap&quot;&gt;Q: Looking ahead, do you see the &lt;a href=&quot;https://xkcd.com/2347/&quot;&gt;sustainability&lt;/a&gt; of tools like grlc as a potential consideration for large-scale projects like HuBMAP?&lt;/h3&gt;
&lt;p&gt;Bruce : It’s definitely something we think about. The continued development and maintenance of grlc is valuable to HuBMAP and the HRA project. While we could theoretically pivot to another technology if needed, grlc has become an important part of our workflow.&lt;/p&gt;
&lt;p&gt;It’s a good example of how open-source tools can become key components of scientific projects. We appreciate the work the grlc team has done and continues to do. Their efforts are helping to advance not just our project, but potentially many others in the scientific community.&lt;/p&gt;
&lt;p&gt;Interview by Lieke de Boer*&lt;/p&gt;</description><pubDate>Thu, 24 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;This is the story of &lt;a href=&quot;https://grlc.io/&quot;&gt;grlc&lt;/a&gt;, a tool that transforms complex linked data queries into user-friendly web interfaces. We interviewed grlc’s developers &lt;a href=&quot;https://github.com/albertmeronyo&quot;&gt;Albert Meroño-Peñuela&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt;, to explore grlc’s origins, development, and real-world impact. We’ll also hear from &lt;a href=&quot;https://github.com/bherr2&quot;&gt;Bruce Herr&lt;/a&gt;, a user from the &lt;a href=&quot;https://hubmapconsortium.org/&quot;&gt;HuBMAP&lt;/a&gt; software project who’s putting grlc to work in groundbreaking research. The story is a testament to the power of open-source collaboration and the unexpected journeys of software tools.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;515&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-cec5731c.3PE2AEFD_Z1FoTLM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@steverichey?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Steve Richey&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;part-1-in-conversation-with-grlc-developers&quot;&gt;Part 1: In Conversation with grlc Developers&lt;/h2&gt;
&lt;h3 id=&quot;q-lets-start-at-the-beginning-what-exactly-is-grlc-and-what-problem-does-it-solve-for-its-users&quot;&gt;Q: Let’s start at the beginning. What exactly is grlc, and what problem does it solve for its users?&lt;/h3&gt;
&lt;p&gt;Albert: grlc is a server that automates the publication of knowledge graph APIs. It takes SPARQL queries as input and generates a functional Open API specification without requiring any coding.&lt;/p&gt;
&lt;p&gt;Imagine you have a collection of linked data about music bands that you want to share with music enthusiasts who don’t know SPARQL. With grlc, you can write a SPARQL query to retrieve band information, put it on GitHub, and grlc will create an API that allows users to access this data using a simple URL. Users can even modify parameters in the URL to get information about different bands, effectively exploring your data without needing to understand the complexities of SPARQL.&lt;/p&gt;
&lt;p&gt;Here is a traditional SPARQL query for a linked dataset:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;598&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-2002d6ee.BSc4dvJ9_nDC9.webp&quot; srcset=&quot;&quot;&gt;
A traditional (complicated) SPARQL query without using grlcIf you are a researcher only interested in music genres, you may not have the time or energy to learn SPARQL. grlc makes it easy to do the same thing:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;581&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-5b2851f8.Bupe_3-B_1NF95P.webp&quot; srcset=&quot;&quot;&gt;
The grlc generated API for the same query displayed aboveThe output of this is a URL, through which you can view and download the data you are after:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;From Corridor Coincidences to Cellular Cartography: The grlc Story&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;496&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-cc5687e2.BAA3ciX7_Z1cAtJu.webp&quot; srcset=&quot;&quot;&gt;
The URL that grlc generated through which you can access the data. You can view this data in your browser, but you can also use your favourite programming language to fetch and analyse data from different genres&lt;/p&gt;
&lt;h3 id=&quot;q-thats-quite-useful-how-did-the-idea-for-grlc-come-about&quot;&gt;Q: That’s quite useful. How did the idea for grlc come about?&lt;/h3&gt;
&lt;p&gt;Albert: The story of grlc begins in 2016. The original contributors were developers who frequently found themselves creating Open API specifications for SPARQL endpoints. Like many programmers, they were looking for ways to automate this repetitive task.&lt;/p&gt;
&lt;p&gt;While some tools existed at the time, they all had limitations — either requiring SPARQL queries to be buried in a database or failing to comply with the emerging Open API specification (then known as Swagger). Faced with these constraints, they decided to build a better solution themselves. This solution ended up becoming grlc.&lt;/p&gt;
&lt;h3 id=&quot;q-how-did-the-escience-center-play-a-role-in-the-development-of-grlc&quot;&gt;Q: How did the eScience Center play a role in the development of grlc?&lt;/h3&gt;
&lt;p&gt;Carlos: I was an eScience Center RSE at the time (now Community Manager, ed.), working on a digital humanities project, building a linked data exploration tool. The other team members on that project had diverse expertise, so they needed a way to separate concerns — front-end developers shouldn’t need to know about data storage, and data specialists shouldn’t have to worry about front-end presentation.&lt;/p&gt;
&lt;p&gt;That’s when I discovered grlc. Albert, the original grlc developer was coincidentally working just down the hall, but we had never met. I started contributing to improve the codebase, bridging the gap between our two teams.&lt;/p&gt;
&lt;p&gt;After that project concluded, another colleague at the eScience Center began &lt;a href=&quot;https://research-software-directory.org/projects/candygene&quot;&gt;candYgene&lt;/a&gt;: a life sciences project using linked data. I suggested using grlc, and as they reported issues and suggested improvements, we kept enhancing the tool. It’s been a rewarding cycle of continuous improvement driven by real-world use cases.&lt;/p&gt;
&lt;h3 id=&quot;q-its-fascinating-to-see-how-tools-evolve-in-practice-how-is-grlc-being-used-now-and-how-do-you-track-its-adoption&quot;&gt;Q: It’s fascinating to see how tools evolve in practice. How is grlc being used now, and how do you track its adoption?&lt;/h3&gt;
&lt;p&gt;Carlos: One of the exciting aspects of open-source development is seeing your creation take on a life of its own. We often discover new use cases when users report issues or reach out for support.&lt;/p&gt;
&lt;p&gt;A particularly interesting example is &lt;a href=&quot;https://hubmapconsortium.org&quot;&gt;HuBMAP&lt;/a&gt; (the Human Biomolecular Atlas Program) using grlc in their groundbreaking work. It’s rewarding to see our tool contributing to such important scientific endeavors, especially ones we never anticipated when we first started development.&lt;/p&gt;
&lt;h2 id=&quot;part-2-grlc-in-action--a-conversation-with-a-hubmap-user&quot;&gt;Part 2: grlc in Action — A Conversation with a HuBMAP User&lt;/h2&gt;
&lt;h3 id=&quot;q-can-you-tell-us-a-bit-about-what-hubmap-is-and-what-youre-working-on&quot;&gt;Q: Can you tell us a bit about what HuBMAP is and what you’re working on?&lt;/h3&gt;
&lt;p&gt;Bruce: &lt;a href=&quot;https://hubmapconsortium.org&quot;&gt;HuBMAP&lt;/a&gt;, or the Human Biomolecular Atlas Program, is an NIH-funded consortium with an ambitious goal: building a comprehensive map of the human body at the cellular level.&lt;/p&gt;
&lt;p&gt;I’m part of the &lt;a href=&quot;https://cns.iu.edu&quot;&gt;Indiana University&lt;/a&gt; Mapping Component, where we’re creating the &lt;a href=&quot;https://humanatlas.io/&quot;&gt;Human Reference Atlas&lt;/a&gt; (HRA). It’s a fascinating project that combines ontologies, expert-curated data (including 2D and 3D anatomical imagery), and experimental data from various providers. The end result is an interconnected map of the human body that’s opening new frontiers in biomedical research.&lt;/p&gt;
&lt;h3 id=&quot;q-that-sounds-like-complex-and-important-work-how-does-grlc-fit-into-this-picture&quot;&gt;Q: That sounds like complex and important work. How does grlc fit into this picture?&lt;/h3&gt;
&lt;p&gt;Bruce: grlc has become an important tool for us. The HRA is built as a &lt;a href=&quot;https://lod.humanatlas.io/&quot;&gt;set of RDF graphs&lt;/a&gt;, which allows us to represent complex relationships in our data. However, we often get requests for specific data from researchers who may not be familiar with SPARQL or RDF.&lt;/p&gt;
&lt;p&gt;This is where grlc comes in handy. We can write a SPARQL query to extract the requested data, and grlc transforms that into a user-friendly interface and API. It’s accessible to both programmers and non-programmers, which is crucial given the diverse backgrounds of our collaborators and data users.&lt;/p&gt;
&lt;h3 id=&quot;q-so-grlc-is-bridging-the-gap-between-your-complex-data-structure-and-the-end-users-who-need-that-data-what-specific-capabilities-has-grlc-unlocked-for-your-team&quot;&gt;Q: So grlc is bridging the gap between your complex data structure and the end-users who need that data. What specific capabilities has grlc unlocked for your team?&lt;/h3&gt;
&lt;p&gt;Bruce: The key advantage is that grlc allows us to maintain our data in a rich, expressive format (RDF) while still providing straightforward reports and interfaces for our end users. It’s lowered the barrier for getting derived data products out to folks who need them.&lt;/p&gt;
&lt;p&gt;Before grlc, there was often a tension between having a powerful, flexible data structure and providing easy access to that data. grlc helps resolve that tension. We can focus on creating comprehensive RDF graphs and writing powerful SPARQL queries and be confident that we can easily share the results with collaborators who might not have the same technical background.&lt;/p&gt;
&lt;h3 id=&quot;q-how-did-you-first-discover-grlc&quot;&gt;Q: How did you first discover grlc?&lt;/h3&gt;
&lt;p&gt;Bruce: It was actually through a collaboration. Around 2022, we were working with EBI (European Bioinformatics Institute), one of our partners. We noticed they were using this tool called grlc for their Ubergraph project. At the time, we had our own SPARQL server and were looking for better ways to share queries and data. After seeing how effectively EBI was using grlc, we decided to &lt;a href=&quot;https://github.com/hubmapconsortium/ccf-grlc/&quot;&gt;give it a try&lt;/a&gt;. Now we’re using it for sharing queries and data in our CCF (Common Coordinate Framework) project.&lt;/p&gt;
&lt;h3 id=&quot;q-looking-ahead-do-you-see-the-sustainability-of-tools-like-grlc-as-a-potential-consideration-for-large-scale-projects-like-hubmap&quot;&gt;Q: Looking ahead, do you see the &lt;a href=&quot;https://xkcd.com/2347/&quot;&gt;sustainability&lt;/a&gt; of tools like grlc as a potential consideration for large-scale projects like HuBMAP?&lt;/h3&gt;
&lt;p&gt;Bruce : It’s definitely something we think about. The continued development and maintenance of grlc is valuable to HuBMAP and the HRA project. While we could theoretically pivot to another technology if needed, grlc has become an important part of our workflow.&lt;/p&gt;
&lt;p&gt;It’s a good example of how open-source tools can become key components of scientific projects. We appreciate the work the grlc team has done and continues to do. Their efforts are helping to advance not just our project, but potentially many others in the scientific community.&lt;/p&gt;
&lt;p&gt;Interview by Lieke de Boer*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/from-corridor-coincidences-to-cellular-c-cec5731c.3PE2AEFD.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>The magic of teaching about the anti-magic of generative AI</title><link>https://blog2.esciencecenter.nl/posts/2024-10-03---the-magic-of-teaching-about-the-anti-magic-of-generative-ai</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-10-03---the-magic-of-teaching-about-the-anti-magic-of-generative-ai</guid><description>&lt;p&gt;On the use and abuse of generative artificial intelligence by students&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1750&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Kj-xgUZwT-yLWAbb-1b9e9f52.CaD9LNVx_1zkuYs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Owen Beard on Unsplash&lt;/p&gt;
&lt;p&gt;Recently, I taught the pilot workshop &lt;a href=&quot;https://www.esciencecenter.nl/event/pilot-medical-image-processing/&quot;&gt;Medical Image Processing in Python&lt;/a&gt;. The room was full of post-docs, research software engineers and even faculty, but mostly young PhD candidates or freshly minted PhDs. Although the Netherlands eScience Center offers many courses and workshops, most are established. Many are based on existing &lt;a href=&quot;https://carpentries.org/&quot;&gt;Carpentries&lt;/a&gt; materials that are taught globally. Recognizing a large gap in the existing curriculum in terms of computational medical image processing, the Netherlands eScience Center embraced the idea of starting some sort of workshop about it. Part of the gap, in my opinion, was a lack of a curriculum that addressed generative AI.&lt;/p&gt;
&lt;p&gt;A few brave engineers at the Center designed their own workshops. This year, I did just that, and the process was at once terrifying and energizing. On the weekend before the course, I literally had a nightmare that the students would revolt during the workshop. I dreamt about angry PhDs in computer science yelling at me and the other course developer, a biomedical engineer, literally standing up during my MRI lecture, eyes rolling and correcting me about how spin echo MRI sequences were made.&lt;/p&gt;
&lt;p&gt;By the end of the day, none of this had happened, yet I expected the students to be exhausted and perhaps annoyed. I had stuck a segment on generative AI onto the end of the day, and was dedicated to teaching it, but feared the student revolt of my nightmares might still be coming.&lt;/p&gt;
&lt;p&gt;The role of instructor or faculty can often seem like a bit of a sham in the world of computation-driven health sciences research, and particularly any kind of medical signal processing. On the one hand, the theory behind signal processing is something instructors need to teach to students. On the other hand, all of the theory now needs to be implemented in the digital world, and the ability to implement anything with code well does not seem to track with rank. I have been around this part of academia long enough to know that the pattern is that often students should be teaching the teachers about technology, even if on paper it is the other way around. Would the students be annoyed about the relatively high amount of time we assigned to learn basic code for things like registration and segmentation?&lt;/p&gt;
&lt;p&gt;Or would they just be exhausted? After all, since morning we had all written lots of code, accomplishing many non-trivial feats like &lt;a href=&quot;https://esciencecenter-digital-skills.github.io/medical-image-processing/simpleitk.html&quot;&gt;visualizing image registration in SITK&lt;/a&gt; and augmenting a dataset for machine learning. As I rounded the corner towards the end, showing what &lt;a href=&quot;https://pydicom.github.io/pydicom/stable/index.html#&quot;&gt;pydicom&lt;/a&gt; could do in terms of anonymizing DICOM metadata, I realized I had an urgent last message to impart. How would I ever make people continue to pay attention?&lt;/p&gt;
&lt;p&gt;I took a breath and wondered if the students would start walking out, ready to leave after making it through most of the day. None of them did. Instead, to my surprise, students began engaging more during my last lecture. I could see them thinking about what I was saying.&lt;/p&gt;
&lt;p&gt;Perhaps the topic of generative AI was not as ‘last year’ as I had imagined. I thought everyone had discussed generative AI to death at this point, and certainly, I wouldn’t point out anything younger people didn’t already know. I feared that I might seem like a grandma to them, still mystified and confused by the remote control. It turns out I was wrong about all of that.&lt;/p&gt;
&lt;p&gt;I began my generative AI lecture by showcasing some absolute failures from a well-known generative algorithm in terms of radiological image generation. I showed how even with specific, correctly spelled prompts, I could get back imaging that looked like a computer graphical rendering from 1986 of a circle when prompting about things like an MRI of polycystic kidneys.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;542&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SjLUqHDcUb0oqKPd4QRmyQ-34a1bbb0.F-0zC_qZ_YT8xe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image generated in response to prompt for a T2 MRI axial slice of polycystic kidney disease&lt;/p&gt;
&lt;p&gt;I then showed some of the coding fails I have seen other people create with ChatGPT. The code I showed was far from ready to run, but it was what I had seen. The code began with approximately the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;path_to_niftis &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Z&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;directory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectoy3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;path_to_meta_data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; directory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectoy5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;variable_1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; some_never_specified_variable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def funct1&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  for variable_1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  sub_folder &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; some_other_never_specified_variable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sadly, the code did not improve from there. I then pointed out to the students that in both cases the problem here was that anyone had ever taken these outputs (the bad image and the bad code) seriously. Unfortunately, someone had, in the case of the code, and they approached me to review what they had prompted. With one glance, I asked, disingenuously “Did you actually run this?” knowing that at least half the lines would fail to run given that they included variables that were never assigned.&lt;/p&gt;
&lt;p&gt;Afterward, I immediately wrote down some notes for my upcoming lecture. I stumbled upon yet another perfect example of one of the counter-intuitive problems of generative AI that I see all the time. To use these algorithms properly, you need to have deep knowledge of what you expect them to generate. At least in the field of medical imaging research, you cannot leapfrog over learning how to code or spending time with radiologists and pathologists to understand what proper images look like. If you are expert enough at coding, generative models can save you time by helping you debug and write boring code quickly (or so I hear from my more skilled colleagues who use these things). Now there is even &lt;a href=&quot;http://dx.doi.org/10.2139/ssrn.4945566&quot;&gt;some science behind such claims&lt;/a&gt;, although the obvious conflicts of interest should have been stated explicitly in the linked article. But if you have not developed certain skills, generative AI will not necessarily save you time, as opposed to say getting people to share their data and code with you.&lt;/p&gt;
&lt;p&gt;Unfortunately, I suspect the sudden uptick in student attention and involvement was not a reflection of my teaching. Ask anyone who teaches graduate students these days, and you will likely hear some stories about ChatGPT or Copilot or some other generative algorithm. Students have embraced these tools as if they were a sort of digital magic even though &lt;a href=&quot;https://blog.esciencecenter.nl/language-modeling-the-first-100-years-357556816148&quot;&gt;there is nothing magical about these models&lt;/a&gt;. Speak the right spell over the bubbling pot, or server in this case, and the entire world will change into a place where you solve all problems in time to spend hours doing something other than studying and learning. The promise that seems to have been marketed is that not only will your code be written and your work done, but you will be transformed into a wizard who can warp the time-space continuum in such a way that you get free time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;602&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sfx6zP0DpHT0OnE9XPlgmA-549d87d7.DtJhIfcM_xLfYO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image generated by Openart.ai after several prompts by the author&lt;/p&gt;
&lt;p&gt;There is a bit of truth to this idea. What I didn’t tell the students is that code is by far the easy case. Here even a mediocre engineer can deploy a bit of witchcraft and potentially transform AI-generated code into something usable. The witchcraft is manual and automated testing. Sometimes all you have to do to improve AI-generated code is to try to get it to run and to write some tests for it. Many of my colleagues are actually getting some useful results out of generative tools.&lt;/p&gt;
&lt;p&gt;With images, things get murkier. There is some published work showing that there are &lt;a href=&quot;https://www.nature.com/articles/s41467-021-27577-x&quot;&gt;synthetic images good enough so that even expert radiologists&lt;/a&gt; could not detect that they were not real. But radiologists are not computers, and typically not engineers either. Rumor has it that in some unpublished studies, while the radiologists were fooled, the software engineers were not. They had seen so much of their own work they could recognize it. I suspect that in terms of machine learning features, generative algorithms might be able to create subtly detectable differences, and therefore a machine learning algorithm could potentially encode some bizarre unintended biases based on these features. I gave the students a more obvious example of potentially doubling down on biases in mammography. What if you want to balance a dataset with more breast cancer samples but all the synthetic data you create shows low-density, relatively fatty, breasts? Then you can potentially increase the correlation between this low density and breast cancer in your dataset. This kind of problem would be fairly easy for human eyes to see, but what about more subtle ones?&lt;/p&gt;
&lt;p&gt;Alas, there are, as of yet, no magic-based solutions to some problems we face in medical imaging research. Maybe the younger generation, today’s students are still hoping for this, because some basic tasks in research now do have solutions that work at astounding speed. Computation on modern computers seems like magic, especially if you do not see GPUs, but hear about some mystical cloud where these things live. The mistake I have seen students make is to double down on generative AI. “I must not be prompting this correctly”, they say when things go wrong, based on the assumption that with the right spell, precisely the code and images they want will appear. But could they even recognize them as such if they did?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The mistake I have seen students make is to double down on generative AI. “I must not be prompting this correctly”, they say when things go wrong, based on the assumption that with the right spell, precisely the code and images they want will appear. But could they even recognize them as such if they did?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is some level of debate in education about the relative importance of teaching facts and information as opposed to teaching methods and skills for discovery. Some people even argued that learning information was already obsolete in the era of search engines and instant access to information. Potentially generative AI is a method of discovery that can amplify anyone’s capabilities. However, I would argue that some amount of foundational information is necessary to get the most from generative tools. What I hope anyone educating university students reading this will take away from learning about my experience is that addressing the issues of Generative AI head-on will make your students stop playing with ChatGPT, sit up, and listen. And maybe even rededicate themselves to including alternative, older forms of knowledge acquisition alongside embracing generative-based methods. Whatever the case, talking about this stuff seems to have almost supernatural effects.&lt;/p&gt;</description><pubDate>Thu, 03 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;On the use and abuse of generative artificial intelligence by students&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1750&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Kj-xgUZwT-yLWAbb-1b9e9f52.CaD9LNVx_1zkuYs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Owen Beard on Unsplash&lt;/p&gt;
&lt;p&gt;Recently, I taught the pilot workshop &lt;a href=&quot;https://www.esciencecenter.nl/event/pilot-medical-image-processing/&quot;&gt;Medical Image Processing in Python&lt;/a&gt;. The room was full of post-docs, research software engineers and even faculty, but mostly young PhD candidates or freshly minted PhDs. Although the Netherlands eScience Center offers many courses and workshops, most are established. Many are based on existing &lt;a href=&quot;https://carpentries.org/&quot;&gt;Carpentries&lt;/a&gt; materials that are taught globally. Recognizing a large gap in the existing curriculum in terms of computational medical image processing, the Netherlands eScience Center embraced the idea of starting some sort of workshop about it. Part of the gap, in my opinion, was a lack of a curriculum that addressed generative AI.&lt;/p&gt;
&lt;p&gt;A few brave engineers at the Center designed their own workshops. This year, I did just that, and the process was at once terrifying and energizing. On the weekend before the course, I literally had a nightmare that the students would revolt during the workshop. I dreamt about angry PhDs in computer science yelling at me and the other course developer, a biomedical engineer, literally standing up during my MRI lecture, eyes rolling and correcting me about how spin echo MRI sequences were made.&lt;/p&gt;
&lt;p&gt;By the end of the day, none of this had happened, yet I expected the students to be exhausted and perhaps annoyed. I had stuck a segment on generative AI onto the end of the day, and was dedicated to teaching it, but feared the student revolt of my nightmares might still be coming.&lt;/p&gt;
&lt;p&gt;The role of instructor or faculty can often seem like a bit of a sham in the world of computation-driven health sciences research, and particularly any kind of medical signal processing. On the one hand, the theory behind signal processing is something instructors need to teach to students. On the other hand, all of the theory now needs to be implemented in the digital world, and the ability to implement anything with code well does not seem to track with rank. I have been around this part of academia long enough to know that the pattern is that often students should be teaching the teachers about technology, even if on paper it is the other way around. Would the students be annoyed about the relatively high amount of time we assigned to learn basic code for things like registration and segmentation?&lt;/p&gt;
&lt;p&gt;Or would they just be exhausted? After all, since morning we had all written lots of code, accomplishing many non-trivial feats like &lt;a href=&quot;https://esciencecenter-digital-skills.github.io/medical-image-processing/simpleitk.html&quot;&gt;visualizing image registration in SITK&lt;/a&gt; and augmenting a dataset for machine learning. As I rounded the corner towards the end, showing what &lt;a href=&quot;https://pydicom.github.io/pydicom/stable/index.html#&quot;&gt;pydicom&lt;/a&gt; could do in terms of anonymizing DICOM metadata, I realized I had an urgent last message to impart. How would I ever make people continue to pay attention?&lt;/p&gt;
&lt;p&gt;I took a breath and wondered if the students would start walking out, ready to leave after making it through most of the day. None of them did. Instead, to my surprise, students began engaging more during my last lecture. I could see them thinking about what I was saying.&lt;/p&gt;
&lt;p&gt;Perhaps the topic of generative AI was not as ‘last year’ as I had imagined. I thought everyone had discussed generative AI to death at this point, and certainly, I wouldn’t point out anything younger people didn’t already know. I feared that I might seem like a grandma to them, still mystified and confused by the remote control. It turns out I was wrong about all of that.&lt;/p&gt;
&lt;p&gt;I began my generative AI lecture by showcasing some absolute failures from a well-known generative algorithm in terms of radiological image generation. I showed how even with specific, correctly spelled prompts, I could get back imaging that looked like a computer graphical rendering from 1986 of a circle when prompting about things like an MRI of polycystic kidneys.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;542&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SjLUqHDcUb0oqKPd4QRmyQ-34a1bbb0.F-0zC_qZ_YT8xe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image generated in response to prompt for a T2 MRI axial slice of polycystic kidney disease&lt;/p&gt;
&lt;p&gt;I then showed some of the coding fails I have seen other people create with ChatGPT. The code I showed was far from ready to run, but it was what I had seen. The code began with approximately the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;path_to_niftis &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Z&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;directory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectoy3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;path_to_meta_data &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; directory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectory4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;subdirectoy5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;variable_1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; some_never_specified_variable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def funct1&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  for variable_1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  sub_folder &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; some_other_never_specified_variable&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sadly, the code did not improve from there. I then pointed out to the students that in both cases the problem here was that anyone had ever taken these outputs (the bad image and the bad code) seriously. Unfortunately, someone had, in the case of the code, and they approached me to review what they had prompted. With one glance, I asked, disingenuously “Did you actually run this?” knowing that at least half the lines would fail to run given that they included variables that were never assigned.&lt;/p&gt;
&lt;p&gt;Afterward, I immediately wrote down some notes for my upcoming lecture. I stumbled upon yet another perfect example of one of the counter-intuitive problems of generative AI that I see all the time. To use these algorithms properly, you need to have deep knowledge of what you expect them to generate. At least in the field of medical imaging research, you cannot leapfrog over learning how to code or spending time with radiologists and pathologists to understand what proper images look like. If you are expert enough at coding, generative models can save you time by helping you debug and write boring code quickly (or so I hear from my more skilled colleagues who use these things). Now there is even &lt;a href=&quot;http://dx.doi.org/10.2139/ssrn.4945566&quot;&gt;some science behind such claims&lt;/a&gt;, although the obvious conflicts of interest should have been stated explicitly in the linked article. But if you have not developed certain skills, generative AI will not necessarily save you time, as opposed to say getting people to share their data and code with you.&lt;/p&gt;
&lt;p&gt;Unfortunately, I suspect the sudden uptick in student attention and involvement was not a reflection of my teaching. Ask anyone who teaches graduate students these days, and you will likely hear some stories about ChatGPT or Copilot or some other generative algorithm. Students have embraced these tools as if they were a sort of digital magic even though &lt;a href=&quot;https://blog.esciencecenter.nl/language-modeling-the-first-100-years-357556816148&quot;&gt;there is nothing magical about these models&lt;/a&gt;. Speak the right spell over the bubbling pot, or server in this case, and the entire world will change into a place where you solve all problems in time to spend hours doing something other than studying and learning. The promise that seems to have been marketed is that not only will your code be written and your work done, but you will be transformed into a wizard who can warp the time-space continuum in such a way that you get free time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;602&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sfx6zP0DpHT0OnE9XPlgmA-549d87d7.DtJhIfcM_xLfYO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image generated by Openart.ai after several prompts by the author&lt;/p&gt;
&lt;p&gt;There is a bit of truth to this idea. What I didn’t tell the students is that code is by far the easy case. Here even a mediocre engineer can deploy a bit of witchcraft and potentially transform AI-generated code into something usable. The witchcraft is manual and automated testing. Sometimes all you have to do to improve AI-generated code is to try to get it to run and to write some tests for it. Many of my colleagues are actually getting some useful results out of generative tools.&lt;/p&gt;
&lt;p&gt;With images, things get murkier. There is some published work showing that there are &lt;a href=&quot;https://www.nature.com/articles/s41467-021-27577-x&quot;&gt;synthetic images good enough so that even expert radiologists&lt;/a&gt; could not detect that they were not real. But radiologists are not computers, and typically not engineers either. Rumor has it that in some unpublished studies, while the radiologists were fooled, the software engineers were not. They had seen so much of their own work they could recognize it. I suspect that in terms of machine learning features, generative algorithms might be able to create subtly detectable differences, and therefore a machine learning algorithm could potentially encode some bizarre unintended biases based on these features. I gave the students a more obvious example of potentially doubling down on biases in mammography. What if you want to balance a dataset with more breast cancer samples but all the synthetic data you create shows low-density, relatively fatty, breasts? Then you can potentially increase the correlation between this low density and breast cancer in your dataset. This kind of problem would be fairly easy for human eyes to see, but what about more subtle ones?&lt;/p&gt;
&lt;p&gt;Alas, there are, as of yet, no magic-based solutions to some problems we face in medical imaging research. Maybe the younger generation, today’s students are still hoping for this, because some basic tasks in research now do have solutions that work at astounding speed. Computation on modern computers seems like magic, especially if you do not see GPUs, but hear about some mystical cloud where these things live. The mistake I have seen students make is to double down on generative AI. “I must not be prompting this correctly”, they say when things go wrong, based on the assumption that with the right spell, precisely the code and images they want will appear. But could they even recognize them as such if they did?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The mistake I have seen students make is to double down on generative AI. “I must not be prompting this correctly”, they say when things go wrong, based on the assumption that with the right spell, precisely the code and images they want will appear. But could they even recognize them as such if they did?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is some level of debate in education about the relative importance of teaching facts and information as opposed to teaching methods and skills for discovery. Some people even argued that learning information was already obsolete in the era of search engines and instant access to information. Potentially generative AI is a method of discovery that can amplify anyone’s capabilities. However, I would argue that some amount of foundational information is necessary to get the most from generative tools. What I hope anyone educating university students reading this will take away from learning about my experience is that addressing the issues of Generative AI head-on will make your students stop playing with ChatGPT, sit up, and listen. And maybe even rededicate themselves to including alternative, older forms of knowledge acquisition alongside embracing generative-based methods. Whatever the case, talking about this stuff seems to have almost supernatural effects.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_SjLUqHDcUb0oqKPd4QRmyQ-34a1bbb0.F-0zC_qZ.png" medium="image"/><author>Candace Moore</author></item><item><title>National Research Software Day: National Infrastructures for Sustainable Software</title><link>https://blog2.esciencecenter.nl/posts/2024-09-19---national-research-software-day-national-infrastructures-for-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-09-19---national-research-software-day-national-infrastructures-for-</guid><description>&lt;p&gt;*Written by &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/luisa-orozco/&quot;&gt;&lt;em&gt;Luisa Orozco&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://danielagawehns.github.io/&quot;&gt;&lt;em&gt;Daniela Gawehns&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and *&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first &lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day&lt;/a&gt; already took place more than five months ago in Hilversum, on 23 April 2024. Following an inspiring keynote by Rogier Kievit, several parallel sessions competed for the attention of participants. This blog covers the ‘National infrastructures for sustainable software’ session.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;National Research Software Day: National Infrastructures for Sustainable Software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/national-research-software-day-national--8a937220.BjtgdaL6_hKCo.webp&quot; srcset=&quot;&quot;&gt;
This session was a follow-up from a &lt;a href=&quot;https://blog2.esciencecenter.nl/open-science-festival-what-infrastructures-do-we-need-to-preserve-research-software-7c181404f310&quot;&gt;similar session&lt;/a&gt; that took place during the &lt;a href=&quot;https://opensciencefestival.nl/&quot;&gt;Dutch Open Science Festival&lt;/a&gt; in 2023. On this occasion, the format was the same: a series of panel pitches, followed by a group discussion. The panel shared their insights and experiences related to infrastructure used for creating and maintaining sustainable research software. The composition of the panel was different on this occasion, so the discussion took a different direction.&lt;/p&gt;
&lt;p&gt;Luisa Orozco, RSE at the Netherlands eScience Center, led the discussion.&lt;/p&gt;
&lt;p&gt;After the session, the panelists were also interviewed by Peter Schmidt for the &lt;a href=&quot;https://codeforthought.buzzsprout.com/1326658/15210839-en-a-national-day-for-research-software-the-escience-center&quot;&gt;Code for Thought Podcast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;National Research Software Day: National Infrastructures for Sustainable Software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/national-research-software-day-national--912a8b8f.B554FYB3_Z1o2JrB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;panel-composition-and-introduction&quot;&gt;Panel composition and introduction&lt;/h2&gt;
&lt;h3 id=&quot;elaine-van-ommen-kloeke-arise&quot;&gt;Elaine van Ommen Kloeke, ARISE&lt;/h3&gt;
&lt;p&gt;At Naturalis we build a digital infrastructure for recognizing species biodiversity. Data is huge, vertebrates, plants, insects, fungi. It is a huge challenge to capture, store and move data.&lt;/p&gt;
&lt;h3 id=&quot;louise-bezuidenhout-cwts-leiden-university&quot;&gt;Louise Bezuidenhout, CWTS Leiden University&lt;/h3&gt;
&lt;p&gt;Senior researcher focusing on Open Science monitoring and the evolution of Open Science infrastructures. The CWTS publishes the annual Leiden University rankings using Open Data, based on the Leiden manifesto which advocates for open and transparent research assessments moving beyond the normal metrics.&lt;/p&gt;
&lt;h3 id=&quot;jason-maassen-research-software-directory&quot;&gt;Jason Maassen, Research Software Directory&lt;/h3&gt;
&lt;p&gt;Jason is a Technology Lead at the Netherlands eScience Center supporting and helping researchers develop software. The eScience Center leads the Research Software Directory (RSD), a platform developed to highlight the roles of RSEs in research through links between software and other kinds of research outputs such as datasets, publications, research activities, projects and people.&lt;/p&gt;
&lt;h3 id=&quot;roel-janssen-4turesearchdata&quot;&gt;Roel Janssen, 4TU.ResearchData&lt;/h3&gt;
&lt;p&gt;4TU.ResearchData stores, archives and publishes datasets for technical universities in the Netherlands. I have the opportunity to work together at the National level with, for example, the RSD, to implement APIs and standards to help the deployability of research data and software.&lt;/p&gt;
&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Which kind of software, or which kind of infrastructure do you need in your day-to-day work or your institutes?&lt;/em&gt;**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine:&lt;/em&gt; There’s nothing standard that we can use. Some parts we can reuse and are open-source, while others have to be built from scratch. I need data storage, computing, dimension systems, PID identification systems, authentication, authorization and I need it to be user-friendly and encourage collaboration.&lt;/p&gt;
&lt;p&gt;*Louise: *I need access to data and knowledge graphs that we can use for our meta-research.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How does the RSD and 4TU cater to the needs that researchers have in terms of infrastructure? Which niche or which solution are you targeting?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason:&lt;/em&gt; With the RSD, we link software to other research outputs and activities, integrating information needed for institute assessment. Also, it is a useful tool for researchers to find software.&lt;/p&gt;
&lt;p&gt;*Roel: *At 4TU we offer data and software repositories, more data storage is a common request. We also offer computation environments such that a given code can be run alongside the data.&lt;/p&gt;
&lt;p&gt;We also strive for recognition of good software, so that a user can find and reuse the software. We also try to make data publications more attractive to researchers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;When using those infrastructures, what are the boundaries or limitations that you encounter? For example national vs international, or open/closed/paid.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;*Elaine: *My first criterion is ‘does it get the job done’? Ideally open and reusable.&lt;/p&gt;
&lt;p&gt;*Louise: *I work with computer scientists examining how accessible these infrastructures are to users globally. We have used VPNs to access resources and found significant variability not only in terms of access speed but also in geographical accessibility. This variability raises questions about the impact of resource location, funding models, and user requirements on accessibility. We need to critically evaluate the geopolitical landscape surrounding infrastructure choices, take the example of GitHub, which is inaccessible to users in countries currently under financial sanction by the US.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;From more of a provider side: What are your boundaries or limitations? How do you decide who is your public and how far can you get?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel, you mentioned new features that the users were requesting. How do you handle those requests?&lt;/em&gt;**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel:&lt;/em&gt; We do receive more feature requests than we can implement due to limited manpower. To manage this, we prioritize based on ease of implementation, sometimes responding quickly and other times taking longer due to extensive planning required. At community events like those within 4TU, we prioritize requests from partners, universities, and funders, addressing recurring ones promptly. Additionally, we anticipate future needs by observing trends in software usage, implementing APIs for upcoming demands even before they are explicitly requested. It’s a balancing act between fulfilling immediate requests and anticipating long-term needs to stay ahead of the curve.&lt;/p&gt;
&lt;h2 id=&quot;questions-from-the-public&quot;&gt;Questions from the public&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GitHub plays a central role in software development and it is a potential point of failure: it is centralized in nature, American-owned and has the possibility of being closed down, similar to what happened with Google Code. This is a vulnerability not just for the Netherlands but globally. How can these risks be mitigated?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel:&lt;/em&gt; There was a similar issue in the past with SVN and SourceForge. Unlike then, modern version control systems like Git offer a distributed model, where each developer has a complete copy of the source code, making it easier to switch platforms if needed. SoftwareHeritage also stores a copy of everything stored on GitHub. However, transferring auxiliary components like Wikis and issues remains a challenge. Continuous integration tools like GitHub Actions, while powerful, can be proprietary and tied to specific platforms, raising concerns about dependence on a single provider.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Louise&lt;/em&gt;: Now that the OpenScience movement is gaining momentum, the Open Science community should have a better dialogue with companies such as GitHub, and together find a suitable way of working. This type of change has already started, for example, with the publishing industries which have also been changing in this direction. The decision to create a national dataverse is also an outcome of these dialogues.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: You do see a lot of organizations looking for alternatives, for example, running local GitLab instances. But these alternatives also take time and cost money. When organizations realize how much time and effort it costs, they often back off and turn back to commercial providers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine&lt;/em&gt;: It depends on what you are trying to achieve. I could run my own data management system, but then I would need 15 dedicated engineers, and I only have two. I want those two to focus on other things. It is a bit of a balance between being principled and being pragmatic. There needs to be a conversation between research-performing organizations and commercial companies. I have no problem using a commercial company, as long as I keep the option to move my data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There is an issue with depending on commercial companies, because if, for example, they change their license, you may need to change things in your own software. The same applies if they change formats — I have a lot of data from 30 years ago in Microsoft formats that I am unable to read anymore. You are putting yourself at risk!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine&lt;/em&gt;: It is the same story with a Discman, it is the natural evolution of products and services that occurs everywhere, all the time. We now no longer use Discman today, but rather we use Spotify. We still listen to music, but if you insist on sticking with a Discman and are not prepared to move to new tech, you can get stuck. It is not something that applies to commercial products only. It is a risk that exists and that you need to take into account and plan for sufficiently in advance. You need to be aware of what risks exist, and what alternatives are available.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: Maybe it is preferable to keep options as generic as possible. So instead of having a button that says “link with GitHub” have a more generic “link with any git version control”. It is useful to show which options you provide and that there are alternatives.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you think having a centralized way of operation is the solution?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: For many types of infrastructure, perhaps that would be a viable option. That would be the case for a national PID system. It is the type of infrastructure that everybody needs, but nobody wants to build it or pay for it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: Maybe in terms of standards, if we have a well-defined standard and many options of implementation, then that would be the best.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is there a way to see at an institutional level how much data and software have been produced? For example, PURE registers all your publications, but for data and software, it is not done as much.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: For publications, publishers harvest and analyze this information. Technically, it is not that hard to do, but it is not consistently done for data and software. One thing we have done is look at OpenAlex and try to connect all of these resources and figure out if we can identify citations for software. What you see is that there are many citations for publications, some citations for datasets and very few citations for software.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Louise&lt;/em&gt;: At CWTS we are looking into this, and we’ve been working with the Center for Digital Scholarship, but we do not have solutions yet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At Digital Humanities Lab we are looking into how to make our software more visible. But if we offload all the metadata to the RSD, how many people will use it? You also need to engage in how to make users find it. For developers, the incentive to create software is knowing it will be used.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: We are currently working with different communities to create community-specific views, the goal is that communities themselves curate the content by ensuring keywords are relevant for the target users. We are also looking into integrating the RSD with search engine tools so that software can be found more easily.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is the bus-factor for the RSD/4TU.ResearchData? What challenges do you face in increasing it?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: Currently, at the eScience Center the bus-factor is three. This is a great increase from one, which is what it was a few years ago. We are also collaborating with other organizations in Germany, which increases it. But finding someone to keep pushing the software remains a difficult challenge.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: Our bus factor is two and a half or three, spread over multiple people over the team. We do not have enough money available to grow the team, but we do have multiple people who understand how everything works.&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;What would you like participants of this session to remember as their take home message. Something you would still like to say?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine&lt;/em&gt;: Keep talking! People hate meetings, but getting together is how people share ideas, especially across domains but also for setting standards.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Louise&lt;/em&gt;: Keep talking, also to people who you never talked to before. The range of stakeholders in science is very broad: it is not limited to academia, not limited to the Netherlands.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: Recognition not only for those developing great research software but also for those engaging in promoting best practices, infrastructures and in setting standards.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: For me, if you have any ideas on how to improve repositories please get in touch!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you to all of our panellists for their participation. These are a lot of topics that are very interesting for us and it is great we could have this nice conversation!&lt;/strong&gt;&lt;/p&gt;</description><pubDate>Thu, 19 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;*Written by &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/luisa-orozco/&quot;&gt;&lt;em&gt;Luisa Orozco&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://danielagawehns.github.io/&quot;&gt;&lt;em&gt;Daniela Gawehns&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and *&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first &lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day&lt;/a&gt; already took place more than five months ago in Hilversum, on 23 April 2024. Following an inspiring keynote by Rogier Kievit, several parallel sessions competed for the attention of participants. This blog covers the ‘National infrastructures for sustainable software’ session.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;National Research Software Day: National Infrastructures for Sustainable Software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/national-research-software-day-national--8a937220.BjtgdaL6_hKCo.webp&quot; srcset=&quot;&quot;&gt;
This session was a follow-up from a &lt;a href=&quot;https://blog2.esciencecenter.nl/open-science-festival-what-infrastructures-do-we-need-to-preserve-research-software-7c181404f310&quot;&gt;similar session&lt;/a&gt; that took place during the &lt;a href=&quot;https://opensciencefestival.nl/&quot;&gt;Dutch Open Science Festival&lt;/a&gt; in 2023. On this occasion, the format was the same: a series of panel pitches, followed by a group discussion. The panel shared their insights and experiences related to infrastructure used for creating and maintaining sustainable research software. The composition of the panel was different on this occasion, so the discussion took a different direction.&lt;/p&gt;
&lt;p&gt;Luisa Orozco, RSE at the Netherlands eScience Center, led the discussion.&lt;/p&gt;
&lt;p&gt;After the session, the panelists were also interviewed by Peter Schmidt for the &lt;a href=&quot;https://codeforthought.buzzsprout.com/1326658/15210839-en-a-national-day-for-research-software-the-escience-center&quot;&gt;Code for Thought Podcast&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;National Research Software Day: National Infrastructures for Sustainable Software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/national-research-software-day-national--912a8b8f.B554FYB3_Z1o2JrB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;panel-composition-and-introduction&quot;&gt;Panel composition and introduction&lt;/h2&gt;
&lt;h3 id=&quot;elaine-van-ommen-kloeke-arise&quot;&gt;Elaine van Ommen Kloeke, ARISE&lt;/h3&gt;
&lt;p&gt;At Naturalis we build a digital infrastructure for recognizing species biodiversity. Data is huge, vertebrates, plants, insects, fungi. It is a huge challenge to capture, store and move data.&lt;/p&gt;
&lt;h3 id=&quot;louise-bezuidenhout-cwts-leiden-university&quot;&gt;Louise Bezuidenhout, CWTS Leiden University&lt;/h3&gt;
&lt;p&gt;Senior researcher focusing on Open Science monitoring and the evolution of Open Science infrastructures. The CWTS publishes the annual Leiden University rankings using Open Data, based on the Leiden manifesto which advocates for open and transparent research assessments moving beyond the normal metrics.&lt;/p&gt;
&lt;h3 id=&quot;jason-maassen-research-software-directory&quot;&gt;Jason Maassen, Research Software Directory&lt;/h3&gt;
&lt;p&gt;Jason is a Technology Lead at the Netherlands eScience Center supporting and helping researchers develop software. The eScience Center leads the Research Software Directory (RSD), a platform developed to highlight the roles of RSEs in research through links between software and other kinds of research outputs such as datasets, publications, research activities, projects and people.&lt;/p&gt;
&lt;h3 id=&quot;roel-janssen-4turesearchdata&quot;&gt;Roel Janssen, 4TU.ResearchData&lt;/h3&gt;
&lt;p&gt;4TU.ResearchData stores, archives and publishes datasets for technical universities in the Netherlands. I have the opportunity to work together at the National level with, for example, the RSD, to implement APIs and standards to help the deployability of research data and software.&lt;/p&gt;
&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Which kind of software, or which kind of infrastructure do you need in your day-to-day work or your institutes?&lt;/em&gt;**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine:&lt;/em&gt; There’s nothing standard that we can use. Some parts we can reuse and are open-source, while others have to be built from scratch. I need data storage, computing, dimension systems, PID identification systems, authentication, authorization and I need it to be user-friendly and encourage collaboration.&lt;/p&gt;
&lt;p&gt;*Louise: *I need access to data and knowledge graphs that we can use for our meta-research.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How does the RSD and 4TU cater to the needs that researchers have in terms of infrastructure? Which niche or which solution are you targeting?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason:&lt;/em&gt; With the RSD, we link software to other research outputs and activities, integrating information needed for institute assessment. Also, it is a useful tool for researchers to find software.&lt;/p&gt;
&lt;p&gt;*Roel: *At 4TU we offer data and software repositories, more data storage is a common request. We also offer computation environments such that a given code can be run alongside the data.&lt;/p&gt;
&lt;p&gt;We also strive for recognition of good software, so that a user can find and reuse the software. We also try to make data publications more attractive to researchers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;When using those infrastructures, what are the boundaries or limitations that you encounter? For example national vs international, or open/closed/paid.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;*Elaine: *My first criterion is ‘does it get the job done’? Ideally open and reusable.&lt;/p&gt;
&lt;p&gt;*Louise: *I work with computer scientists examining how accessible these infrastructures are to users globally. We have used VPNs to access resources and found significant variability not only in terms of access speed but also in geographical accessibility. This variability raises questions about the impact of resource location, funding models, and user requirements on accessibility. We need to critically evaluate the geopolitical landscape surrounding infrastructure choices, take the example of GitHub, which is inaccessible to users in countries currently under financial sanction by the US.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;From more of a provider side: What are your boundaries or limitations? How do you decide who is your public and how far can you get?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel, you mentioned new features that the users were requesting. How do you handle those requests?&lt;/em&gt;**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel:&lt;/em&gt; We do receive more feature requests than we can implement due to limited manpower. To manage this, we prioritize based on ease of implementation, sometimes responding quickly and other times taking longer due to extensive planning required. At community events like those within 4TU, we prioritize requests from partners, universities, and funders, addressing recurring ones promptly. Additionally, we anticipate future needs by observing trends in software usage, implementing APIs for upcoming demands even before they are explicitly requested. It’s a balancing act between fulfilling immediate requests and anticipating long-term needs to stay ahead of the curve.&lt;/p&gt;
&lt;h2 id=&quot;questions-from-the-public&quot;&gt;Questions from the public&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GitHub plays a central role in software development and it is a potential point of failure: it is centralized in nature, American-owned and has the possibility of being closed down, similar to what happened with Google Code. This is a vulnerability not just for the Netherlands but globally. How can these risks be mitigated?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel:&lt;/em&gt; There was a similar issue in the past with SVN and SourceForge. Unlike then, modern version control systems like Git offer a distributed model, where each developer has a complete copy of the source code, making it easier to switch platforms if needed. SoftwareHeritage also stores a copy of everything stored on GitHub. However, transferring auxiliary components like Wikis and issues remains a challenge. Continuous integration tools like GitHub Actions, while powerful, can be proprietary and tied to specific platforms, raising concerns about dependence on a single provider.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Louise&lt;/em&gt;: Now that the OpenScience movement is gaining momentum, the Open Science community should have a better dialogue with companies such as GitHub, and together find a suitable way of working. This type of change has already started, for example, with the publishing industries which have also been changing in this direction. The decision to create a national dataverse is also an outcome of these dialogues.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: You do see a lot of organizations looking for alternatives, for example, running local GitLab instances. But these alternatives also take time and cost money. When organizations realize how much time and effort it costs, they often back off and turn back to commercial providers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine&lt;/em&gt;: It depends on what you are trying to achieve. I could run my own data management system, but then I would need 15 dedicated engineers, and I only have two. I want those two to focus on other things. It is a bit of a balance between being principled and being pragmatic. There needs to be a conversation between research-performing organizations and commercial companies. I have no problem using a commercial company, as long as I keep the option to move my data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There is an issue with depending on commercial companies, because if, for example, they change their license, you may need to change things in your own software. The same applies if they change formats — I have a lot of data from 30 years ago in Microsoft formats that I am unable to read anymore. You are putting yourself at risk!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine&lt;/em&gt;: It is the same story with a Discman, it is the natural evolution of products and services that occurs everywhere, all the time. We now no longer use Discman today, but rather we use Spotify. We still listen to music, but if you insist on sticking with a Discman and are not prepared to move to new tech, you can get stuck. It is not something that applies to commercial products only. It is a risk that exists and that you need to take into account and plan for sufficiently in advance. You need to be aware of what risks exist, and what alternatives are available.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: Maybe it is preferable to keep options as generic as possible. So instead of having a button that says “link with GitHub” have a more generic “link with any git version control”. It is useful to show which options you provide and that there are alternatives.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you think having a centralized way of operation is the solution?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: For many types of infrastructure, perhaps that would be a viable option. That would be the case for a national PID system. It is the type of infrastructure that everybody needs, but nobody wants to build it or pay for it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: Maybe in terms of standards, if we have a well-defined standard and many options of implementation, then that would be the best.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is there a way to see at an institutional level how much data and software have been produced? For example, PURE registers all your publications, but for data and software, it is not done as much.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: For publications, publishers harvest and analyze this information. Technically, it is not that hard to do, but it is not consistently done for data and software. One thing we have done is look at OpenAlex and try to connect all of these resources and figure out if we can identify citations for software. What you see is that there are many citations for publications, some citations for datasets and very few citations for software.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Louise&lt;/em&gt;: At CWTS we are looking into this, and we’ve been working with the Center for Digital Scholarship, but we do not have solutions yet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At Digital Humanities Lab we are looking into how to make our software more visible. But if we offload all the metadata to the RSD, how many people will use it? You also need to engage in how to make users find it. For developers, the incentive to create software is knowing it will be used.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: We are currently working with different communities to create community-specific views, the goal is that communities themselves curate the content by ensuring keywords are relevant for the target users. We are also looking into integrating the RSD with search engine tools so that software can be found more easily.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is the bus-factor for the RSD/4TU.ResearchData? What challenges do you face in increasing it?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: Currently, at the eScience Center the bus-factor is three. This is a great increase from one, which is what it was a few years ago. We are also collaborating with other organizations in Germany, which increases it. But finding someone to keep pushing the software remains a difficult challenge.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: Our bus factor is two and a half or three, spread over multiple people over the team. We do not have enough money available to grow the team, but we do have multiple people who understand how everything works.&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;What would you like participants of this session to remember as their take home message. Something you would still like to say?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Elaine&lt;/em&gt;: Keep talking! People hate meetings, but getting together is how people share ideas, especially across domains but also for setting standards.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Louise&lt;/em&gt;: Keep talking, also to people who you never talked to before. The range of stakeholders in science is very broad: it is not limited to academia, not limited to the Netherlands.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jason&lt;/em&gt;: Recognition not only for those developing great research software but also for those engaging in promoting best practices, infrastructures and in setting standards.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Roel&lt;/em&gt;: For me, if you have any ideas on how to improve repositories please get in touch!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you to all of our panellists for their participation. These are a lot of topics that are very interesting for us and it is great we could have this nice conversation!&lt;/strong&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/national-research-software-day-national--8a937220.BjtgdaL6.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>(Un)wieldy workflows with WRF</title><link>https://blog2.esciencecenter.nl/posts/2024-09-05---unwieldy-workflows-with-wrf</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-09-05---unwieldy-workflows-with-wrf</guid><description>&lt;h1 id=&quot;unwieldy-workflows-with-wrf&quot;&gt;&lt;strong&gt;(Un)wieldy workflows with WRF&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;streamlining-experiments-with-the-weather-research-and-forecasting-model&quot;&gt;&lt;strong&gt;Streamlining experiments with the Weather Research and Forecasting model&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.mmm.ucar.edu/models/wrf&quot;&gt;Weather Research and Forecasting model&lt;/a&gt;, WRF for short, is a beautiful piece of research software with a large community of active users. That’s something we love and advocate for at the eScience Center.&lt;/p&gt;
&lt;p&gt;Given its large user base, one might think this must be an exemplary model to work with. And perhaps it is, in comparison to other models in the scene. But as I’m working with WRF again after several years, I’m reminded of my struggles in keeping my workflows organized.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;(Un)wieldy workflows with WRF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;386&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-b6e59d0c.B5Z5PUNe_Z1p8i5Q.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@hdbernd?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Bernd 📷 Dittrich&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To try and tackle this issue once and for all, we experimented with different solutions, including a simple shell script, as well as &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/&quot;&gt;Snakemake&lt;/a&gt;, a python-based workflow management tool often used in bioinformatics. Both approaches turn out to have their own merits and quirks.&lt;/p&gt;
&lt;p&gt;Overall, we did get a better grip on the antipatterns that prevented us from keeping a nice and orderly workflow. From this, we extracted some best practices for managing complex (WRF) modelling workflows. This blogpost documents our journey and the lessons learned, in the hope that it will be useful for other WRF users and those who struggle with managing their experiments.&lt;/p&gt;
&lt;h2 id=&quot;running-basic-wrf&quot;&gt;Running basic WRF**&lt;/h2&gt;
&lt;p&gt;Let’s start with an overview of the steps required to run a basic WRF (real data) experiment, as per the instructions in the &lt;a href=&quot;https://www2.mmm.ucar.edu/wrf/users/wrf_users_guide/build/html/wps.html&quot;&gt;user guide&lt;/a&gt;. First you must run the WRF preprocessing system (WPS), which itself consists of three programs: geogrid, ungrib, and metgrid. Then you run WRF itself, which also consists of two programs: real and wrf.&lt;/p&gt;
&lt;p&gt;cd WPS**&lt;/p&gt;
&lt;h1 id=&quot;run-geogrid-interpolate-spatial-datasets-to-the-model-grid&quot;&gt;Run geogrid (interpolate spatial datasets to the model grid)&lt;/h1&gt;
&lt;p&gt;./geogrid.exe&lt;/p&gt;
&lt;h1 id=&quot;run-ungrib-unpack-meteorological-input-data&quot;&gt;Run ungrib (unpack meteorological input data)&lt;/h1&gt;
&lt;p&gt;./link_grib.csh /your/meteo/data/dir
ln -s ungrib/Variable_Tables/Vtable.GFS Vtable
./ungrib.exe&lt;/p&gt;
&lt;h1 id=&quot;run-metgrid-interpolate-the-meteo-data-to-model-grid&quot;&gt;Run metgrid (interpolate the meteo data to model grid)&lt;/h1&gt;
&lt;p&gt;./metgrid.exe&lt;/p&gt;
&lt;p&gt;cd ../WRF/run&lt;/p&gt;
&lt;h1 id=&quot;run-real-extract-initial-and-boundary-fields-from-preprocessed-data&quot;&gt;Run real (extract initial and boundary fields from preprocessed data)&lt;/h1&gt;
&lt;p&gt;ln -sf ../../WPS/met_em* .
./real.exe&lt;/p&gt;
&lt;h1 id=&quot;run-wrf-the-actual-forecast&quot;&gt;Run WRF (the actual forecast)&lt;/h1&gt;
&lt;p&gt;./wrf.exeThis workflow is not great in several ways. WRF and WPS are run in different working directories; yet they “pretend” to be in the same directory by use of symbolic links (&lt;code&gt;ln&lt;/code&gt;). Also, exectuables are in the same directory as the input/output data. Now, imagine, for example, that we want to do multiple experiments with slightly different settings.&lt;/p&gt;
&lt;p&gt;One option would be to move the output to a separate directory between each run. We would need to meticulously bookkeep our files, especially since runs may fail at different stages causing us to re-run (part of) the workflow. Also, we would not be able run the experiments in parallel. Clearly, using WRF in this way is a labour-intensive, error-prone process.&lt;/p&gt;
&lt;p&gt;Alternatively, we could duplicate our &lt;code&gt;WPS&lt;/code&gt;and &lt;code&gt;WRF/run&lt;/code&gt;directories. That’s also not great: imagine we want to re-run our experiments with a re-compiled version of WRF. Then we would need to copy over the new executables to all experiment directories.&lt;/p&gt;
&lt;p&gt;Finally, there’s lots of files in these directories that are not needed for our experiments, which makes it hard to tell the wheat from the chaff.&lt;/p&gt;
&lt;h3 id=&quot;our-workflow-wishlist&quot;&gt;Our workflow wishlist**&lt;/h3&gt;
&lt;p&gt;Considering the points above, let’s think about how we would like it to be, and start a workflow wishlist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each/all experiment(s) can be re-run with a single command&lt;/li&gt;
&lt;li&gt;One directory per experiment, containing config + output&lt;/li&gt;
&lt;li&gt;Intermediate/output data well organized in subdirectories&lt;/li&gt;
&lt;li&gt;Config files (namelists) specify paths to all relevant input data; no links&lt;/li&gt;
&lt;li&gt;Executables should be in a system path or another dedicated location&lt;/li&gt;
&lt;li&gt;We should be able to (re-)run only part of a workflow&lt;/li&gt;
&lt;li&gt;Bonus: reuse intermediate files that are the same for all experiments&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solution-1-using-a-shell-script&quot;&gt;&lt;strong&gt;Solution #1: using a shell script&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Let’s see how far we can get with a simple shell script. In this example, we maintain multiple namelists and geogrid tables for each experiment. These are stored alongside the shell script and copied over to the experiment folder once the script is run. The full code is available &lt;a href=&quot;https://github.com/Urban-M4/wrf-runner&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;some-initialization-of-the-environment-module-loads-etc-&quot;&gt;Some initialization of the environment, module loads etc.**# …&lt;/h1&gt;
&lt;h1 id=&quot;set-path-to-executables&quot;&gt;Set path to executables&lt;/h1&gt;
&lt;p&gt;WPS_HOME=&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;HOME/wrf-model/WPS
WRF_HOME=&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;HOME/wrf-model/WRF&lt;/p&gt;
&lt;h1 id=&quot;define-experiment-name&quot;&gt;Define experiment name&lt;/h1&gt;
&lt;p&gt;EXP=USGS&lt;/p&gt;
&lt;h1 id=&quot;make-new-experiment-directory&quot;&gt;Make new experiment directory&lt;/h1&gt;
&lt;p&gt;export RUNDIR=wrf_experiments/&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{EXP}
mkdir -p &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7778em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;mk&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR
mkdir &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;RUNDIR/geogrid
mkdir &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;mk&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/metgrid&lt;/p&gt;
&lt;h1 id=&quot;copy-experiment-dependent-files&quot;&gt;Copy experiment-dependent files&lt;/h1&gt;
&lt;p&gt;cp namelist.wps_&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;EXP &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/namelist.wps
cp namelist.input_&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;EXP &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/namelist.input
cp GEOGRID.TBL.ARW_&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;EXP &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/GEOGRID.TBL&lt;/p&gt;
&lt;h1 id=&quot;copy-additional-input-files-from-wrfwps&quot;&gt;Copy additional input files from WRF/WPS&lt;/h1&gt;
&lt;p&gt;cd &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;RUNDIR
cp &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WPS_HOME/metgrid/METGRID.TBL.ARW METGRID.TBL
cp &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WPS_HOME/ungrid/Variable_Tables/Vtable.ECMWF VTable
cp &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;iab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WRF_HOME/run/CAMtr_volume_mixing_ratio.RCP8.5 CAMtr_volume_mixing_ratio
cp &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WRF_HOME/run/ozone* .
cp &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;oz&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∗&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WRF_HOME/run/RRTMG* .
cp $WRF_HOME/run/*.TBL .&lt;/p&gt;
&lt;h1 id=&quot;run-experiments&quot;&gt;Run experiments&lt;/h1&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WPS_HOME/link_grib.csh &quot;path/to/our/input/data/*&quot;
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0361em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ib&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cs&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∗&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WPS_HOME/ungrib.exe
&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;&amp;#x26;&amp;#x27; at position 47: …R&amp;#x22; geogrid.log &amp;#x26;̲amp;&amp;#x26;amp; echo …&quot; style=&quot;color:#cc0000&quot;&gt;WPS_HOME/geogrid.exe
grep &quot;ERROR&quot; geogrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in geogrid.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1
&lt;/span&gt;WPS_HOME/metgrid.exe
grep “ERROR” metgrid.log &amp;#x26;&amp;#x26; echo “Aborting: ERROR in metgrid.log.” &amp;#x26;&amp;#x26; exit 1&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WRF_HOME/run/real.exe
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WRF_HOME/run/wrf.exeEvidently, WRF and WPS &lt;em&gt;can&lt;/em&gt; be run from another directory, by calling them by their full path. Alternatively, we could have added the &lt;code&gt;WPS&lt;/code&gt; and &lt;code&gt;WRF/run&lt;/code&gt; directories to our &lt;code&gt;PATH&lt;/code&gt; variable. However, WRF and WPS expect certain files (tables etc.) in the working directory, so we need to copy those.&lt;/p&gt;
&lt;p&gt;Geogrid and metgrid tables are expected in subfolders, but we can use the namelist setting &lt;code&gt;opt_geogrid_table_path=&apos;.&apos;&lt;/code&gt; (default is &lt;code&gt;&apos;./geogrid&apos;&lt;/code&gt;) to overwrite that, and similar for metgrid. Geogrid will then look in that folder for a file called &lt;code&gt;GEOGRID.TBL&lt;/code&gt;. (Why not simply point to the geogrid table directly in the namelist?)&lt;/p&gt;
&lt;p&gt;We were able to declutter our working directory somewhat by using the namelist.wps options &lt;code&gt;opt_output_from_geogrid_path&lt;/code&gt; and similar for metgrid. Unfortunately, that option is not available for ungrib, the worst clutterer of all… We were able to point &lt;code&gt;real.exe&lt;/code&gt; to our metgrid subfolder through the namelist.input parameter &lt;code&gt;[auxinput1_inname](https://github.com/wrf-model/WRF/blob/0a11865f97680fdd6865b278ea29d910e5db3ed7/run/README.namelist#L89)&lt;/code&gt;, so we could skip that linking step as well.&lt;/p&gt;
&lt;p&gt;We wanted the workflow to fail when one of the steps fails. However, metgrid and geogrid &lt;a href=&quot;https://github.com/wrf-model/WPS/issues/252#issue-2315032244&quot;&gt;don’t fail with a proper exit code&lt;/a&gt;. As a simple patch, we added extra commands to look for errors in the log files and raise an exception when needed.&lt;/p&gt;
&lt;p&gt;Despite some peculiarities, this is a good start. We can already tick some of the items off our wishlist. However, the workflow quickly becomes more complex. For example, as we are adding more experiments, we would like to edit the namelists programmatically. And for some runs, we may want to run an intermediate step (e.g. wudapt-to-wrf). Before we know it, the shell script becomes messy, which defeats our purpose of maintaining a tidy and organized workflow.&lt;/p&gt;
&lt;p&gt;To summarize, the following namelist parameters should probably be much better advertised:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;opt_geogrid_table_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opt_metgrid_table_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opt_output_from_geogrid_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opt_output_from_metgrid_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[auxinput1_inname](https://github.com/wrf-model/WRF/blob/0a11865f97680fdd6865b278ea29d910e5db3ed7/run/README.namelist#L89)&lt;/code&gt; (namelist.input)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a similar option for ungrib, the WRF experience would already be much better.&lt;/p&gt;
&lt;h2 id=&quot;solution-2-using-snakemake&quot;&gt;Solution #2: using Snakemake**&lt;/h2&gt;
&lt;p&gt;Ideally, we want to be able to run only part of a workflow. For example, when &lt;code&gt;real.exe&lt;/code&gt; fails, we don’t want to re-run WPS. Similarly, we may want to run all pre-processing first, and then submit WRF as a batch job.&lt;/p&gt;
&lt;h3 id=&quot;brief-intro-to-snakemake&quot;&gt;Brief intro to Snakemake&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;(Un)wieldy workflows with WRF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;177&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-ef7a50be.BXCuInXQ_Z1i0EU1.webp&quot; srcset=&quot;&quot;&gt;
Example Snakemake rules (source &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/project_info/faq.html#what-is-the-key-idea-of-snakemake-workflows&quot;&gt;https://snakemake.readthedocs.io/en/stable/project_info/faq.html#what-is-the-key-idea-of-snakemake-workflows&lt;/a&gt;)A snakemake workflow, aka ‘Snakefile’, consists of rules. Each rule has certain inputs and outputs, and the commands to produce that output, either in Python code (a &lt;code&gt;run&lt;/code&gt; block) or as shell commands (a &lt;code&gt;shell&lt;/code&gt; block). When you tell snakemake to produce a certain output file, it will check which rule must executed in order to obtain that file. It does so in a smart way: if the required for a rule input already exists, it will not re-run that rule, unless the input is newer than the output.&lt;/p&gt;
&lt;h3 id=&quot;our-desired-workflow&quot;&gt;Our desired workflow&lt;/h3&gt;
&lt;p&gt;Before we delve into details, let’s have a look at the workflow that we want to achieve. For demonstration purposes I will focus on WPS only. Snakemake provides a command (&lt;code&gt;snakemake --dag WPS | dot -Tpng &amp;#x26;gt; dag.png&lt;/code&gt;) to visualize the task graph for our workflow:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;(Un)wieldy workflows with WRF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;237&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-1d504248.iij7pUP3_2tEvlr.webp&quot; srcset=&quot;&quot;&gt;
Task graph for our WPS workflow. Boxes (nodes) are rules, arrows indicate dependencies between rules. Dashed lines indicate that these rules have already been executed. Full-line rules still need to be (re)run.As you can see, we want to run four independent experiments. While they share all the same steps, they have a different value for the &lt;code&gt;experiment&lt;/code&gt; setting. This is achieved through the use of a wildcard*.&lt;/p&gt;
&lt;h3 id=&quot;providing-experiment-settings&quot;&gt;Providing experiment settings&lt;/h3&gt;
&lt;p&gt;The values for the wildcard are provided to snakemake via a configuration file. This is a relatively simple file which, in addition to our experiment-specific settings, contains some global settings like &lt;code&gt;wps_home&lt;/code&gt;. Our config file looks like this (only showing the first experiment):&lt;/p&gt;
&lt;p&gt;wps_home: ~/Urban-M4/WPS
wrf_home: ~/Urban-M4/WRF
data_home: /projects/0/prjs0914/wrf-data/default
working_directory: ./output&lt;/p&gt;
&lt;p&gt;experiments:
usgs:
geog_data_res: [‘usgs_30s’,‘usgs_30s’,‘usgs_30s’,‘usgs_30s’]
geog_data_path: ‘/projects/0/prjs0914/wrf-data/default/static/summerinthecity’
geogrid_table: GEOGRID.TBL.ARW_USGS
use_wudapt_lcz: false
num_land_cat: 24
modis_lcz:
…The config file is read at the very top of the Snakefile, like so:&lt;/p&gt;
&lt;p&gt;configfile: workflow.source_path(“config.yaml”)The first rule in our workflow, &lt;code&gt;UPDATE_NAMELIST_WPS&lt;/code&gt;, uses a python package &lt;code&gt;[f90nml](https://f90nml.readthedocs.io/en/latest/)&lt;/code&gt; to load a reference namelist.wps, modify the settings as specified in the experiment configuration, and store the updated namelist in the output folder for that experiment. It looks like this:&lt;/p&gt;
&lt;p&gt;rule UPDATE_NAMELIST_WPS:
input:
namelist_wps = workflow.source_path(“namelist.wps”)
output:
“{experiment}/namelist.wps”,
run:
# Get parameters from config
geog_data_res = config[‘experiments’][wildcards.experiment][‘geog_data_res’]
geog_data_path = config[‘experiments’][wildcards.experiment][‘geog_data_path’]&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Read source namelist.wps with f90nml, make some changes, and save in experiment dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml = f90nml.read(input.namelist_wps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_path&quot;] = geog_data_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_res&quot;] = geog_data_res&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml.write(f&quot;{wildcards.experiment}/namelist.wps&quot;)Notice that we are reading the reference namelist form the workflow source path. This is because it is stored alongside the snakefile. Normally, all paths in snakemake are relative to the working directory.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importantly, this rule works for any value of the &lt;code&gt;experiment&lt;/code&gt; wildcard (as long as the settings are provided in the configuration file). To invoke the rule for each of our experiments, we use a target rule, like so:&lt;/p&gt;
&lt;p&gt;rule PRODUCE_ALL_NAMELISTS:
input: collect(“{experiment}/namelist.wps”, experiment=config[“experiments”].keys())The &lt;code&gt;collect&lt;/code&gt; function fills the values of &lt;code&gt;experiment&lt;/code&gt; with all keys found in &lt;code&gt;config[&quot;experiments&quot;]&lt;/code&gt;. When we invoke this target rule, e.g. by running &lt;code&gt;snakemake PRODUCE_ALL_NAMELISTS&lt;/code&gt;, Snakemake will look for a rule that can produc the following files (unless they already exist):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;usgs/namelist.wps&lt;/li&gt;
&lt;li&gt;modis_lcz/namelist.wps&lt;/li&gt;
&lt;li&gt;wur/namelist.wps&lt;/li&gt;
&lt;li&gt;wur_lcz/namelist.wps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It will find &lt;code&gt;UPDATE_NAMELIST_WPS&lt;/code&gt;and invoke this rule, inferring that the first segment corresponds to the value of the wildcard.&lt;/p&gt;
&lt;h3 id=&quot;specifying-the-other-steps&quot;&gt;Specifying the other steps&lt;/h3&gt;
&lt;p&gt;Getting Snakemake to use the different experiment settings was by far the most involved part of our journey. Next, we want to add rules for all the other steps. For example, out METGRID rule looks as follows:&lt;/p&gt;
&lt;p&gt;rule METGRID:
input:
“{experiment}/namelist.wps”,
“{experiment}/finished.ungrib”,
“{experiment}/finished.geogrid”,
output: “{experiment}/finished.metgrid”
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p metgrid&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cp {config[wps_home]}/metgrid/METGRID.TBL.ARW METGRID.TBL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/metgrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (metgrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; metgrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in metgrid.log. &quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.metgrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;Snakemake infers the dependecies between rules via their input and output filenames. Since WPS output filenames are not predictable without parsing the namelist, we opted for a workaround: at the end of each rule, we create an empty file called `finished.&amp;#x26;lt;rule&amp;#x26;gt;`. As such, we inform Snakemake that metgrid must be run after updating the namelist, and after geogrid and ungrib.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As opposed to the first rule, which executes Python code (a &lt;code&gt;run&lt;/code&gt; block), here we use shell commands. This is nice, because it is very similar to what you would do manually on the command line. As an intermediate option we can use &lt;code&gt;params&lt;/code&gt;. We use this in our &lt;code&gt;GEOGRID&lt;/code&gt; rule:&lt;/p&gt;
&lt;p&gt;rule GEOGRID:
input: “{experiment}/namelist.wps”,
output: “{experiment}/finished.geogrid”
params: geogrid_table = lambda wildcards: workflow.source_path(config[‘experiments’][wildcards.experiment][‘geogrid_table’]),
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p geogrid
cp {params.geogrid_table} GEOGRID.TBL&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Run geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/geogrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (geogrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; geogrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in geogrid.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;The use of params enables us to execute some Python code to assign a value to a variable, which can then be accessed in the shell block of the rule. Here, we get the `geogrid_table` from our experiment config. So we can combine the flexibility of Python with the transparancy of plain shell commands.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;final-workflow&quot;&gt;Final workflow&lt;/h3&gt;
&lt;p&gt;Putting everything together, our full workflow looks something like below. Notice that &lt;code&gt;WPS&lt;/code&gt; is the target rule in this case.&lt;/p&gt;
&lt;p&gt;import os
from pathlib import Path&lt;/p&gt;
&lt;p&gt;import f90nml&lt;/p&gt;
&lt;p&gt;configfile: workflow.source_path(“config.yaml”)
workdir: config[“working_directory”]
envvars: “NETCDF”&lt;/p&gt;
&lt;p&gt;rule UPDATE_NAMELIST_WPS:
input:
namelist_wps = workflow.source_path(“namelist.wps”)
output:
“{experiment}/namelist.wps”,
run:
# Get parameters from config
geog_data_res = config[‘experiments’][wildcards.experiment][‘geog_data_res’]
geog_data_path = config[‘experiments’][wildcards.experiment][‘geog_data_path’]&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Read source namelist.wps with f90nml, make some changes, and save in experiment dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml = f90nml.read(input.namelist_wps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_path&quot;] = geog_data_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_res&quot;] = geog_data_res&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml.write(f&quot;{wildcards.experiment}/namelist.wps&quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule GEOGRID:
input: “{experiment}/namelist.wps”,
output: “{experiment}/finished.geogrid”
params: geogrid_table = lambda wildcards: workflow.source_path(config[‘experiments’][wildcards.experiment][‘geogrid_table’]),
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p geogrid
cp {params.geogrid_table} GEOGRID.TBL&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Run geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/geogrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (geogrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; geogrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in geogrid.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule UNGRIB:
input: “{experiment}/namelist.wps”
output: “{experiment}/finished.ungrib”
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Remove old output if present (ungrib doesn&apos;t like to overwrite stuff)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    rm -f FILE*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Link vtable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cp {config[wps_home]}/ungrib/Variable_Tables/Vtable.ECMWF Vtable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Link gribfiles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/link_grib.csh {config[data_home]}/real-time/july2019/*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Run ungrib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/ungrib.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (ungrib can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; ungrib.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in ungrib.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Report ready&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.ungrib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule METGRID:
input:
“{experiment}/namelist.wps”,
“{experiment}/finished.ungrib”,
“{experiment}/finished.geogrid”,
output: “{experiment}/finished.metgrid”
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p metgrid&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cp {config[wps_home]}/metgrid/METGRID.TBL.ARW METGRID.TBL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/metgrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (metgrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; metgrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in metgrid.log. &quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.metgrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule WPS:
input: collect(“{experiment}/finished.metgrid”, experiment=config[“experiments”].keys())We’re steadily accumulating lines of code, but overall, we’re quite happy with how interpretable this still looks. As we develop this further, it would be good to split it up into multiple files, and incorporate other best practices as outlined in the &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/snakefiles/best_practices.html&quot;&gt;Snakemake documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;struggles&quot;&gt;Struggles&lt;/h3&gt;
&lt;p&gt;While we’re quite happy with our progress so far, here are some things that we struggled with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flexibility of output directories: we want to organize our output as follows: &lt;code&gt;./results/{experiment}&lt;/code&gt;. By default, all paths are relative to the working directory. We set the working directory to &lt;code&gt;./results&lt;/code&gt;, so the first rule, &lt;code&gt;UPDATE_NAMELIST&lt;/code&gt;, will actually create the file &lt;code&gt;./results/{experiment}/namelist.wps&lt;/code&gt;. Unfortunately, snakemake cannot use wildcards for the working directory. Therefore, we need to &lt;code&gt;cd&lt;/code&gt; to the experiment directory in every rule.&lt;/li&gt;
&lt;li&gt;Complex input/output: the output of WPS programs depends on the settings in namelist.wps. Specifically, filenames like &lt;code&gt;met_em.d03.2019...&lt;/code&gt; encode information about the domain and (a lot of) dates. We could use something like &lt;code&gt;output: expand(&quot;met_em.{domain}.{datetime}.nc&quot;, domain=DOMAINS, datetime=DATETIMES)&lt;/code&gt;. For that to work, we’d need to set &lt;code&gt;DOMAINS&lt;/code&gt; and &lt;code&gt;DATETIMES&lt;/code&gt; in the configuration file, or infer them from the template namelist.wps. Not ideal, and quickly getting complex.&lt;/li&gt;
&lt;li&gt;Atomic inputs/outputs: a bit of a stretch goal, but when using a workflow manager like this, it would be nice if you could do, for example, &lt;code&gt;metgrid.exe --domain=1 --date=20190101&lt;/code&gt;. This way, when only one domain/timestamp needs to be re-processed, we don’t need to re-run the workflow for everything else as well. However, this means some of the logic that’s currently encoded in WPS programs, specifically parsing the domain and time control sections of the namelist and looping over them, is moved entirely to the workflow. Do we really want to go down that path?&lt;/li&gt;
&lt;li&gt;Shared input/output: now, we’re saving the output of each experiment in a dedicated directory. However, there is quite some duplication. Instead, we could store WPS output in a shared directory. But what happens if two namelists with different settings create the same file &lt;code&gt;geo_em.d01.nc&lt;/code&gt;? We would need to encode the WPS configuration in the path somehow, e.g. &lt;code&gt;geogrid/usgs**/geo_em.d01.nc&lt;/code&gt; and &lt;code&gt;ungrib/**ifs**/FILE:20190101&lt;/code&gt; combine to create &lt;code&gt;metgrid/**usgs/ifs**/met_em...&lt;/code&gt;. This is currently not possible since the ungrib directory is not configurable.&lt;/li&gt;
&lt;li&gt;SLURM: snakemake can submit workflows to a batch scheduler like slurm through a plugin. However, we found it to be very cumbersome. For example, we found the main Snakemake program was hanging often and did not seem to check for status; online help often referred to old versions; you can mark jobs for local execution when slurm is the default, but not vice versa as we would have preferred; the working directory was not respected; we had to carefully reinitialize the environment; et cetera. Eventually it seemed easier to wrap the entire Snakemake workflow in a batch script and submit that to slurm, but this is also suboptimal, especially since we cannot differentiate between resources for eacht task then.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;verdict&quot;&gt;Verdict&lt;/h3&gt;
&lt;p&gt;Some of these things can probably be solved by digging further into the inner workings of Snakemake. At the same time, we’re conscious of the complexity of our workflow. If it takes more time to build and maintain it than it would take to do the tedious manual bookkeeping, is it really worth the effort?&lt;/p&gt;
&lt;p&gt;Hopefully yes: reproducibility is important, and perhaps others can benefit as well. For now, however, we need to focus on the results for a bit. So let’s do a quick recap and call it a day.&lt;/p&gt;
&lt;p&gt;If you want to follow our progress, keep an eye on our repository &lt;a href=&quot;https://github.com/Urban-M4/snakemake-wrf&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;We’ve experimented with different options for managing WRF workflows. With a few tweaks, we were able to tackle many of our initial painpoints. Once we got the hang of it, we quite liked the flexibility of Snakemake and its promise of reproducible experiment sets. However, while we aimed for something simple, we found that our solutions quickly grew complex as we tried to bend the tools to our will.&lt;/p&gt;
&lt;p&gt;There’s a few peculiarities about WRF that were very much in the way. For example, that we couldn’t specify the ungrib directory. In terms of compatibility with Snakemake, it would be nice if WRF was less dependent on the current working directory, and/or if Snakemake’s working directory would be able to adapt to wildcard values.&lt;/p&gt;
&lt;p&gt;Perhaps the main conclusion should be that organizing your (WRF) workflows is not as straightforward as it may seem. This is something that many people must struggle with. And while there’s plenty of resources on the WRF documentation and user forum, “how to manage your workflow” does not seem to get the attention it deserves.&lt;/p&gt;
&lt;p&gt;How do you manage your workflows? Please share your tips and tricks in the comments or in any other way that you see fit.&lt;/p&gt;</description><pubDate>Thu, 05 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;unwieldy-workflows-with-wrf&quot;&gt;&lt;strong&gt;(Un)wieldy workflows with WRF&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;streamlining-experiments-with-the-weather-research-and-forecasting-model&quot;&gt;&lt;strong&gt;Streamlining experiments with the Weather Research and Forecasting model&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.mmm.ucar.edu/models/wrf&quot;&gt;Weather Research and Forecasting model&lt;/a&gt;, WRF for short, is a beautiful piece of research software with a large community of active users. That’s something we love and advocate for at the eScience Center.&lt;/p&gt;
&lt;p&gt;Given its large user base, one might think this must be an exemplary model to work with. And perhaps it is, in comparison to other models in the scene. But as I’m working with WRF again after several years, I’m reminded of my struggles in keeping my workflows organized.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;(Un)wieldy workflows with WRF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;386&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-b6e59d0c.B5Z5PUNe_Z1p8i5Q.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@hdbernd?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Bernd 📷 Dittrich&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To try and tackle this issue once and for all, we experimented with different solutions, including a simple shell script, as well as &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/&quot;&gt;Snakemake&lt;/a&gt;, a python-based workflow management tool often used in bioinformatics. Both approaches turn out to have their own merits and quirks.&lt;/p&gt;
&lt;p&gt;Overall, we did get a better grip on the antipatterns that prevented us from keeping a nice and orderly workflow. From this, we extracted some best practices for managing complex (WRF) modelling workflows. This blogpost documents our journey and the lessons learned, in the hope that it will be useful for other WRF users and those who struggle with managing their experiments.&lt;/p&gt;
&lt;h2 id=&quot;running-basic-wrf&quot;&gt;Running basic WRF**&lt;/h2&gt;
&lt;p&gt;Let’s start with an overview of the steps required to run a basic WRF (real data) experiment, as per the instructions in the &lt;a href=&quot;https://www2.mmm.ucar.edu/wrf/users/wrf_users_guide/build/html/wps.html&quot;&gt;user guide&lt;/a&gt;. First you must run the WRF preprocessing system (WPS), which itself consists of three programs: geogrid, ungrib, and metgrid. Then you run WRF itself, which also consists of two programs: real and wrf.&lt;/p&gt;
&lt;p&gt;cd WPS**&lt;/p&gt;
&lt;h1 id=&quot;run-geogrid-interpolate-spatial-datasets-to-the-model-grid&quot;&gt;Run geogrid (interpolate spatial datasets to the model grid)&lt;/h1&gt;
&lt;p&gt;./geogrid.exe&lt;/p&gt;
&lt;h1 id=&quot;run-ungrib-unpack-meteorological-input-data&quot;&gt;Run ungrib (unpack meteorological input data)&lt;/h1&gt;
&lt;p&gt;./link_grib.csh /your/meteo/data/dir
ln -s ungrib/Variable_Tables/Vtable.GFS Vtable
./ungrib.exe&lt;/p&gt;
&lt;h1 id=&quot;run-metgrid-interpolate-the-meteo-data-to-model-grid&quot;&gt;Run metgrid (interpolate the meteo data to model grid)&lt;/h1&gt;
&lt;p&gt;./metgrid.exe&lt;/p&gt;
&lt;p&gt;cd ../WRF/run&lt;/p&gt;
&lt;h1 id=&quot;run-real-extract-initial-and-boundary-fields-from-preprocessed-data&quot;&gt;Run real (extract initial and boundary fields from preprocessed data)&lt;/h1&gt;
&lt;p&gt;ln -sf ../../WPS/met_em* .
./real.exe&lt;/p&gt;
&lt;h1 id=&quot;run-wrf-the-actual-forecast&quot;&gt;Run WRF (the actual forecast)&lt;/h1&gt;
&lt;p&gt;./wrf.exeThis workflow is not great in several ways. WRF and WPS are run in different working directories; yet they “pretend” to be in the same directory by use of symbolic links (&lt;code&gt;ln&lt;/code&gt;). Also, exectuables are in the same directory as the input/output data. Now, imagine, for example, that we want to do multiple experiments with slightly different settings.&lt;/p&gt;
&lt;p&gt;One option would be to move the output to a separate directory between each run. We would need to meticulously bookkeep our files, especially since runs may fail at different stages causing us to re-run (part of) the workflow. Also, we would not be able run the experiments in parallel. Clearly, using WRF in this way is a labour-intensive, error-prone process.&lt;/p&gt;
&lt;p&gt;Alternatively, we could duplicate our &lt;code&gt;WPS&lt;/code&gt;and &lt;code&gt;WRF/run&lt;/code&gt;directories. That’s also not great: imagine we want to re-run our experiments with a re-compiled version of WRF. Then we would need to copy over the new executables to all experiment directories.&lt;/p&gt;
&lt;p&gt;Finally, there’s lots of files in these directories that are not needed for our experiments, which makes it hard to tell the wheat from the chaff.&lt;/p&gt;
&lt;h3 id=&quot;our-workflow-wishlist&quot;&gt;Our workflow wishlist**&lt;/h3&gt;
&lt;p&gt;Considering the points above, let’s think about how we would like it to be, and start a workflow wishlist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each/all experiment(s) can be re-run with a single command&lt;/li&gt;
&lt;li&gt;One directory per experiment, containing config + output&lt;/li&gt;
&lt;li&gt;Intermediate/output data well organized in subdirectories&lt;/li&gt;
&lt;li&gt;Config files (namelists) specify paths to all relevant input data; no links&lt;/li&gt;
&lt;li&gt;Executables should be in a system path or another dedicated location&lt;/li&gt;
&lt;li&gt;We should be able to (re-)run only part of a workflow&lt;/li&gt;
&lt;li&gt;Bonus: reuse intermediate files that are the same for all experiments&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solution-1-using-a-shell-script&quot;&gt;&lt;strong&gt;Solution #1: using a shell script&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Let’s see how far we can get with a simple shell script. In this example, we maintain multiple namelists and geogrid tables for each experiment. These are stored alongside the shell script and copied over to the experiment folder once the script is run. The full code is available &lt;a href=&quot;https://github.com/Urban-M4/wrf-runner&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;some-initialization-of-the-environment-module-loads-etc-&quot;&gt;Some initialization of the environment, module loads etc.**# …&lt;/h1&gt;
&lt;h1 id=&quot;set-path-to-executables&quot;&gt;Set path to executables&lt;/h1&gt;
&lt;p&gt;WPS_HOME=&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;HOME/wrf-model/WPS
WRF_HOME=&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;HOME/wrf-model/WRF&lt;/p&gt;
&lt;h1 id=&quot;define-experiment-name&quot;&gt;Define experiment name&lt;/h1&gt;
&lt;p&gt;EXP=USGS&lt;/p&gt;
&lt;h1 id=&quot;make-new-experiment-directory&quot;&gt;Make new experiment directory&lt;/h1&gt;
&lt;p&gt;export RUNDIR=wrf_experiments/&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;{EXP}
mkdir -p &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7778em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;mk&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR
mkdir &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;RUNDIR/geogrid
mkdir &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;mk&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/metgrid&lt;/p&gt;
&lt;h1 id=&quot;copy-experiment-dependent-files&quot;&gt;Copy experiment-dependent files&lt;/h1&gt;
&lt;p&gt;cp namelist.wps_&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;EXP &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/namelist.wps
cp namelist.input_&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;EXP &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/namelist.input
cp GEOGRID.TBL.ARW_&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;X&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;EXP &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RUNDIR/GEOGRID.TBL&lt;/p&gt;
&lt;h1 id=&quot;copy-additional-input-files-from-wrfwps&quot;&gt;Copy additional input files from WRF/WPS&lt;/h1&gt;
&lt;p&gt;cd &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;D&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;RUNDIR
cp &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WPS_HOME/metgrid/METGRID.TBL.ARW METGRID.TBL
cp &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WPS_HOME/ungrid/Variable_Tables/Vtable.ECMWF VTable
cp &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;iab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:0em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0715em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WRF_HOME/run/CAMtr_volume_mixing_ratio.RCP8.5 CAMtr_volume_mixing_ratio
cp &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WRF_HOME/run/ozone* .
cp &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.044em;&quot;&gt;oz&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∗&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.625em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WRF_HOME/run/RRTMG* .
cp $WRF_HOME/run/*.TBL .&lt;/p&gt;
&lt;h1 id=&quot;run-experiments&quot;&gt;Run experiments&lt;/h1&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mo&gt;∗&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WPS_HOME/link_grib.csh &quot;path/to/our/input/data/*&quot;
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0361em;vertical-align:-0.2861em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.1514em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.2861em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ib&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;cs&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;∗&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WPS_HOME/ungrib.exe
&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;&amp;#x26;&amp;#x27; at position 47: …R&amp;#x22; geogrid.log &amp;#x26;̲amp;&amp;#x26;amp; echo …&quot; style=&quot;color:#cc0000&quot;&gt;WPS_HOME/geogrid.exe
grep &quot;ERROR&quot; geogrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in geogrid.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1
&lt;/span&gt;WPS_HOME/metgrid.exe
grep “ERROR” metgrid.log &amp;#x26;&amp;#x26; echo “Aborting: ERROR in metgrid.log.” &amp;#x26;&amp;#x26; exit 1&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;W&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;msub&gt;&lt;mi&gt;F&lt;/mi&gt;&lt;mi&gt;H&lt;/mi&gt;&lt;/msub&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;M&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;WRF_HOME/run/real.exe
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;W&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t vlist-t2&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.3283em;&quot;&gt;&lt;span style=&quot;top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mathnormal mtight&quot; style=&quot;margin-right:0.0813em;&quot;&gt;H&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-s&quot;&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.15em;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;WRF_HOME/run/wrf.exeEvidently, WRF and WPS &lt;em&gt;can&lt;/em&gt; be run from another directory, by calling them by their full path. Alternatively, we could have added the &lt;code&gt;WPS&lt;/code&gt; and &lt;code&gt;WRF/run&lt;/code&gt; directories to our &lt;code&gt;PATH&lt;/code&gt; variable. However, WRF and WPS expect certain files (tables etc.) in the working directory, so we need to copy those.&lt;/p&gt;
&lt;p&gt;Geogrid and metgrid tables are expected in subfolders, but we can use the namelist setting &lt;code&gt;opt_geogrid_table_path=&apos;.&apos;&lt;/code&gt; (default is &lt;code&gt;&apos;./geogrid&apos;&lt;/code&gt;) to overwrite that, and similar for metgrid. Geogrid will then look in that folder for a file called &lt;code&gt;GEOGRID.TBL&lt;/code&gt;. (Why not simply point to the geogrid table directly in the namelist?)&lt;/p&gt;
&lt;p&gt;We were able to declutter our working directory somewhat by using the namelist.wps options &lt;code&gt;opt_output_from_geogrid_path&lt;/code&gt; and similar for metgrid. Unfortunately, that option is not available for ungrib, the worst clutterer of all… We were able to point &lt;code&gt;real.exe&lt;/code&gt; to our metgrid subfolder through the namelist.input parameter &lt;code&gt;[auxinput1_inname](https://github.com/wrf-model/WRF/blob/0a11865f97680fdd6865b278ea29d910e5db3ed7/run/README.namelist#L89)&lt;/code&gt;, so we could skip that linking step as well.&lt;/p&gt;
&lt;p&gt;We wanted the workflow to fail when one of the steps fails. However, metgrid and geogrid &lt;a href=&quot;https://github.com/wrf-model/WPS/issues/252#issue-2315032244&quot;&gt;don’t fail with a proper exit code&lt;/a&gt;. As a simple patch, we added extra commands to look for errors in the log files and raise an exception when needed.&lt;/p&gt;
&lt;p&gt;Despite some peculiarities, this is a good start. We can already tick some of the items off our wishlist. However, the workflow quickly becomes more complex. For example, as we are adding more experiments, we would like to edit the namelists programmatically. And for some runs, we may want to run an intermediate step (e.g. wudapt-to-wrf). Before we know it, the shell script becomes messy, which defeats our purpose of maintaining a tidy and organized workflow.&lt;/p&gt;
&lt;p&gt;To summarize, the following namelist parameters should probably be much better advertised:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;opt_geogrid_table_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opt_metgrid_table_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opt_output_from_geogrid_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;opt_output_from_metgrid_path&lt;/code&gt; (namelist.wps)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[auxinput1_inname](https://github.com/wrf-model/WRF/blob/0a11865f97680fdd6865b278ea29d910e5db3ed7/run/README.namelist#L89)&lt;/code&gt; (namelist.input)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a similar option for ungrib, the WRF experience would already be much better.&lt;/p&gt;
&lt;h2 id=&quot;solution-2-using-snakemake&quot;&gt;Solution #2: using Snakemake**&lt;/h2&gt;
&lt;p&gt;Ideally, we want to be able to run only part of a workflow. For example, when &lt;code&gt;real.exe&lt;/code&gt; fails, we don’t want to re-run WPS. Similarly, we may want to run all pre-processing first, and then submit WRF as a batch job.&lt;/p&gt;
&lt;h3 id=&quot;brief-intro-to-snakemake&quot;&gt;Brief intro to Snakemake&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;(Un)wieldy workflows with WRF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;177&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-ef7a50be.BXCuInXQ_Z1i0EU1.webp&quot; srcset=&quot;&quot;&gt;
Example Snakemake rules (source &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/project_info/faq.html#what-is-the-key-idea-of-snakemake-workflows&quot;&gt;https://snakemake.readthedocs.io/en/stable/project_info/faq.html#what-is-the-key-idea-of-snakemake-workflows&lt;/a&gt;)A snakemake workflow, aka ‘Snakefile’, consists of rules. Each rule has certain inputs and outputs, and the commands to produce that output, either in Python code (a &lt;code&gt;run&lt;/code&gt; block) or as shell commands (a &lt;code&gt;shell&lt;/code&gt; block). When you tell snakemake to produce a certain output file, it will check which rule must executed in order to obtain that file. It does so in a smart way: if the required for a rule input already exists, it will not re-run that rule, unless the input is newer than the output.&lt;/p&gt;
&lt;h3 id=&quot;our-desired-workflow&quot;&gt;Our desired workflow&lt;/h3&gt;
&lt;p&gt;Before we delve into details, let’s have a look at the workflow that we want to achieve. For demonstration purposes I will focus on WPS only. Snakemake provides a command (&lt;code&gt;snakemake --dag WPS | dot -Tpng &amp;#x26;gt; dag.png&lt;/code&gt;) to visualize the task graph for our workflow:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;(Un)wieldy workflows with WRF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;237&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-1d504248.iij7pUP3_2tEvlr.webp&quot; srcset=&quot;&quot;&gt;
Task graph for our WPS workflow. Boxes (nodes) are rules, arrows indicate dependencies between rules. Dashed lines indicate that these rules have already been executed. Full-line rules still need to be (re)run.As you can see, we want to run four independent experiments. While they share all the same steps, they have a different value for the &lt;code&gt;experiment&lt;/code&gt; setting. This is achieved through the use of a wildcard*.&lt;/p&gt;
&lt;h3 id=&quot;providing-experiment-settings&quot;&gt;Providing experiment settings&lt;/h3&gt;
&lt;p&gt;The values for the wildcard are provided to snakemake via a configuration file. This is a relatively simple file which, in addition to our experiment-specific settings, contains some global settings like &lt;code&gt;wps_home&lt;/code&gt;. Our config file looks like this (only showing the first experiment):&lt;/p&gt;
&lt;p&gt;wps_home: ~/Urban-M4/WPS
wrf_home: ~/Urban-M4/WRF
data_home: /projects/0/prjs0914/wrf-data/default
working_directory: ./output&lt;/p&gt;
&lt;p&gt;experiments:
usgs:
geog_data_res: [‘usgs_30s’,‘usgs_30s’,‘usgs_30s’,‘usgs_30s’]
geog_data_path: ‘/projects/0/prjs0914/wrf-data/default/static/summerinthecity’
geogrid_table: GEOGRID.TBL.ARW_USGS
use_wudapt_lcz: false
num_land_cat: 24
modis_lcz:
…The config file is read at the very top of the Snakefile, like so:&lt;/p&gt;
&lt;p&gt;configfile: workflow.source_path(“config.yaml”)The first rule in our workflow, &lt;code&gt;UPDATE_NAMELIST_WPS&lt;/code&gt;, uses a python package &lt;code&gt;[f90nml](https://f90nml.readthedocs.io/en/latest/)&lt;/code&gt; to load a reference namelist.wps, modify the settings as specified in the experiment configuration, and store the updated namelist in the output folder for that experiment. It looks like this:&lt;/p&gt;
&lt;p&gt;rule UPDATE_NAMELIST_WPS:
input:
namelist_wps = workflow.source_path(“namelist.wps”)
output:
“{experiment}/namelist.wps”,
run:
# Get parameters from config
geog_data_res = config[‘experiments’][wildcards.experiment][‘geog_data_res’]
geog_data_path = config[‘experiments’][wildcards.experiment][‘geog_data_path’]&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Read source namelist.wps with f90nml, make some changes, and save in experiment dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml = f90nml.read(input.namelist_wps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_path&quot;] = geog_data_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_res&quot;] = geog_data_res&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml.write(f&quot;{wildcards.experiment}/namelist.wps&quot;)Notice that we are reading the reference namelist form the workflow source path. This is because it is stored alongside the snakefile. Normally, all paths in snakemake are relative to the working directory.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importantly, this rule works for any value of the &lt;code&gt;experiment&lt;/code&gt; wildcard (as long as the settings are provided in the configuration file). To invoke the rule for each of our experiments, we use a target rule, like so:&lt;/p&gt;
&lt;p&gt;rule PRODUCE_ALL_NAMELISTS:
input: collect(“{experiment}/namelist.wps”, experiment=config[“experiments”].keys())The &lt;code&gt;collect&lt;/code&gt; function fills the values of &lt;code&gt;experiment&lt;/code&gt; with all keys found in &lt;code&gt;config[&quot;experiments&quot;]&lt;/code&gt;. When we invoke this target rule, e.g. by running &lt;code&gt;snakemake PRODUCE_ALL_NAMELISTS&lt;/code&gt;, Snakemake will look for a rule that can produc the following files (unless they already exist):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;usgs/namelist.wps&lt;/li&gt;
&lt;li&gt;modis_lcz/namelist.wps&lt;/li&gt;
&lt;li&gt;wur/namelist.wps&lt;/li&gt;
&lt;li&gt;wur_lcz/namelist.wps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It will find &lt;code&gt;UPDATE_NAMELIST_WPS&lt;/code&gt;and invoke this rule, inferring that the first segment corresponds to the value of the wildcard.&lt;/p&gt;
&lt;h3 id=&quot;specifying-the-other-steps&quot;&gt;Specifying the other steps&lt;/h3&gt;
&lt;p&gt;Getting Snakemake to use the different experiment settings was by far the most involved part of our journey. Next, we want to add rules for all the other steps. For example, out METGRID rule looks as follows:&lt;/p&gt;
&lt;p&gt;rule METGRID:
input:
“{experiment}/namelist.wps”,
“{experiment}/finished.ungrib”,
“{experiment}/finished.geogrid”,
output: “{experiment}/finished.metgrid”
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p metgrid&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cp {config[wps_home]}/metgrid/METGRID.TBL.ARW METGRID.TBL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/metgrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (metgrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; metgrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in metgrid.log. &quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.metgrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;Snakemake infers the dependecies between rules via their input and output filenames. Since WPS output filenames are not predictable without parsing the namelist, we opted for a workaround: at the end of each rule, we create an empty file called `finished.&amp;#x26;lt;rule&amp;#x26;gt;`. As such, we inform Snakemake that metgrid must be run after updating the namelist, and after geogrid and ungrib.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As opposed to the first rule, which executes Python code (a &lt;code&gt;run&lt;/code&gt; block), here we use shell commands. This is nice, because it is very similar to what you would do manually on the command line. As an intermediate option we can use &lt;code&gt;params&lt;/code&gt;. We use this in our &lt;code&gt;GEOGRID&lt;/code&gt; rule:&lt;/p&gt;
&lt;p&gt;rule GEOGRID:
input: “{experiment}/namelist.wps”,
output: “{experiment}/finished.geogrid”
params: geogrid_table = lambda wildcards: workflow.source_path(config[‘experiments’][wildcards.experiment][‘geogrid_table’]),
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p geogrid
cp {params.geogrid_table} GEOGRID.TBL&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Run geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/geogrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (geogrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; geogrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in geogrid.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;The use of params enables us to execute some Python code to assign a value to a variable, which can then be accessed in the shell block of the rule. Here, we get the `geogrid_table` from our experiment config. So we can combine the flexibility of Python with the transparancy of plain shell commands.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;final-workflow&quot;&gt;Final workflow&lt;/h3&gt;
&lt;p&gt;Putting everything together, our full workflow looks something like below. Notice that &lt;code&gt;WPS&lt;/code&gt; is the target rule in this case.&lt;/p&gt;
&lt;p&gt;import os
from pathlib import Path&lt;/p&gt;
&lt;p&gt;import f90nml&lt;/p&gt;
&lt;p&gt;configfile: workflow.source_path(“config.yaml”)
workdir: config[“working_directory”]
envvars: “NETCDF”&lt;/p&gt;
&lt;p&gt;rule UPDATE_NAMELIST_WPS:
input:
namelist_wps = workflow.source_path(“namelist.wps”)
output:
“{experiment}/namelist.wps”,
run:
# Get parameters from config
geog_data_res = config[‘experiments’][wildcards.experiment][‘geog_data_res’]
geog_data_path = config[‘experiments’][wildcards.experiment][‘geog_data_path’]&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Read source namelist.wps with f90nml, make some changes, and save in experiment dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml = f90nml.read(input.namelist_wps)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_path&quot;] = geog_data_path&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml[&quot;geogrid&quot;][&quot;geog_data_res&quot;] = geog_data_res&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    nml.write(f&quot;{wildcards.experiment}/namelist.wps&quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule GEOGRID:
input: “{experiment}/namelist.wps”,
output: “{experiment}/finished.geogrid”
params: geogrid_table = lambda wildcards: workflow.source_path(config[‘experiments’][wildcards.experiment][‘geogrid_table’]),
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p geogrid
cp {params.geogrid_table} GEOGRID.TBL&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Run geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/geogrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (geogrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; geogrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in geogrid.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.geogrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule UNGRIB:
input: “{experiment}/namelist.wps”
output: “{experiment}/finished.ungrib”
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Remove old output if present (ungrib doesn&apos;t like to overwrite stuff)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    rm -f FILE*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Link vtable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cp {config[wps_home]}/ungrib/Variable_Tables/Vtable.ECMWF Vtable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Link gribfiles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/link_grib.csh {config[data_home]}/real-time/july2019/*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Run ungrib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/ungrib.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (ungrib can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; ungrib.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in ungrib.log.&quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Report ready&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.ungrib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule METGRID:
input:
“{experiment}/namelist.wps”,
“{experiment}/finished.ungrib”,
“{experiment}/finished.geogrid”,
output: “{experiment}/finished.metgrid”
shell:
&quot;&quot;&quot;
cd {wildcards.experiment}
mkdir -p metgrid&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cp {config[wps_home]}/metgrid/METGRID.TBL.ARW METGRID.TBL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {config[wps_home]}/metgrid.exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # Scan logfile for errors and raise if necessary (metgrid can fail silently with 0 exit status)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    grep &quot;ERROR&quot; metgrid.log &amp;#x26;amp;&amp;#x26;amp; echo &quot;Aborting: ERROR in metgrid.log. &quot; &amp;#x26;amp;&amp;#x26;amp; exit 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    touch finished.metgrid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;rule WPS:
input: collect(“{experiment}/finished.metgrid”, experiment=config[“experiments”].keys())We’re steadily accumulating lines of code, but overall, we’re quite happy with how interpretable this still looks. As we develop this further, it would be good to split it up into multiple files, and incorporate other best practices as outlined in the &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/snakefiles/best_practices.html&quot;&gt;Snakemake documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;struggles&quot;&gt;Struggles&lt;/h3&gt;
&lt;p&gt;While we’re quite happy with our progress so far, here are some things that we struggled with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Flexibility of output directories: we want to organize our output as follows: &lt;code&gt;./results/{experiment}&lt;/code&gt;. By default, all paths are relative to the working directory. We set the working directory to &lt;code&gt;./results&lt;/code&gt;, so the first rule, &lt;code&gt;UPDATE_NAMELIST&lt;/code&gt;, will actually create the file &lt;code&gt;./results/{experiment}/namelist.wps&lt;/code&gt;. Unfortunately, snakemake cannot use wildcards for the working directory. Therefore, we need to &lt;code&gt;cd&lt;/code&gt; to the experiment directory in every rule.&lt;/li&gt;
&lt;li&gt;Complex input/output: the output of WPS programs depends on the settings in namelist.wps. Specifically, filenames like &lt;code&gt;met_em.d03.2019...&lt;/code&gt; encode information about the domain and (a lot of) dates. We could use something like &lt;code&gt;output: expand(&quot;met_em.{domain}.{datetime}.nc&quot;, domain=DOMAINS, datetime=DATETIMES)&lt;/code&gt;. For that to work, we’d need to set &lt;code&gt;DOMAINS&lt;/code&gt; and &lt;code&gt;DATETIMES&lt;/code&gt; in the configuration file, or infer them from the template namelist.wps. Not ideal, and quickly getting complex.&lt;/li&gt;
&lt;li&gt;Atomic inputs/outputs: a bit of a stretch goal, but when using a workflow manager like this, it would be nice if you could do, for example, &lt;code&gt;metgrid.exe --domain=1 --date=20190101&lt;/code&gt;. This way, when only one domain/timestamp needs to be re-processed, we don’t need to re-run the workflow for everything else as well. However, this means some of the logic that’s currently encoded in WPS programs, specifically parsing the domain and time control sections of the namelist and looping over them, is moved entirely to the workflow. Do we really want to go down that path?&lt;/li&gt;
&lt;li&gt;Shared input/output: now, we’re saving the output of each experiment in a dedicated directory. However, there is quite some duplication. Instead, we could store WPS output in a shared directory. But what happens if two namelists with different settings create the same file &lt;code&gt;geo_em.d01.nc&lt;/code&gt;? We would need to encode the WPS configuration in the path somehow, e.g. &lt;code&gt;geogrid/usgs**/geo_em.d01.nc&lt;/code&gt; and &lt;code&gt;ungrib/**ifs**/FILE:20190101&lt;/code&gt; combine to create &lt;code&gt;metgrid/**usgs/ifs**/met_em...&lt;/code&gt;. This is currently not possible since the ungrib directory is not configurable.&lt;/li&gt;
&lt;li&gt;SLURM: snakemake can submit workflows to a batch scheduler like slurm through a plugin. However, we found it to be very cumbersome. For example, we found the main Snakemake program was hanging often and did not seem to check for status; online help often referred to old versions; you can mark jobs for local execution when slurm is the default, but not vice versa as we would have preferred; the working directory was not respected; we had to carefully reinitialize the environment; et cetera. Eventually it seemed easier to wrap the entire Snakemake workflow in a batch script and submit that to slurm, but this is also suboptimal, especially since we cannot differentiate between resources for eacht task then.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;verdict&quot;&gt;Verdict&lt;/h3&gt;
&lt;p&gt;Some of these things can probably be solved by digging further into the inner workings of Snakemake. At the same time, we’re conscious of the complexity of our workflow. If it takes more time to build and maintain it than it would take to do the tedious manual bookkeeping, is it really worth the effort?&lt;/p&gt;
&lt;p&gt;Hopefully yes: reproducibility is important, and perhaps others can benefit as well. For now, however, we need to focus on the results for a bit. So let’s do a quick recap and call it a day.&lt;/p&gt;
&lt;p&gt;If you want to follow our progress, keep an eye on our repository &lt;a href=&quot;https://github.com/Urban-M4/snakemake-wrf&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;We’ve experimented with different options for managing WRF workflows. With a few tweaks, we were able to tackle many of our initial painpoints. Once we got the hang of it, we quite liked the flexibility of Snakemake and its promise of reproducible experiment sets. However, while we aimed for something simple, we found that our solutions quickly grew complex as we tried to bend the tools to our will.&lt;/p&gt;
&lt;p&gt;There’s a few peculiarities about WRF that were very much in the way. For example, that we couldn’t specify the ungrib directory. In terms of compatibility with Snakemake, it would be nice if WRF was less dependent on the current working directory, and/or if Snakemake’s working directory would be able to adapt to wildcard values.&lt;/p&gt;
&lt;p&gt;Perhaps the main conclusion should be that organizing your (WRF) workflows is not as straightforward as it may seem. This is something that many people must struggle with. And while there’s plenty of resources on the WRF documentation and user forum, “how to manage your workflow” does not seem to get the attention it deserves.&lt;/p&gt;
&lt;p&gt;How do you manage your workflows? Please share your tips and tricks in the comments or in any other way that you see fit.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/unwieldy-workflows-with-wrf-b6e59d0c.B5Z5PUNe.jpg" medium="image"/><author>Peter Kalverla</author></item><item><title>Research software is critical to the future of AI-driven research</title><link>https://blog2.esciencecenter.nl/posts/2024-08-22---research-software-is-critical-to-the-future-of-ai-driven-res</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-08-22---research-software-is-critical-to-the-future-of-ai-driven-res</guid><description>&lt;p&gt;&lt;em&gt;By Michelle Barker, Kim Hartley, Daniel S. Katz, Richard Littauer, Qian Zhang, Shurui Zhou, Jyoti Bhogal&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cross-posted from ReSA and the Digital Research Alliance of Canada&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research software is critical to the future of AI-driven research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-is-critical-to-the-fut-cea947aa.CtbIw_yP_2h44w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo credit: &lt;a href=&quot;https://www.shutterstock.com/g/TheMezereon&quot;&gt;TheMezereon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This position paper provides a statement on the criticality of research software in artificial intelligence (AI)-driven research and makes recommendations for stakeholders on how to consider research software in their AI goals. This is needed to ensure that the focus on technological infrastructure to support AI acceleration includes research software and its personnel as a vital part of that infrastructure. This paper discusses both research software that supports generative AI, which is now being explored today as a tool to enable new research, as well as more traditional machine learning, which has demonstrated impact in research in most disciplines (particularly in the last decade).&lt;/p&gt;
&lt;p&gt;This paper begins by providing definitions for key terms and demonstrating the importance of research software in AI-driven research. The paper then explores the need for AI strategies to recognise research software as key building blocks of AI-driven research, and to include this element alongside a focus on computing systems, data, and models. The fact that AI is dependent on software (i.e., data preparation and model training are performed by software, models are implemented in software) is not always adequately considered. Alongside this high-level need for incorporation of research software in AI strategies, the challenges inherent in software dependencies also need consideration, as research software requires continual maintenance, updating, bug fixes, etc. Consequently, the broader challenges in enabling ongoing support for research software used for any type of research are equally relevant to AI-driven research and presented here.&lt;/p&gt;
&lt;p&gt;There is also a need to better support the people who develop and maintain the research software that enables AI-driven research. Because human skills, training, and career paths often feature in AI strategies, it is imperative that stakeholders facilitate practices that support and recognise research software personnel. While the research community is exploring how to leverage AI to improve how research software is developed and maintained, this is also affecting how research software practices should be taught. The paper also illustrates how some countries are operationalising AI strategies that could support the critical element of research software, and have the potential to do so by building on existing investments in research software.&lt;/p&gt;
&lt;p&gt;This paper was written in collaboration with the Research Software Alliance (ReSA) and the Digital Research Alliance of Canada, one of ReSA’s Founding Members. ReSA is a global organisation that unites decision-makers and influencers across the international research software community.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt; is funded by the Government of Canada to serve Canadian researchers, including the infrastructure and activities required for research software. Other community leaders also provided inputs from institutional and open-source perspectives.&lt;/p&gt;
&lt;h2 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;/h2&gt;
&lt;p&gt;This position paper provides a statement on the criticality of research software in artificial intelligence (AI)-driven research. This is needed to ensure that the focus on technological infrastructure to support AI acceleration includes research software — a vital part of that infrastructure. This paper begins by providing definitions for key terms, demonstrating the importance of research software in AI-driven research, and explaining why this paper was developed. The paper then explores the need for AI strategies to recognise research software as a key building block of AI-driven research, and to include this element alongside a focus on computing systems, data, and models. To do this, evidence on the issues in supporting research software, including open-source scientific software, is presented.&lt;/p&gt;
&lt;p&gt;The paper then explores how to better support the people who develop and maintain the research software in AI-driven research. AI strategies often consider people elements such as skills and career paths, which also reflect broader issues for personnel. The paper then illustrates how some countries are operationalising AI strategies that could support the critical element of research software, and have the potential to do so by building on existing investments in research software. Finally, the paper makes recommendations for stakeholders to consider research software in their AI strategies.&lt;/p&gt;
&lt;h2 id=&quot;2-what-is-research-software-and-why-is-it-critical-to-ai&quot;&gt;2. What is research software and why is it critical to AI?&lt;/h2&gt;
&lt;p&gt;Research software is defined in accordance with the FAIR for Research Software Principles (Barker et al. 2022) as “source code files, algorithms, scripts, computational workflows and executables that were created during the research process or for a research purpose. Software components (e.g., operating systems, libraries, dependencies, packages, scripts, etc.) that are used for research but were not created during or with a clear research intent should be considered software in research and not research software. This differentiation may vary between disciplines” (Gruenpeter et al. 2021).&lt;/p&gt;
&lt;p&gt;Research software supports AI, both 1) in more traditional machine learning (ML), where models are trained on data and then used to infer knowledge about new data, and 2) in generative AI, which can be defined as “deep-learning models that can generate high-quality text, images, and other content based on the data they were trained on” (Martineau 2021).&lt;/p&gt;
&lt;p&gt;Research software is already recognised as critical to research outcomes (Barker, Katz, and Gonzalez-Beltran 2020; Hocquet et al. 2024; Strasser et al. 2022). Research software can be a research output in itself, and its many functions range from being a component of research instruments, being the research instrument (where research software generates research data, validates research data, or tests hypotheses, such as models and simulations), analysing and presenting research data, and providing infrastructure or underlying tools (Nieuwpoort and Katz 2024). All machine learning (ML) and AI began as research software. In many cases, AI research software has transitioned outside of research and is widely used outside research today.&lt;/p&gt;
&lt;p&gt;Consequently, research software is essential in AI-based research, where newly developed methods are** research software. Some AI reports and strategies recognise this; for example, OECD’s &lt;a href=&quot;https://www.oecd-ilibrary.org/science-and-technology/artificial-intelligence-in-science_a8d820bd-en&quot;&gt;Artificial Intelligence in Science&lt;/a&gt; report (OECD 2023) highlights the need to better support research software as part of utilising AI to accelerate scientific productivity, in a number of ways, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increase access to software&lt;/li&gt;
&lt;li&gt;Share best practices and applications of research software&lt;/li&gt;
&lt;li&gt;Facilitate more regular funding and more secure positions&lt;/li&gt;
&lt;li&gt;Improve ways to measure research impact and productivity&lt;/li&gt;
&lt;li&gt;Consider academic training changes needed&lt;/li&gt;
&lt;li&gt;Utilise disciplinary consortiums to accelerate discovery and improve reproducibility through the sharing of software&lt;/li&gt;
&lt;li&gt;Understand how AI can speed up research software development&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The research community personnel who develop and maintain research software are just as important as the research software itself, if not more important, as the software will stop working without ongoing maintenance. This maintenance is needed 1) to respond to bugs so that the software continues to be correct, 2) to add new features so that the software continues to be useful as research progresses, 3) to adapt to change in underlying software and hardware or in related software ecosystems, such as changed libraries and computing systems, so that the software continues to work.&lt;/p&gt;
&lt;p&gt;The people who do this work can have many titles, including researchers, research software engineers (RSEs), data scientists, computer scientists, data engineers, bioinformaticians, students, community scientists, and many more (Hettrick et al. 2022; Barker and Buchhorn 2022). The inclusion of improved support for the staff who develop and maintain research software is also emphasised in the UK-focused&lt;a href=&quot;https://www.turing.ac.uk/sites/default/files/2022-09/ukri-requirements-report_final_edits.pdf&quot;&gt; Review of Digital Research Infrastructure Requirements for AI&lt;/a&gt; (Lazauskas et al. 2022). This report’s findings included emphasis that “any investment in any infrastructure for AI would need to be matched by investments in training and support”, with the second highest priority areas identified as funding for RSEs (Lazauskas et al. 2022). The UK’s &lt;a href=&quot;https://doi.org/10.5281/zenodo.4986062&quot;&gt;ExCALIBUR RSE Knowledge Integration Landscape Review&lt;/a&gt; also highlights the need for RSEs to acquire new skills relevant to AI, and notes that “These skill sets also begin to deviate from what is demanded by industries, requiring novel AI software and capabilities’’ (Parsons et al. 2021).&lt;/p&gt;
&lt;p&gt;ReSA’s initial research on recognition of research software in the AI landscape was presented in March 2024 at its &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; meetings. This forum engages representatives from over 60 funding organisations in online meetings and hybrid venues (ReSA 2024a). Attendees of these March meetings were immediately able to utilise these early findings from the presentation to strengthen their own cases for investment in research software within AI-dominated programs, where the criticality of this building block is not yet understood by many in their organisations. It became clear that further research on best practices would support not only funders but a variety of stakeholders in the international research software community.&lt;/p&gt;
&lt;p&gt;The research in this position paper was undertaken as a partnership between &lt;a href=&quot;https://www.researchsoft.org/&quot;&gt;ReSA&lt;/a&gt; and the &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt;, one of ReSA’s &lt;a href=&quot;https://www.researchsoft.org/about-resa/&quot;&gt;Founding Members&lt;/a&gt;. One of ReSA’s key functions is to ensure that research software is considered in international discussions on how to advance research capabilities. ReSA is a global organisation that unites decision-makers and influencers across the international research software community. The Digital Research Alliance of Canada is a non-profit organisation funded by the Government of Canada. It advances Canada’s position as a leader in the knowledge economy on the international stage by integrating, championing and funding the infrastructure and activities required, with research software as one of the three main areas. Other community leaders were also brought in on this paper in order to present more balanced perspectives on the need for research software in AI, particularly from institutional and open source perspectives.&lt;/p&gt;
&lt;h2 id=&quot;3-consequences-if-research-software-is-not-supported&quot;&gt;3. Consequences if research software is not supported&lt;/h2&gt;
&lt;p&gt;There is a tendency for AI initiatives to minimise or exclude focus on research software. This minimisation creates challenges. To show this, evidence on the issues in supporting research software, including open-source scientific software, is also presented here.&lt;/p&gt;
&lt;p&gt;Many AI initiatives tend to focus on computing systems, data, and models, considering issues such as the availability of systems that can train models and use them for inference in reasonable time periods; FAIRness of underlying data as well as its suitability for training models, including regularity and labelling; understanding and reducing bias in data and models; and understanding privacy. The fact that AI models are implemented in software, and that software is required for training, is rarely considered. Basically, models are thought of as extensions of data, not of software as well. Consequently, many AI strategies focus on data and models but exclude the underlying software. An example of an AI strategy that does not necessarily adequately include a research software focus is the US National Institutes of Health (NIH) workshop,&lt;a href=&quot;https://www.scgcorp.com/ethicalframework2024/Agenda&quot;&gt; Towards an ethical framework for AI in biomedical and behavioural research&lt;/a&gt;, which focused on data and models, but not the research software inherent in using the data and models (ODSS 2024).&lt;/p&gt;
&lt;p&gt;This challenge is not limited to research software. Discussions of AI capacity often omit open-source software, instead focusing on areas such as talent, funding, data, semiconductors, and compute access (Engler 2021). Like research software, open-source software can advance science but also has significant effects in other areas such as the development of AI standards (Engler 2021). Further, research software is often either open-source itself or depends on open-source software. But considerations for software from AI initiatives, if any, do not normally include open source software maintenance as a priority, nor analysis of its dependency on other software (Nahar et al. Forthcoming). Where dependency analysis does happen, it is usually due to concerns about supply chain security or perceived attack vectors (a pathway or method used to access a network or computer to attempt to exploit system vulnerabilities).&lt;/p&gt;
&lt;p&gt;The nature of open source software as a complex stack and the concomitant extra step of funding those open source software dependencies of the research software necessary for AI is largely ignored. This could reflect a misunderstanding of how open-source dependencies introduce systemic vulnerabilities that need to be addressed and maintained on an ongoing basis or concerns regarding funding many independent projects down the dependency tree. When open-source software is used without planning for future community or dependency support, the result is a more brittle system in the long run — for research software, open-source software, and AI.&lt;/p&gt;
&lt;p&gt;There has been some recent work done on software bills of materials (SBOMs) in open source supply chains, where dependencies are charted out, in part so that their vulnerabilities can be understood (National Security Agency 2024; SCAWG 2022) (and it is relevant to note that research software is often used to map these dependencies). Mapping supply chains is increasingly important for understanding how to shore up digital infrastructure, where large economies depend upon open-source software that is poorly maintained and that may be internationally broken or hijacked or may break (as in the XZ Utils, Heartbleed, or the Log4j incidents (Goodin 2024; Buchanan 2021), or the more recent CrowdStrike failure which caused a global Windows outage (Robins-Early 2024)). However, SBOMs are merely an atlas for understanding dependencies — they are policy agnostic and their creation doesn’t mandate funding or supporting important open-source or research software.&lt;/p&gt;
&lt;p&gt;This paper suggests that infrastructural issues with using and supporting open source software are similar or identical to issues with using research software. Where AI is involved, the same questions of continued support for the research software being used to develop, train, and run the AI systems are raised. Any AI initiative that plans to use global infrastructure, to adapt to new fields and target areas, or that hopes to exist for the long haul must consider the research software that enables those goals.&lt;/p&gt;
&lt;h2 id=&quot;4-challenges-if-research-software-personnel-are-not-supported&quot;&gt;4. Challenges if research software personnel are not supported&lt;/h2&gt;
&lt;p&gt;There is also a need to better support the people who develop and maintain research software that is important to AI-driven research. This is recognised in relation to research software personnel in general, particularly in relation to the training, hiring, and funding of both professional research and technical staff able to reuse, develop, and maintain sustainable research software; appropriate reward and recognition measures that enable career progression for all people involved in the creation and maintenance of research software; and citation practices for research software that recognise substantial contributors to all aspects of the software (Van Tuyl 2023; US-RSE Association and IEEE Computer Society 2023; Barker and Katz 2022a; ReSA 2023). For example, &lt;a href=&quot;https://zenodo.org/records/10473186&quot;&gt;Software and skills for research computing in the UK&lt;/a&gt; recommendations include facilitating detailed analysis of how to professionalise RSE roles; and collaboration between government, funders, and employers to create national policies aimed at improving standards of employment (Barker et al. 2024).&lt;/p&gt;
&lt;p&gt;Whilst many of the issues for research software, in general, are the same for research software to support AI-driven research, one area of difference is in the specifics of skills and training. Human skills, training, and career paths often feature in AI strategies, and it is important that these focus on relevant research software practices. For example, the&lt;a href=&quot;https://www.turing.ac.uk/sites/default/files/2022-09/ukri-requirements-report_final_edits.pdf&quot;&gt; Review of Digital Research Infrastructure Requirements for AI&lt;/a&gt; specifically emphasises the lack of AI skills and training, and career paths for research personnel, including for RSEs. It highlights that these staff often lack formal training, and ongoing professional development is crucial in the fast-paced world of AI tools and techniques (Lazauskas et al. 2022). With many researchers now using GenAI for coding tasks (Nordling 2023, cited in Hosseini et al. 2024), software development skills need to change to reflect this (Caballar 2024; Dursi 2024).&lt;/p&gt;
&lt;h2 id=&quot;5-national-approaches&quot;&gt;5. National approaches&lt;/h2&gt;
&lt;p&gt;AI is now seen as a geopolitical asset, and as international organisations and a range of countries seek to show leadership for AI in science, some countries are operationalising AI strategies that could support the critical element of research software. However, more focus is needed. One example of discussing software within a national AI strategy is the US &lt;a href=&quot;https://new.nsf.gov/focus-areas/artificial-intelligence/nairr&quot;&gt;National Artificial Intelligence Research Resource&lt;/a&gt; (NAIRR). NAIRR aims to provide a shared national research infrastructure for responsible discovery and innovation in AI, to address the fact that many researchers lack the necessary access to the computing, data, software and educational resources needed. The NAIRR pilot’s four operational focus areas include one area dedicated to software, to “facilitate and investigate interoperable use of AI software, platforms, tools and services for NAIRR pilot resources” (NSF 2024). However, there are potential challenges with this approach as the focus is on interoperability of existing software, which assumes that sustainable software is already in place.&lt;/p&gt;
&lt;p&gt;Many countries also have existing investments in research software (Barker and Katz 2022b; ReSA 2024b) that national initiatives have the potential to build on. The UK’s &lt;a href=&quot;https://www.ukri.org/news/300-million-to-launch-first-phase-of-new-ai-research-resource/&quot;&gt;AI Research Resource&lt;/a&gt; (AIRR) is another example of a national initiative, which focuses on increasing computational power to support AI-driven research (UKRI 2023), although its funding is now uncertain (Trueman 2024). Whilst AIRR does not seem to include a focus on research software, AIRR is a key component of UK Research and Innovation (UKRI)’s &lt;a href=&quot;https://www.ukri.org/what-we-do/creating-world-class-research-and-innovation-infrastructure/digital-research-infrastructure/&quot;&gt;Digital Research Infrastructure&lt;/a&gt; (DRI) which has featured a number of recent investments in research software, including funding of research technical professionals (RTPs), such as RSEs. For example, the Engineering and Physical Sciences Research Council (EPSRC) and UKRI DRI have invested £16 million to support community-driven projects providing training and development for RTPs (UKRI 2024a). UKRI’s &lt;a href=&quot;https://www.ukri.org/opportunity/ukri-digital-research-technical-professional-skills-networkplus/&quot;&gt;Digital RTP Skills NetworkPlus&lt;/a&gt; aims to explore key challenges and interventions related to skills and careers that are faced by digital RTP communities across the UK research and innovation landscape (UKRI 2024b).&lt;/p&gt;
&lt;p&gt;Canada has been a leader in AI, as the first country in the world to put in place in 2017 a fully-funded AI strategy, the &lt;a href=&quot;https://ised-isde.canada.ca/site/ai-strategy/en&quot;&gt;Pan-Canadian AI Strategy&lt;/a&gt; (ISED 2022). The strategy included the establishment of a national program of research chairs to recruit and retain top researchers at Canadian universities, the establishment of three national AI institutes to be global centres of training and research excellence and the creation of a Pan-Canadian AI Compute Environment (PAICE) platform. The Digital Research Alliance of Canada’s &lt;a href=&quot;https://doi.org/10.5281/zenodo.10214741&quot;&gt;National Research Software Strategy&lt;/a&gt; for 2025–2030 (Digital Research Alliance of Canada, National Research Software Strategy Working Group 2023) also reviewed (inter)national research software funding programs in support of AI, deep learning, and ML-facilitated research. Before the Alliance, CANARIE has been a national Research Software funder and service provider since 2007, whose successful research software initiatives had resulted in the development of sophisticated software tools, known as research platforms, that typically support end-to-end research workflow within a specific domain. New platforms re-used software components previously developed through CANARIE funding, and contributed additional components back to the research community, creating a powerful cycle of software development and reuse (CANARIE 2024). The Alliance is now using the &lt;a href=&quot;https://research-software-directory.org/organisations/digital-research-alliance-of-canada?tab=software&amp;#x26;order=is_featured&quot;&gt;Research Software Directory&lt;/a&gt; to continue promoting the visibility, impact, and reuse of the Canadian research software (Digital Research Alliance of Canada 2024).&lt;/p&gt;
&lt;h2 id=&quot;6-recommendations-for-research-software-to-support-ai&quot;&gt;6. Recommendations for research software to support AI&lt;/h2&gt;
&lt;p&gt;Research software needs to be included in AI strategies. Our recommendations for doing so are listed below, organised in three areas from the &lt;a href=&quot;https://doi.org/10.5281/zenodo.8325436&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability&lt;/a&gt; (ReSA 2023):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Research software practice:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI strategies and funding must recognise that research software is a key part of the (publicly funded) AI pipeline and that AI is dependent on software, and therefore should stimulate the development and maintenance of research software to ensure the success of the AI work.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Research software ecosystem:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because AI-driven research is dependent on the existing research software ecosystem, AI strategies should provide long-term support for its elements, including personnel, communities, and infrastructure, and should add new elements that focus on AI-specific parts as needed.&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Research software personnel:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because the existing research software ecosystem that supports AI-driven research is dependent on research software personnel, AI strategies should facilitate appropriate reward and recognition measures that enable career progression for all people involved in the creation and maintenance of research software that supports AI-driven research.&lt;/p&gt;
&lt;p&gt;Other ways to help ensure that the focus on technological infrastructure to support AI acceleration includes research software and its personnel as a vital part of that infrastructure include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://adore.software/get-involved/&quot;&gt;Signing&lt;/a&gt; the &lt;a href=&quot;https://adore.software/declaration/&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability (ADORE.software)&lt;/a&gt;, which represents a first step to formalise, on a global level, the basic principles and recommendations related to funding the sustainability of research software, including the people needed to achieve this goal.&lt;/li&gt;
&lt;li&gt;Supporting ReSA in its aim to ensure that research software is considered in international discussions on how to advance research capabilities. Become a ReSA &lt;a href=&quot;https://www.researchsoft.org/membership/&quot;&gt;Organisational Member&lt;/a&gt;, &lt;a href=&quot;https://www.researchsoft.org/tf-support/&quot;&gt;support a task force&lt;/a&gt;, or &lt;a href=&quot;https://www.researchsoft.org/donate/&quot;&gt;donate&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For funders, joining the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt;, a global collaboration of funding organisations committed to supporting research software, and those who develop and maintain it, as fundamental and vital to research.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Barker, Michelle, Elena Breitmoser, Philippa Broadbent, Neil Chue Hong, Simon Hettrick, Ioanna Lampaki, Anthony Quinn, and Rebecca Taylor. 2024. ‘Software and Skills for Research Computing in the UK’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.10473186&quot;&gt;https://doi.org/10.5281/ZENODO.10473186&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, and Markus Buchhorn. 2022. ‘Research Software Capability in Australia’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6335998&quot;&gt;https://doi.org/10.5281/ZENODO.6335998&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, Neil P. Chue Hong, Daniel S. Katz, Anna-Lena Lamprecht, Carlos Martinez-Ortiz, Fotis Psomopoulos, Jennifer Harrow, et al. 2022. ‘Introducing the FAIR Principles for Research Software’. Scientific Data* 9 (1): 622. &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;https://doi.org/10.1038/s41597-022-01710-x&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, and Daniel S Katz. 2022a. ‘Encouraging Entry, Retention, Diversity and Inclusion in Research Software Careers’. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.7117842&quot;&gt;https://doi.org/10.5281/ZENODO.7117842&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, and Daniel S. Katz. 2022b. ‘Overview of Research Software Funding Landscape’, February. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6102487&quot;&gt;https://doi.org/10.5281/ZENODO.6102487&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, Daniel S. Katz, and Alejandra Gonzalez-Beltran. 2020. ‘Evidence for the Importance of Research Software’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.3884311&quot;&gt;https://doi.org/10.5281/ZENODO.3884311&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Buchanan, Bill. 2021. ‘Log4j: The Worst Vulnerability In Nearly A Decade?’ &lt;em&gt;Medium&lt;/em&gt; (blog). 2021. &lt;a href=&quot;https://medium.com/asecuritysite-when-bob-met-alice/log4j-the-worst-vulnerability-in-nearly-a-decade-e0cc80cbb49a&quot;&gt;https://medium.com/asecuritysite-when-bob-met-alice/log4j-the-worst-vulnerability-in-nearly-a-decade-e0cc80cbb49a&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Caballar, Rina Diane. 2024. ‘AI Copilots Are Changing How Coding Is Taught — IEEE Spectrum’. 2 May 2024. &lt;a href=&quot;https://spectrum.ieee.org/ai-coding&quot;&gt;https://spectrum.ieee.org/ai-coding&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CANARIE. 2024. ‘Funded Research Software Platforms’. 2024. &lt;a href=&quot;https://www.canarie.ca/software/platforms/&quot;&gt;https://www.canarie.ca/software/platforms/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Digital Research Alliance of Canada. 2024. ‘Research Software Directory’. 2024. &lt;a href=&quot;https://research-software-directory.org/organisations/digital-research-alliance-of-canada?tab=software&amp;#x26;order=is_featured&quot;&gt;https://research-software-directory.org/organisations/digital-research-alliance-of-canada?tab=software&amp;#x26;order=is_featured&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Digital Research Alliance of Canada, National Research Software Strategy Working Group. 2023. ‘National Research Software Strategy 2023’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.10214741&quot;&gt;https://doi.org/10.5281/ZENODO.10214741&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dursi, Jonathan. 2024. ‘We Need To Talk About AI’. &lt;em&gt;Research Computing Teams&lt;/em&gt; 183 (June). &lt;a href=&quot;https://newsletter.researchcomputingteams.org/archive/rct-183-we-need-to-talk-about-ai-plus-upfront/&quot;&gt;https://newsletter.researchcomputingteams.org/archive/rct-183-we-need-to-talk-about-ai-plus-upfront/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Engler, Alex. 2021. ‘How Open-Source Software Shapes AI Policy’. Brookings. 10 August 2021. &lt;a href=&quot;https://www.brookings.edu/articles/how-open-source-software-shapes-ai-policy/&quot;&gt;https://www.brookings.edu/articles/how-open-source-software-shapes-ai-policy/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Goodin, Dan. 2024. ‘The XZ Backdoor: Everything You Need to Know’. Wired. 2 April 2024. &lt;a href=&quot;https://www.wired.com/story/xz-backdoor-everything-you-need-to-know/&quot;&gt;https://www.wired.com/story/xz-backdoor-everything-you-need-to-know/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gruenpeter, Morane, Daniel S. Katz, Anna-Lena Lamprecht, Tom Honeyman, Daniel Garijo, Alexander Struck, Anna Niehues, et al. 2021. ‘Defining Research Software: A Controversial Discussion’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.5504016&quot;&gt;https://doi.org/10.5281/ZENODO.5504016&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hettrick, Simon, Radovan Bast, Steve Crouch, Claire Bradley, Philippe, Botzki, Alex, Carver, Jeffrey, et al. 2022. ‘International RSE Survey 2022’. &lt;a href=&quot;https://softwaresaved.github.io/international-survey-2022/&quot;&gt;https://softwaresaved.github.io/international-survey-2022/&lt;/a&gt;. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6884882&quot;&gt;https://doi.org/10.5281/ZENODO.6884882&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hocquet, Alexandre, Frédéric Wieber, Gabriele Gramelsberger, Konrad Hinsen, Markus Diesmann, Fernando Pasquini Santos, Catharina Landström, et al. 2024. ‘Software in Science Is Ubiquitous yet Overlooked’. &lt;em&gt;Nature Computational Science&lt;/em&gt;, July. &lt;a href=&quot;https://doi.org/10.1038/s43588-024-00651-2&quot;&gt;https://doi.org/10.1038/s43588-024-00651-2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ISED. 2022. ‘Pan-Canadian Artificial Intelligence Strategy’. Home page; Innovation, Science and Economic Development Canada. 20 July 2022. &lt;a href=&quot;https://ised-isde.canada.ca/site/ai-strategy/en/pan-canadian-artificial-intelligence-strategy&quot;&gt;https://ised-isde.canada.ca/site/ai-strategy/en/pan-canadian-artificial-intelligence-strategy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lazauskas, Tomas, Jennifer Ding, Neil Brown, Reda Nausedaite, Felix Dijkstal, Aaron Vinnik, Bruno Raabe, et al. 2022. ‘Review of Digital Research Infrastructure Requirements for AI’. &lt;a href=&quot;https://doi.org/10.13140/RG.2.2.29376.00009&quot;&gt;https://doi.org/10.13140/RG.2.2.29376.00009&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Martineau, Kim. 2021. ‘What Is Generative AI?’ IBM Research. 9 February 2021. &lt;a href=&quot;https://research.ibm.com/blog/what-is-generative-AI&quot;&gt;https://research.ibm.com/blog/what-is-generative-AI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nahar, Nadia, Haoran Zhang, Grace Lewis, Shurui Zhou, and Christian Kästner. Forthcoming. ‘The Product Beyond the Model — An Empirical Study of Repositories of Open-Source ML Products’. In . &lt;a href=&quot;https://www.cs.cmu.edu/~ckaestne/publications.html&quot;&gt;https://www.cs.cmu.edu/~ckaestne/publications.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;National Security Agency. 2024. ‘Recommendations for Software Bill of Materials (SBOM) Management’. &lt;a href=&quot;https://media.defense.gov/2023/Dec/14/2003359097/-1/-1/0/CSI-SCRM-SBOM-MANAGEMENT.PDF&quot;&gt;https://media.defense.gov/2023/Dec/14/2003359097/-1/-1/0/CSI-SCRM-SBOM-MANAGEMENT.PDF&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nordling, Linda. 2023. ‘How ChatGPT Is Transforming the Postdoc Experience’. &lt;em&gt;Nature&lt;/em&gt; 622 (7983): 655–57. &lt;a href=&quot;https://doi.org/10.1038/d41586-023-03235-8&quot;&gt;https://doi.org/10.1038/d41586-023-03235-8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;NSF. 2024. ‘National Artificial Intelligence Research Resource Pilot’. 2024. &lt;a href=&quot;https://new.nsf.gov/focus-areas/artificial-intelligence/nairr&quot;&gt;https://new.nsf.gov/focus-areas/artificial-intelligence/nairr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ODSS. 2024. ‘Toward an Ethical Framework for AI in Biomedical and Behavioral Research’. 2024. &lt;a href=&quot;https://www.scgcorp.com/ethicalframework2024/Agenda&quot;&gt;https://www.scgcorp.com/ethicalframework2024/Agenda&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;OECD. 2023. &lt;em&gt;Artificial Intelligence in Science: Challenges, Opportunities and the Future of Research&lt;/em&gt;. OECD. &lt;a href=&quot;https://doi.org/10.1787/a8d820bd-en&quot;&gt;https://doi.org/10.1787/a8d820bd-en&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Parsons, Mark, Alastair Basden, Richard Bower, Neil P. Chue Hong, Davide Constanzo, Shaun Witt, Luigi Del Debbio, et al. 2021. ‘ExCALIBUR Research Software Engineer Knowledge Integration Landscape Review’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.4986062&quot;&gt;https://doi.org/10.5281/ZENODO.4986062&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ReSA. 2023. ‘Amsterdam Declaration on Funding Research Software Sustainability’, August. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.8325436&quot;&gt;https://doi.org/10.5281/ZENODO.8325436&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024a. ‘Research Software Funders Forum’. 2024. &lt;a href=&quot;https://researchsoft.org/funders-forum/&quot;&gt;https://researchsoft.org/funders-forum/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024b. ‘Research Software Funding Opportunities’. 2024. &lt;a href=&quot;https://researchsoft.org/funding-opportunities/&quot;&gt;https://researchsoft.org/funding-opportunities/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Robins-Early, Nick. 2024. ‘What Is CrowdStrike, and How Did It Cause a Global Windows Outage?’ &lt;em&gt;The Guardian&lt;/em&gt;, 19 July 2024. &lt;a href=&quot;https://www.theguardian.com/technology/article/2024/jul/19/what-is-crowdstrike-microsoft-windows-outage&quot;&gt;https://www.theguardian.com/technology/article/2024/jul/19/what-is-crowdstrike-microsoft-windows-outage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;SCAWG. 2022. ‘Recommendations to Improve the Resilience of Canada’s Digital Supply Chain’. &lt;a href=&quot;https://ised-isde.canada.ca/site/spectrum-management-telecommunications/sites/default/files/attachments/2022/CFDIR-June2022-recommendations.pdf&quot;&gt;https://ised-isde.canada.ca/site/spectrum-management-telecommunications/sites/default/files/attachments/2022/CFDIR-June2022-recommendations.pdf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Strasser, Carly, Kate Hertweck, Josh Greenberg, Dario Taraborelli, and Elizabeth Vu. 2022. ’10 Simple Rules for Funding Scientific Open Source Software’, June. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6611500&quot;&gt;https://doi.org/10.5281/ZENODO.6611500&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Trueman, Charlotte. 2024. ‘UK Government Shelves £1.3bn of Tech and AI Projects; Scraps Plans for First Exascale Supercomputer in Edinburgh’. 2 August 2024. &lt;a href=&quot;https://www.datacenterdynamics.com/en/news/uk-government-shelves-13bn-of-tech-and-ai-projects-scraps-plans-for-first-exascale-supercomputer-in-edinburgh/&quot;&gt;https://www.datacenterdynamics.com/en/news/uk-government-shelves-13bn-of-tech-and-ai-projects-scraps-plans-for-first-exascale-supercomputer-in-edinburgh/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;UKRI. 2023. ‘£300 Million to Launch First Phase of New AI Research Resource’. 1 November 2023. &lt;a href=&quot;https://www.ukri.org/news/300-million-to-launch-first-phase-of-new-ai-research-resource/&quot;&gt;https://www.ukri.org/news/300-million-to-launch-first-phase-of-new-ai-research-resource/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024a. ‘New Funding to Support Research Technical Professionals’. 18 March 2024. &lt;a href=&quot;https://www.ukri.org/news/new-funding-to-support-research-technical-professionals/&quot;&gt;https://www.ukri.org/news/new-funding-to-support-research-technical-professionals/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024b. ‘UKRI Digital Research Technical Professional Skills NetworkPlus’. 22 April 2024. &lt;a href=&quot;https://www.ukri.org/opportunity/ukri-digital-research-technical-professional-skills-networkplus/&quot;&gt;https://www.ukri.org/opportunity/ukri-digital-research-technical-professional-skills-networkplus/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;US-RSE Association and IEEE Computer Society. 2023. ‘Research Software Engineers: Creating a Career Path — and a Career’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.10073232&quot;&gt;https://doi.org/10.5281/ZENODO.10073232&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Van Tuyl, Steve (Ed.). 2023. ‘Hiring, Managing, and Retaining Data Scientists and Research Software Engineers in Academia: A Career Guidebook from ADSA and US-RSE’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.8274378&quot;&gt;https://doi.org/10.5281/ZENODO.8274378&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 22 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;By Michelle Barker, Kim Hartley, Daniel S. Katz, Richard Littauer, Qian Zhang, Shurui Zhou, Jyoti Bhogal&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cross-posted from ReSA and the Digital Research Alliance of Canada&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Research software is critical to the future of AI-driven research&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/research-software-is-critical-to-the-fut-cea947aa.CtbIw_yP_2h44w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo credit: &lt;a href=&quot;https://www.shutterstock.com/g/TheMezereon&quot;&gt;TheMezereon&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This position paper provides a statement on the criticality of research software in artificial intelligence (AI)-driven research and makes recommendations for stakeholders on how to consider research software in their AI goals. This is needed to ensure that the focus on technological infrastructure to support AI acceleration includes research software and its personnel as a vital part of that infrastructure. This paper discusses both research software that supports generative AI, which is now being explored today as a tool to enable new research, as well as more traditional machine learning, which has demonstrated impact in research in most disciplines (particularly in the last decade).&lt;/p&gt;
&lt;p&gt;This paper begins by providing definitions for key terms and demonstrating the importance of research software in AI-driven research. The paper then explores the need for AI strategies to recognise research software as key building blocks of AI-driven research, and to include this element alongside a focus on computing systems, data, and models. The fact that AI is dependent on software (i.e., data preparation and model training are performed by software, models are implemented in software) is not always adequately considered. Alongside this high-level need for incorporation of research software in AI strategies, the challenges inherent in software dependencies also need consideration, as research software requires continual maintenance, updating, bug fixes, etc. Consequently, the broader challenges in enabling ongoing support for research software used for any type of research are equally relevant to AI-driven research and presented here.&lt;/p&gt;
&lt;p&gt;There is also a need to better support the people who develop and maintain the research software that enables AI-driven research. Because human skills, training, and career paths often feature in AI strategies, it is imperative that stakeholders facilitate practices that support and recognise research software personnel. While the research community is exploring how to leverage AI to improve how research software is developed and maintained, this is also affecting how research software practices should be taught. The paper also illustrates how some countries are operationalising AI strategies that could support the critical element of research software, and have the potential to do so by building on existing investments in research software.&lt;/p&gt;
&lt;p&gt;This paper was written in collaboration with the Research Software Alliance (ReSA) and the Digital Research Alliance of Canada, one of ReSA’s Founding Members. ReSA is a global organisation that unites decision-makers and influencers across the international research software community.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt; is funded by the Government of Canada to serve Canadian researchers, including the infrastructure and activities required for research software. Other community leaders also provided inputs from institutional and open-source perspectives.&lt;/p&gt;
&lt;h2 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;/h2&gt;
&lt;p&gt;This position paper provides a statement on the criticality of research software in artificial intelligence (AI)-driven research. This is needed to ensure that the focus on technological infrastructure to support AI acceleration includes research software — a vital part of that infrastructure. This paper begins by providing definitions for key terms, demonstrating the importance of research software in AI-driven research, and explaining why this paper was developed. The paper then explores the need for AI strategies to recognise research software as a key building block of AI-driven research, and to include this element alongside a focus on computing systems, data, and models. To do this, evidence on the issues in supporting research software, including open-source scientific software, is presented.&lt;/p&gt;
&lt;p&gt;The paper then explores how to better support the people who develop and maintain the research software in AI-driven research. AI strategies often consider people elements such as skills and career paths, which also reflect broader issues for personnel. The paper then illustrates how some countries are operationalising AI strategies that could support the critical element of research software, and have the potential to do so by building on existing investments in research software. Finally, the paper makes recommendations for stakeholders to consider research software in their AI strategies.&lt;/p&gt;
&lt;h2 id=&quot;2-what-is-research-software-and-why-is-it-critical-to-ai&quot;&gt;2. What is research software and why is it critical to AI?&lt;/h2&gt;
&lt;p&gt;Research software is defined in accordance with the FAIR for Research Software Principles (Barker et al. 2022) as “source code files, algorithms, scripts, computational workflows and executables that were created during the research process or for a research purpose. Software components (e.g., operating systems, libraries, dependencies, packages, scripts, etc.) that are used for research but were not created during or with a clear research intent should be considered software in research and not research software. This differentiation may vary between disciplines” (Gruenpeter et al. 2021).&lt;/p&gt;
&lt;p&gt;Research software supports AI, both 1) in more traditional machine learning (ML), where models are trained on data and then used to infer knowledge about new data, and 2) in generative AI, which can be defined as “deep-learning models that can generate high-quality text, images, and other content based on the data they were trained on” (Martineau 2021).&lt;/p&gt;
&lt;p&gt;Research software is already recognised as critical to research outcomes (Barker, Katz, and Gonzalez-Beltran 2020; Hocquet et al. 2024; Strasser et al. 2022). Research software can be a research output in itself, and its many functions range from being a component of research instruments, being the research instrument (where research software generates research data, validates research data, or tests hypotheses, such as models and simulations), analysing and presenting research data, and providing infrastructure or underlying tools (Nieuwpoort and Katz 2024). All machine learning (ML) and AI began as research software. In many cases, AI research software has transitioned outside of research and is widely used outside research today.&lt;/p&gt;
&lt;p&gt;Consequently, research software is essential in AI-based research, where newly developed methods are** research software. Some AI reports and strategies recognise this; for example, OECD’s &lt;a href=&quot;https://www.oecd-ilibrary.org/science-and-technology/artificial-intelligence-in-science_a8d820bd-en&quot;&gt;Artificial Intelligence in Science&lt;/a&gt; report (OECD 2023) highlights the need to better support research software as part of utilising AI to accelerate scientific productivity, in a number of ways, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increase access to software&lt;/li&gt;
&lt;li&gt;Share best practices and applications of research software&lt;/li&gt;
&lt;li&gt;Facilitate more regular funding and more secure positions&lt;/li&gt;
&lt;li&gt;Improve ways to measure research impact and productivity&lt;/li&gt;
&lt;li&gt;Consider academic training changes needed&lt;/li&gt;
&lt;li&gt;Utilise disciplinary consortiums to accelerate discovery and improve reproducibility through the sharing of software&lt;/li&gt;
&lt;li&gt;Understand how AI can speed up research software development&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The research community personnel who develop and maintain research software are just as important as the research software itself, if not more important, as the software will stop working without ongoing maintenance. This maintenance is needed 1) to respond to bugs so that the software continues to be correct, 2) to add new features so that the software continues to be useful as research progresses, 3) to adapt to change in underlying software and hardware or in related software ecosystems, such as changed libraries and computing systems, so that the software continues to work.&lt;/p&gt;
&lt;p&gt;The people who do this work can have many titles, including researchers, research software engineers (RSEs), data scientists, computer scientists, data engineers, bioinformaticians, students, community scientists, and many more (Hettrick et al. 2022; Barker and Buchhorn 2022). The inclusion of improved support for the staff who develop and maintain research software is also emphasised in the UK-focused&lt;a href=&quot;https://www.turing.ac.uk/sites/default/files/2022-09/ukri-requirements-report_final_edits.pdf&quot;&gt; Review of Digital Research Infrastructure Requirements for AI&lt;/a&gt; (Lazauskas et al. 2022). This report’s findings included emphasis that “any investment in any infrastructure for AI would need to be matched by investments in training and support”, with the second highest priority areas identified as funding for RSEs (Lazauskas et al. 2022). The UK’s &lt;a href=&quot;https://doi.org/10.5281/zenodo.4986062&quot;&gt;ExCALIBUR RSE Knowledge Integration Landscape Review&lt;/a&gt; also highlights the need for RSEs to acquire new skills relevant to AI, and notes that “These skill sets also begin to deviate from what is demanded by industries, requiring novel AI software and capabilities’’ (Parsons et al. 2021).&lt;/p&gt;
&lt;p&gt;ReSA’s initial research on recognition of research software in the AI landscape was presented in March 2024 at its &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; meetings. This forum engages representatives from over 60 funding organisations in online meetings and hybrid venues (ReSA 2024a). Attendees of these March meetings were immediately able to utilise these early findings from the presentation to strengthen their own cases for investment in research software within AI-dominated programs, where the criticality of this building block is not yet understood by many in their organisations. It became clear that further research on best practices would support not only funders but a variety of stakeholders in the international research software community.&lt;/p&gt;
&lt;p&gt;The research in this position paper was undertaken as a partnership between &lt;a href=&quot;https://www.researchsoft.org/&quot;&gt;ReSA&lt;/a&gt; and the &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt;, one of ReSA’s &lt;a href=&quot;https://www.researchsoft.org/about-resa/&quot;&gt;Founding Members&lt;/a&gt;. One of ReSA’s key functions is to ensure that research software is considered in international discussions on how to advance research capabilities. ReSA is a global organisation that unites decision-makers and influencers across the international research software community. The Digital Research Alliance of Canada is a non-profit organisation funded by the Government of Canada. It advances Canada’s position as a leader in the knowledge economy on the international stage by integrating, championing and funding the infrastructure and activities required, with research software as one of the three main areas. Other community leaders were also brought in on this paper in order to present more balanced perspectives on the need for research software in AI, particularly from institutional and open source perspectives.&lt;/p&gt;
&lt;h2 id=&quot;3-consequences-if-research-software-is-not-supported&quot;&gt;3. Consequences if research software is not supported&lt;/h2&gt;
&lt;p&gt;There is a tendency for AI initiatives to minimise or exclude focus on research software. This minimisation creates challenges. To show this, evidence on the issues in supporting research software, including open-source scientific software, is also presented here.&lt;/p&gt;
&lt;p&gt;Many AI initiatives tend to focus on computing systems, data, and models, considering issues such as the availability of systems that can train models and use them for inference in reasonable time periods; FAIRness of underlying data as well as its suitability for training models, including regularity and labelling; understanding and reducing bias in data and models; and understanding privacy. The fact that AI models are implemented in software, and that software is required for training, is rarely considered. Basically, models are thought of as extensions of data, not of software as well. Consequently, many AI strategies focus on data and models but exclude the underlying software. An example of an AI strategy that does not necessarily adequately include a research software focus is the US National Institutes of Health (NIH) workshop,&lt;a href=&quot;https://www.scgcorp.com/ethicalframework2024/Agenda&quot;&gt; Towards an ethical framework for AI in biomedical and behavioural research&lt;/a&gt;, which focused on data and models, but not the research software inherent in using the data and models (ODSS 2024).&lt;/p&gt;
&lt;p&gt;This challenge is not limited to research software. Discussions of AI capacity often omit open-source software, instead focusing on areas such as talent, funding, data, semiconductors, and compute access (Engler 2021). Like research software, open-source software can advance science but also has significant effects in other areas such as the development of AI standards (Engler 2021). Further, research software is often either open-source itself or depends on open-source software. But considerations for software from AI initiatives, if any, do not normally include open source software maintenance as a priority, nor analysis of its dependency on other software (Nahar et al. Forthcoming). Where dependency analysis does happen, it is usually due to concerns about supply chain security or perceived attack vectors (a pathway or method used to access a network or computer to attempt to exploit system vulnerabilities).&lt;/p&gt;
&lt;p&gt;The nature of open source software as a complex stack and the concomitant extra step of funding those open source software dependencies of the research software necessary for AI is largely ignored. This could reflect a misunderstanding of how open-source dependencies introduce systemic vulnerabilities that need to be addressed and maintained on an ongoing basis or concerns regarding funding many independent projects down the dependency tree. When open-source software is used without planning for future community or dependency support, the result is a more brittle system in the long run — for research software, open-source software, and AI.&lt;/p&gt;
&lt;p&gt;There has been some recent work done on software bills of materials (SBOMs) in open source supply chains, where dependencies are charted out, in part so that their vulnerabilities can be understood (National Security Agency 2024; SCAWG 2022) (and it is relevant to note that research software is often used to map these dependencies). Mapping supply chains is increasingly important for understanding how to shore up digital infrastructure, where large economies depend upon open-source software that is poorly maintained and that may be internationally broken or hijacked or may break (as in the XZ Utils, Heartbleed, or the Log4j incidents (Goodin 2024; Buchanan 2021), or the more recent CrowdStrike failure which caused a global Windows outage (Robins-Early 2024)). However, SBOMs are merely an atlas for understanding dependencies — they are policy agnostic and their creation doesn’t mandate funding or supporting important open-source or research software.&lt;/p&gt;
&lt;p&gt;This paper suggests that infrastructural issues with using and supporting open source software are similar or identical to issues with using research software. Where AI is involved, the same questions of continued support for the research software being used to develop, train, and run the AI systems are raised. Any AI initiative that plans to use global infrastructure, to adapt to new fields and target areas, or that hopes to exist for the long haul must consider the research software that enables those goals.&lt;/p&gt;
&lt;h2 id=&quot;4-challenges-if-research-software-personnel-are-not-supported&quot;&gt;4. Challenges if research software personnel are not supported&lt;/h2&gt;
&lt;p&gt;There is also a need to better support the people who develop and maintain research software that is important to AI-driven research. This is recognised in relation to research software personnel in general, particularly in relation to the training, hiring, and funding of both professional research and technical staff able to reuse, develop, and maintain sustainable research software; appropriate reward and recognition measures that enable career progression for all people involved in the creation and maintenance of research software; and citation practices for research software that recognise substantial contributors to all aspects of the software (Van Tuyl 2023; US-RSE Association and IEEE Computer Society 2023; Barker and Katz 2022a; ReSA 2023). For example, &lt;a href=&quot;https://zenodo.org/records/10473186&quot;&gt;Software and skills for research computing in the UK&lt;/a&gt; recommendations include facilitating detailed analysis of how to professionalise RSE roles; and collaboration between government, funders, and employers to create national policies aimed at improving standards of employment (Barker et al. 2024).&lt;/p&gt;
&lt;p&gt;Whilst many of the issues for research software, in general, are the same for research software to support AI-driven research, one area of difference is in the specifics of skills and training. Human skills, training, and career paths often feature in AI strategies, and it is important that these focus on relevant research software practices. For example, the&lt;a href=&quot;https://www.turing.ac.uk/sites/default/files/2022-09/ukri-requirements-report_final_edits.pdf&quot;&gt; Review of Digital Research Infrastructure Requirements for AI&lt;/a&gt; specifically emphasises the lack of AI skills and training, and career paths for research personnel, including for RSEs. It highlights that these staff often lack formal training, and ongoing professional development is crucial in the fast-paced world of AI tools and techniques (Lazauskas et al. 2022). With many researchers now using GenAI for coding tasks (Nordling 2023, cited in Hosseini et al. 2024), software development skills need to change to reflect this (Caballar 2024; Dursi 2024).&lt;/p&gt;
&lt;h2 id=&quot;5-national-approaches&quot;&gt;5. National approaches&lt;/h2&gt;
&lt;p&gt;AI is now seen as a geopolitical asset, and as international organisations and a range of countries seek to show leadership for AI in science, some countries are operationalising AI strategies that could support the critical element of research software. However, more focus is needed. One example of discussing software within a national AI strategy is the US &lt;a href=&quot;https://new.nsf.gov/focus-areas/artificial-intelligence/nairr&quot;&gt;National Artificial Intelligence Research Resource&lt;/a&gt; (NAIRR). NAIRR aims to provide a shared national research infrastructure for responsible discovery and innovation in AI, to address the fact that many researchers lack the necessary access to the computing, data, software and educational resources needed. The NAIRR pilot’s four operational focus areas include one area dedicated to software, to “facilitate and investigate interoperable use of AI software, platforms, tools and services for NAIRR pilot resources” (NSF 2024). However, there are potential challenges with this approach as the focus is on interoperability of existing software, which assumes that sustainable software is already in place.&lt;/p&gt;
&lt;p&gt;Many countries also have existing investments in research software (Barker and Katz 2022b; ReSA 2024b) that national initiatives have the potential to build on. The UK’s &lt;a href=&quot;https://www.ukri.org/news/300-million-to-launch-first-phase-of-new-ai-research-resource/&quot;&gt;AI Research Resource&lt;/a&gt; (AIRR) is another example of a national initiative, which focuses on increasing computational power to support AI-driven research (UKRI 2023), although its funding is now uncertain (Trueman 2024). Whilst AIRR does not seem to include a focus on research software, AIRR is a key component of UK Research and Innovation (UKRI)’s &lt;a href=&quot;https://www.ukri.org/what-we-do/creating-world-class-research-and-innovation-infrastructure/digital-research-infrastructure/&quot;&gt;Digital Research Infrastructure&lt;/a&gt; (DRI) which has featured a number of recent investments in research software, including funding of research technical professionals (RTPs), such as RSEs. For example, the Engineering and Physical Sciences Research Council (EPSRC) and UKRI DRI have invested £16 million to support community-driven projects providing training and development for RTPs (UKRI 2024a). UKRI’s &lt;a href=&quot;https://www.ukri.org/opportunity/ukri-digital-research-technical-professional-skills-networkplus/&quot;&gt;Digital RTP Skills NetworkPlus&lt;/a&gt; aims to explore key challenges and interventions related to skills and careers that are faced by digital RTP communities across the UK research and innovation landscape (UKRI 2024b).&lt;/p&gt;
&lt;p&gt;Canada has been a leader in AI, as the first country in the world to put in place in 2017 a fully-funded AI strategy, the &lt;a href=&quot;https://ised-isde.canada.ca/site/ai-strategy/en&quot;&gt;Pan-Canadian AI Strategy&lt;/a&gt; (ISED 2022). The strategy included the establishment of a national program of research chairs to recruit and retain top researchers at Canadian universities, the establishment of three national AI institutes to be global centres of training and research excellence and the creation of a Pan-Canadian AI Compute Environment (PAICE) platform. The Digital Research Alliance of Canada’s &lt;a href=&quot;https://doi.org/10.5281/zenodo.10214741&quot;&gt;National Research Software Strategy&lt;/a&gt; for 2025–2030 (Digital Research Alliance of Canada, National Research Software Strategy Working Group 2023) also reviewed (inter)national research software funding programs in support of AI, deep learning, and ML-facilitated research. Before the Alliance, CANARIE has been a national Research Software funder and service provider since 2007, whose successful research software initiatives had resulted in the development of sophisticated software tools, known as research platforms, that typically support end-to-end research workflow within a specific domain. New platforms re-used software components previously developed through CANARIE funding, and contributed additional components back to the research community, creating a powerful cycle of software development and reuse (CANARIE 2024). The Alliance is now using the &lt;a href=&quot;https://research-software-directory.org/organisations/digital-research-alliance-of-canada?tab=software&amp;#x26;order=is_featured&quot;&gt;Research Software Directory&lt;/a&gt; to continue promoting the visibility, impact, and reuse of the Canadian research software (Digital Research Alliance of Canada 2024).&lt;/p&gt;
&lt;h2 id=&quot;6-recommendations-for-research-software-to-support-ai&quot;&gt;6. Recommendations for research software to support AI&lt;/h2&gt;
&lt;p&gt;Research software needs to be included in AI strategies. Our recommendations for doing so are listed below, organised in three areas from the &lt;a href=&quot;https://doi.org/10.5281/zenodo.8325436&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability&lt;/a&gt; (ReSA 2023):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Research software practice:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI strategies and funding must recognise that research software is a key part of the (publicly funded) AI pipeline and that AI is dependent on software, and therefore should stimulate the development and maintenance of research software to ensure the success of the AI work.&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Research software ecosystem:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because AI-driven research is dependent on the existing research software ecosystem, AI strategies should provide long-term support for its elements, including personnel, communities, and infrastructure, and should add new elements that focus on AI-specific parts as needed.&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Research software personnel:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because the existing research software ecosystem that supports AI-driven research is dependent on research software personnel, AI strategies should facilitate appropriate reward and recognition measures that enable career progression for all people involved in the creation and maintenance of research software that supports AI-driven research.&lt;/p&gt;
&lt;p&gt;Other ways to help ensure that the focus on technological infrastructure to support AI acceleration includes research software and its personnel as a vital part of that infrastructure include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://adore.software/get-involved/&quot;&gt;Signing&lt;/a&gt; the &lt;a href=&quot;https://adore.software/declaration/&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability (ADORE.software)&lt;/a&gt;, which represents a first step to formalise, on a global level, the basic principles and recommendations related to funding the sustainability of research software, including the people needed to achieve this goal.&lt;/li&gt;
&lt;li&gt;Supporting ReSA in its aim to ensure that research software is considered in international discussions on how to advance research capabilities. Become a ReSA &lt;a href=&quot;https://www.researchsoft.org/membership/&quot;&gt;Organisational Member&lt;/a&gt;, &lt;a href=&quot;https://www.researchsoft.org/tf-support/&quot;&gt;support a task force&lt;/a&gt;, or &lt;a href=&quot;https://www.researchsoft.org/donate/&quot;&gt;donate&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For funders, joining the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt;, a global collaboration of funding organisations committed to supporting research software, and those who develop and maintain it, as fundamental and vital to research.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Barker, Michelle, Elena Breitmoser, Philippa Broadbent, Neil Chue Hong, Simon Hettrick, Ioanna Lampaki, Anthony Quinn, and Rebecca Taylor. 2024. ‘Software and Skills for Research Computing in the UK’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.10473186&quot;&gt;https://doi.org/10.5281/ZENODO.10473186&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, and Markus Buchhorn. 2022. ‘Research Software Capability in Australia’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6335998&quot;&gt;https://doi.org/10.5281/ZENODO.6335998&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, Neil P. Chue Hong, Daniel S. Katz, Anna-Lena Lamprecht, Carlos Martinez-Ortiz, Fotis Psomopoulos, Jennifer Harrow, et al. 2022. ‘Introducing the FAIR Principles for Research Software’. Scientific Data* 9 (1): 622. &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;https://doi.org/10.1038/s41597-022-01710-x&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, and Daniel S Katz. 2022a. ‘Encouraging Entry, Retention, Diversity and Inclusion in Research Software Careers’. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.7117842&quot;&gt;https://doi.org/10.5281/ZENODO.7117842&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, and Daniel S. Katz. 2022b. ‘Overview of Research Software Funding Landscape’, February. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6102487&quot;&gt;https://doi.org/10.5281/ZENODO.6102487&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Barker, Michelle, Daniel S. Katz, and Alejandra Gonzalez-Beltran. 2020. ‘Evidence for the Importance of Research Software’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.3884311&quot;&gt;https://doi.org/10.5281/ZENODO.3884311&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Buchanan, Bill. 2021. ‘Log4j: The Worst Vulnerability In Nearly A Decade?’ &lt;em&gt;Medium&lt;/em&gt; (blog). 2021. &lt;a href=&quot;https://medium.com/asecuritysite-when-bob-met-alice/log4j-the-worst-vulnerability-in-nearly-a-decade-e0cc80cbb49a&quot;&gt;https://medium.com/asecuritysite-when-bob-met-alice/log4j-the-worst-vulnerability-in-nearly-a-decade-e0cc80cbb49a&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Caballar, Rina Diane. 2024. ‘AI Copilots Are Changing How Coding Is Taught — IEEE Spectrum’. 2 May 2024. &lt;a href=&quot;https://spectrum.ieee.org/ai-coding&quot;&gt;https://spectrum.ieee.org/ai-coding&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CANARIE. 2024. ‘Funded Research Software Platforms’. 2024. &lt;a href=&quot;https://www.canarie.ca/software/platforms/&quot;&gt;https://www.canarie.ca/software/platforms/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Digital Research Alliance of Canada. 2024. ‘Research Software Directory’. 2024. &lt;a href=&quot;https://research-software-directory.org/organisations/digital-research-alliance-of-canada?tab=software&amp;#x26;order=is_featured&quot;&gt;https://research-software-directory.org/organisations/digital-research-alliance-of-canada?tab=software&amp;#x26;order=is_featured&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Digital Research Alliance of Canada, National Research Software Strategy Working Group. 2023. ‘National Research Software Strategy 2023’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.10214741&quot;&gt;https://doi.org/10.5281/ZENODO.10214741&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dursi, Jonathan. 2024. ‘We Need To Talk About AI’. &lt;em&gt;Research Computing Teams&lt;/em&gt; 183 (June). &lt;a href=&quot;https://newsletter.researchcomputingteams.org/archive/rct-183-we-need-to-talk-about-ai-plus-upfront/&quot;&gt;https://newsletter.researchcomputingteams.org/archive/rct-183-we-need-to-talk-about-ai-plus-upfront/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Engler, Alex. 2021. ‘How Open-Source Software Shapes AI Policy’. Brookings. 10 August 2021. &lt;a href=&quot;https://www.brookings.edu/articles/how-open-source-software-shapes-ai-policy/&quot;&gt;https://www.brookings.edu/articles/how-open-source-software-shapes-ai-policy/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Goodin, Dan. 2024. ‘The XZ Backdoor: Everything You Need to Know’. Wired. 2 April 2024. &lt;a href=&quot;https://www.wired.com/story/xz-backdoor-everything-you-need-to-know/&quot;&gt;https://www.wired.com/story/xz-backdoor-everything-you-need-to-know/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Gruenpeter, Morane, Daniel S. Katz, Anna-Lena Lamprecht, Tom Honeyman, Daniel Garijo, Alexander Struck, Anna Niehues, et al. 2021. ‘Defining Research Software: A Controversial Discussion’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.5504016&quot;&gt;https://doi.org/10.5281/ZENODO.5504016&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hettrick, Simon, Radovan Bast, Steve Crouch, Claire Bradley, Philippe, Botzki, Alex, Carver, Jeffrey, et al. 2022. ‘International RSE Survey 2022’. &lt;a href=&quot;https://softwaresaved.github.io/international-survey-2022/&quot;&gt;https://softwaresaved.github.io/international-survey-2022/&lt;/a&gt;. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6884882&quot;&gt;https://doi.org/10.5281/ZENODO.6884882&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hocquet, Alexandre, Frédéric Wieber, Gabriele Gramelsberger, Konrad Hinsen, Markus Diesmann, Fernando Pasquini Santos, Catharina Landström, et al. 2024. ‘Software in Science Is Ubiquitous yet Overlooked’. &lt;em&gt;Nature Computational Science&lt;/em&gt;, July. &lt;a href=&quot;https://doi.org/10.1038/s43588-024-00651-2&quot;&gt;https://doi.org/10.1038/s43588-024-00651-2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ISED. 2022. ‘Pan-Canadian Artificial Intelligence Strategy’. Home page; Innovation, Science and Economic Development Canada. 20 July 2022. &lt;a href=&quot;https://ised-isde.canada.ca/site/ai-strategy/en/pan-canadian-artificial-intelligence-strategy&quot;&gt;https://ised-isde.canada.ca/site/ai-strategy/en/pan-canadian-artificial-intelligence-strategy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Lazauskas, Tomas, Jennifer Ding, Neil Brown, Reda Nausedaite, Felix Dijkstal, Aaron Vinnik, Bruno Raabe, et al. 2022. ‘Review of Digital Research Infrastructure Requirements for AI’. &lt;a href=&quot;https://doi.org/10.13140/RG.2.2.29376.00009&quot;&gt;https://doi.org/10.13140/RG.2.2.29376.00009&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Martineau, Kim. 2021. ‘What Is Generative AI?’ IBM Research. 9 February 2021. &lt;a href=&quot;https://research.ibm.com/blog/what-is-generative-AI&quot;&gt;https://research.ibm.com/blog/what-is-generative-AI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nahar, Nadia, Haoran Zhang, Grace Lewis, Shurui Zhou, and Christian Kästner. Forthcoming. ‘The Product Beyond the Model — An Empirical Study of Repositories of Open-Source ML Products’. In . &lt;a href=&quot;https://www.cs.cmu.edu/~ckaestne/publications.html&quot;&gt;https://www.cs.cmu.edu/~ckaestne/publications.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;National Security Agency. 2024. ‘Recommendations for Software Bill of Materials (SBOM) Management’. &lt;a href=&quot;https://media.defense.gov/2023/Dec/14/2003359097/-1/-1/0/CSI-SCRM-SBOM-MANAGEMENT.PDF&quot;&gt;https://media.defense.gov/2023/Dec/14/2003359097/-1/-1/0/CSI-SCRM-SBOM-MANAGEMENT.PDF&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nordling, Linda. 2023. ‘How ChatGPT Is Transforming the Postdoc Experience’. &lt;em&gt;Nature&lt;/em&gt; 622 (7983): 655–57. &lt;a href=&quot;https://doi.org/10.1038/d41586-023-03235-8&quot;&gt;https://doi.org/10.1038/d41586-023-03235-8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;NSF. 2024. ‘National Artificial Intelligence Research Resource Pilot’. 2024. &lt;a href=&quot;https://new.nsf.gov/focus-areas/artificial-intelligence/nairr&quot;&gt;https://new.nsf.gov/focus-areas/artificial-intelligence/nairr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ODSS. 2024. ‘Toward an Ethical Framework for AI in Biomedical and Behavioral Research’. 2024. &lt;a href=&quot;https://www.scgcorp.com/ethicalframework2024/Agenda&quot;&gt;https://www.scgcorp.com/ethicalframework2024/Agenda&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;OECD. 2023. &lt;em&gt;Artificial Intelligence in Science: Challenges, Opportunities and the Future of Research&lt;/em&gt;. OECD. &lt;a href=&quot;https://doi.org/10.1787/a8d820bd-en&quot;&gt;https://doi.org/10.1787/a8d820bd-en&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Parsons, Mark, Alastair Basden, Richard Bower, Neil P. Chue Hong, Davide Constanzo, Shaun Witt, Luigi Del Debbio, et al. 2021. ‘ExCALIBUR Research Software Engineer Knowledge Integration Landscape Review’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.4986062&quot;&gt;https://doi.org/10.5281/ZENODO.4986062&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ReSA. 2023. ‘Amsterdam Declaration on Funding Research Software Sustainability’, August. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.8325436&quot;&gt;https://doi.org/10.5281/ZENODO.8325436&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024a. ‘Research Software Funders Forum’. 2024. &lt;a href=&quot;https://researchsoft.org/funders-forum/&quot;&gt;https://researchsoft.org/funders-forum/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024b. ‘Research Software Funding Opportunities’. 2024. &lt;a href=&quot;https://researchsoft.org/funding-opportunities/&quot;&gt;https://researchsoft.org/funding-opportunities/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Robins-Early, Nick. 2024. ‘What Is CrowdStrike, and How Did It Cause a Global Windows Outage?’ &lt;em&gt;The Guardian&lt;/em&gt;, 19 July 2024. &lt;a href=&quot;https://www.theguardian.com/technology/article/2024/jul/19/what-is-crowdstrike-microsoft-windows-outage&quot;&gt;https://www.theguardian.com/technology/article/2024/jul/19/what-is-crowdstrike-microsoft-windows-outage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;SCAWG. 2022. ‘Recommendations to Improve the Resilience of Canada’s Digital Supply Chain’. &lt;a href=&quot;https://ised-isde.canada.ca/site/spectrum-management-telecommunications/sites/default/files/attachments/2022/CFDIR-June2022-recommendations.pdf&quot;&gt;https://ised-isde.canada.ca/site/spectrum-management-telecommunications/sites/default/files/attachments/2022/CFDIR-June2022-recommendations.pdf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Strasser, Carly, Kate Hertweck, Josh Greenberg, Dario Taraborelli, and Elizabeth Vu. 2022. ’10 Simple Rules for Funding Scientific Open Source Software’, June. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.6611500&quot;&gt;https://doi.org/10.5281/ZENODO.6611500&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Trueman, Charlotte. 2024. ‘UK Government Shelves £1.3bn of Tech and AI Projects; Scraps Plans for First Exascale Supercomputer in Edinburgh’. 2 August 2024. &lt;a href=&quot;https://www.datacenterdynamics.com/en/news/uk-government-shelves-13bn-of-tech-and-ai-projects-scraps-plans-for-first-exascale-supercomputer-in-edinburgh/&quot;&gt;https://www.datacenterdynamics.com/en/news/uk-government-shelves-13bn-of-tech-and-ai-projects-scraps-plans-for-first-exascale-supercomputer-in-edinburgh/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;UKRI. 2023. ‘£300 Million to Launch First Phase of New AI Research Resource’. 1 November 2023. &lt;a href=&quot;https://www.ukri.org/news/300-million-to-launch-first-phase-of-new-ai-research-resource/&quot;&gt;https://www.ukri.org/news/300-million-to-launch-first-phase-of-new-ai-research-resource/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024a. ‘New Funding to Support Research Technical Professionals’. 18 March 2024. &lt;a href=&quot;https://www.ukri.org/news/new-funding-to-support-research-technical-professionals/&quot;&gt;https://www.ukri.org/news/new-funding-to-support-research-technical-professionals/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;— — — . 2024b. ‘UKRI Digital Research Technical Professional Skills NetworkPlus’. 22 April 2024. &lt;a href=&quot;https://www.ukri.org/opportunity/ukri-digital-research-technical-professional-skills-networkplus/&quot;&gt;https://www.ukri.org/opportunity/ukri-digital-research-technical-professional-skills-networkplus/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;US-RSE Association and IEEE Computer Society. 2023. ‘Research Software Engineers: Creating a Career Path — and a Career’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.10073232&quot;&gt;https://doi.org/10.5281/ZENODO.10073232&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Van Tuyl, Steve (Ed.). 2023. ‘Hiring, Managing, and Retaining Data Scientists and Research Software Engineers in Academia: A Career Guidebook from ADSA and US-RSE’. Zenodo. &lt;a href=&quot;https://doi.org/10.5281/ZENODO.8274378&quot;&gt;https://doi.org/10.5281/ZENODO.8274378&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/research-software-is-critical-to-the-fut-cea947aa.CtbIw_yP.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Scripting vs. Programming</title><link>https://blog2.esciencecenter.nl/posts/2024-08-01---scripting-vs-programming</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-08-01---scripting-vs-programming</guid><description>&lt;p&gt;][Lourens Veen]·Apr 26, 2023&lt;/p&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Any remaining differences are usually due to particular features supported by certain languages. In R for example, you can write down a statistical model equation, for which it has a special syntax using the &lt;code&gt;~&lt;/code&gt; symbol. There’s no equivalent of that in Python or C or Pascal, because those languages weren’t designed for statistics.&lt;/p&gt;
&lt;h3 id=&quot;structure&quot;&gt;Structure&lt;/h3&gt;
&lt;p&gt;Scripts typically have a simple structure. They consist of a single file, all variables are global, and there may be a function or two but mostly it’s a straightforward list of instructions. This works fine for small scripts, but it becomes impossible to manage for a thousand- or million-line library. To keep those organised, you need functions, classes, packages/modules and namespaces.&lt;/p&gt;
&lt;p&gt;Languages like Java and C++ are designed for this, and do well on this criterion. Python is actually pretty good as well, it does have all of these and there are some large programs written in it. These features are anyway quite common in modern languages, even ones intended for scripting-type work.&lt;/p&gt;
&lt;p&gt;Of course, adding features makes the language more complex (i.e., it makes the manual bigger). Even if you don’t use them, others will, and so you’ll have to learn how they work if you want to be able to use other people’s packages for example. So there is a cost to this additional functionality as well as a benefit, which is what Jisk was getting at with his comment on languages being too “computer science oriented” for what he wants to do.&lt;/p&gt;
&lt;h3 id=&quot;error-handling&quot;&gt;Error handling&lt;/h3&gt;
&lt;p&gt;Finally, error handling. Your basic script handles errors in a basic way: it prints an error message (comprehensible or not) and then halts. Normally, this isn’t done by the script itself but by the programming environment it runs in, with the script simply ignoring the possibility of anything going wrong. This actually works quite well in a notebook environment, where you execute one statement at a time (so it’s usually clear where the problem is) and where there’s a human to read the error message and handle the problem.&lt;/p&gt;
&lt;p&gt;For a web service, or a complex library, or a desktop application, crashing whenever something goes wrong is not acceptable. Errors need to be handled, and only if there’s nothing the program can do to fix it does the error get forwarded to a human, after which we continue with handling the next request. At the language level, this is implemented either through returning an error code from a function, or by using exceptions. Older languages like C and Fortran don’t support exceptions, so all errors have to be signalled and handled explicitly. This means that if you do it right, basically every function call is &lt;a href=&quot;https://github.com/SecConNet/net-admin-helper/blob/8bd39c6ca5fb4c7787bba72b060485e7cc57e3aa/src/container_wireguard.c#L205&quot;&gt;followed by an “if” block that checks for errors and handles them&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This gets very very wordy, so newer languages like Java and Python support exceptions. Exceptions automate keeping track of errors, and by default escalate any errors in a function you called to the function that called you, and so on. In other words, if something goes wrong, you tell the boss, who tells her boss, etc. until the problem reaches someone who can decide what to do. If the error reaches the top without having been solved then the program crashes and the user will have to figure it out, but ideally something handled the problem before we got to that point. Crucially, if the programmer ignores the possibility of errors, then they will end up with the user. That’s not so good, but it’s better than the error being quietly ignored, as would be the case with ignoring returned error codes.&lt;/p&gt;
&lt;p&gt;One disadvantage of exceptions is that to be completely robust, you need to carefully keep track of which exceptions can be raised by functions you call, and make sure you handle them all. In Python, this is pretty much impossible because they’re not documented very well. Java provides syntax for this, and forces you to declare all exceptions a function can raise, which is much better for reliability but is also sure to make Jisk unhappy in his quest for a simple language.&lt;/p&gt;
&lt;p&gt;It’s interesting to see that after all the exceptions in C++ and Java, in yet newer languages like Rust and Go there’s a bit more emphasis on returning errors again. There’s the idea there that most errors are just “normal” possible outcomes of calling a function that should be handled immediately, and that an exception-like “panic” system is to be used only in truly exceptional circumstances. Meanwhile in Python it’s the other way around, and exceptions are sometimes even used for things that are expected to happen during normal control flow (e.g. StopIteration).&lt;/p&gt;
&lt;p&gt;There’s more to say and explain about error handling, and we’ll come back to it in a future TEC. For now, the point is that languages that allow you to completely ignore the possibility of an error occurring are more suitable for scripting, while languages that require you to take possible errors into account lead to more reliable programs.&lt;/p&gt;
&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;So, which language is best for which purpose? Python is obviously good for scripting, and Julia is an interesting alternative that I think may be a better fit for Jisk than Go, seeing as he is interested in calculating things. R seems to work well as a command-line interface for doing statistics but I don’t like it as a programming language (although the Tidyverse is a good development).&lt;/p&gt;
&lt;p&gt;On the programs and libraries side, I’ve built a few slightly bigger systems (in the tens-of-files, thousands-of-lines range) in Python, and it works pretty well, plus you can still put something together very quickly. The downside is that the dynamic typing, lack of encapsulation and lack of exception specifications make it more difficult to make things robust, and performance is also nothing to write home about. Potentially better if slower to work in alternatives would be Java, (modern) C++, and new kid on the block Rust. For now, C++ is my go-to language if I need more performance, even though it’s very complex and by no means perfect.&lt;/p&gt;
&lt;p&gt;What works best for you depends on what you want to do, how much time you have available to learn, a bit on taste, and on external factors like availability of software and of support from the people around you. Many concepts carry over from one language to another though, so don’t worry too much about choosing the wrong one: once you know one programming language, learning others gets a lot easier.&lt;/p&gt;
&lt;p&gt;Well, that concludes the first instalment of The Engineering Corner*. Hope you liked it! Do you write scripts or programs or both? What’s your favourite programming language? Did you like this topic? Was this too basic or too advanced or maybe just right? What would you like to read about next? I’d love to hear about all these things in the comments below. In the mean time:&lt;/p&gt;
&lt;p&gt;Choo choo! Happy Engineering!&lt;/p&gt;
&lt;p&gt;Lourens&lt;/p&gt;
&lt;p&gt;← &amp;#x3C;previous TEC not found&gt; — TEC 1: &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;Better scripts with typing&lt;/a&gt; →&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#2e2f&quot;&gt;[0]&lt;/a&gt; &lt;em&gt;Control flow&lt;/em&gt; refers to the order in which commands are executed, and to branches (if..then) and loops (for.., while..) causing them to be executed not at all, or more than once. In other words, the path through the code taken by the computer’s “cursor” as the code runs.&lt;/p&gt;</description><pubDate>Thu, 01 Aug 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;][Lourens Veen]·Apr 26, 2023&lt;/p&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Any remaining differences are usually due to particular features supported by certain languages. In R for example, you can write down a statistical model equation, for which it has a special syntax using the &lt;code&gt;~&lt;/code&gt; symbol. There’s no equivalent of that in Python or C or Pascal, because those languages weren’t designed for statistics.&lt;/p&gt;
&lt;h3 id=&quot;structure&quot;&gt;Structure&lt;/h3&gt;
&lt;p&gt;Scripts typically have a simple structure. They consist of a single file, all variables are global, and there may be a function or two but mostly it’s a straightforward list of instructions. This works fine for small scripts, but it becomes impossible to manage for a thousand- or million-line library. To keep those organised, you need functions, classes, packages/modules and namespaces.&lt;/p&gt;
&lt;p&gt;Languages like Java and C++ are designed for this, and do well on this criterion. Python is actually pretty good as well, it does have all of these and there are some large programs written in it. These features are anyway quite common in modern languages, even ones intended for scripting-type work.&lt;/p&gt;
&lt;p&gt;Of course, adding features makes the language more complex (i.e., it makes the manual bigger). Even if you don’t use them, others will, and so you’ll have to learn how they work if you want to be able to use other people’s packages for example. So there is a cost to this additional functionality as well as a benefit, which is what Jisk was getting at with his comment on languages being too “computer science oriented” for what he wants to do.&lt;/p&gt;
&lt;h3 id=&quot;error-handling&quot;&gt;Error handling&lt;/h3&gt;
&lt;p&gt;Finally, error handling. Your basic script handles errors in a basic way: it prints an error message (comprehensible or not) and then halts. Normally, this isn’t done by the script itself but by the programming environment it runs in, with the script simply ignoring the possibility of anything going wrong. This actually works quite well in a notebook environment, where you execute one statement at a time (so it’s usually clear where the problem is) and where there’s a human to read the error message and handle the problem.&lt;/p&gt;
&lt;p&gt;For a web service, or a complex library, or a desktop application, crashing whenever something goes wrong is not acceptable. Errors need to be handled, and only if there’s nothing the program can do to fix it does the error get forwarded to a human, after which we continue with handling the next request. At the language level, this is implemented either through returning an error code from a function, or by using exceptions. Older languages like C and Fortran don’t support exceptions, so all errors have to be signalled and handled explicitly. This means that if you do it right, basically every function call is &lt;a href=&quot;https://github.com/SecConNet/net-admin-helper/blob/8bd39c6ca5fb4c7787bba72b060485e7cc57e3aa/src/container_wireguard.c#L205&quot;&gt;followed by an “if” block that checks for errors and handles them&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This gets very very wordy, so newer languages like Java and Python support exceptions. Exceptions automate keeping track of errors, and by default escalate any errors in a function you called to the function that called you, and so on. In other words, if something goes wrong, you tell the boss, who tells her boss, etc. until the problem reaches someone who can decide what to do. If the error reaches the top without having been solved then the program crashes and the user will have to figure it out, but ideally something handled the problem before we got to that point. Crucially, if the programmer ignores the possibility of errors, then they will end up with the user. That’s not so good, but it’s better than the error being quietly ignored, as would be the case with ignoring returned error codes.&lt;/p&gt;
&lt;p&gt;One disadvantage of exceptions is that to be completely robust, you need to carefully keep track of which exceptions can be raised by functions you call, and make sure you handle them all. In Python, this is pretty much impossible because they’re not documented very well. Java provides syntax for this, and forces you to declare all exceptions a function can raise, which is much better for reliability but is also sure to make Jisk unhappy in his quest for a simple language.&lt;/p&gt;
&lt;p&gt;It’s interesting to see that after all the exceptions in C++ and Java, in yet newer languages like Rust and Go there’s a bit more emphasis on returning errors again. There’s the idea there that most errors are just “normal” possible outcomes of calling a function that should be handled immediately, and that an exception-like “panic” system is to be used only in truly exceptional circumstances. Meanwhile in Python it’s the other way around, and exceptions are sometimes even used for things that are expected to happen during normal control flow (e.g. StopIteration).&lt;/p&gt;
&lt;p&gt;There’s more to say and explain about error handling, and we’ll come back to it in a future TEC. For now, the point is that languages that allow you to completely ignore the possibility of an error occurring are more suitable for scripting, while languages that require you to take possible errors into account lead to more reliable programs.&lt;/p&gt;
&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;So, which language is best for which purpose? Python is obviously good for scripting, and Julia is an interesting alternative that I think may be a better fit for Jisk than Go, seeing as he is interested in calculating things. R seems to work well as a command-line interface for doing statistics but I don’t like it as a programming language (although the Tidyverse is a good development).&lt;/p&gt;
&lt;p&gt;On the programs and libraries side, I’ve built a few slightly bigger systems (in the tens-of-files, thousands-of-lines range) in Python, and it works pretty well, plus you can still put something together very quickly. The downside is that the dynamic typing, lack of encapsulation and lack of exception specifications make it more difficult to make things robust, and performance is also nothing to write home about. Potentially better if slower to work in alternatives would be Java, (modern) C++, and new kid on the block Rust. For now, C++ is my go-to language if I need more performance, even though it’s very complex and by no means perfect.&lt;/p&gt;
&lt;p&gt;What works best for you depends on what you want to do, how much time you have available to learn, a bit on taste, and on external factors like availability of software and of support from the people around you. Many concepts carry over from one language to another though, so don’t worry too much about choosing the wrong one: once you know one programming language, learning others gets a lot easier.&lt;/p&gt;
&lt;p&gt;Well, that concludes the first instalment of The Engineering Corner*. Hope you liked it! Do you write scripts or programs or both? What’s your favourite programming language? Did you like this topic? Was this too basic or too advanced or maybe just right? What would you like to read about next? I’d love to hear about all these things in the comments below. In the mean time:&lt;/p&gt;
&lt;p&gt;Choo choo! Happy Engineering!&lt;/p&gt;
&lt;p&gt;Lourens&lt;/p&gt;
&lt;p&gt;← &amp;#x3C;previous TEC not found&gt; — TEC 1: &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;Better scripts with typing&lt;/a&gt; →&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#2e2f&quot;&gt;[0]&lt;/a&gt; &lt;em&gt;Control flow&lt;/em&gt; refers to the order in which commands are executed, and to branches (if..then) and loops (for.., while..) causing them to be executed not at all, or more than once. In other words, the path through the code taken by the computer’s “cursor” as the code runs.&lt;/p&gt;</content:encoded><author>Lourens Veen</author></item><item><title>Decoding Research Software Impact: A Collaborative Journey</title><link>https://blog2.esciencecenter.nl/posts/2024-07-26---decoding-research-software-impact-a-collaborative-journey</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-07-26---decoding-research-software-impact-a-collaborative-journey</guid><description>&lt;h1 id=&quot;decoding-research-software-impact-a-collaborative-journey&quot;&gt;&lt;strong&gt;Decoding Research Software Impact: A Collaborative Journey&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;on-23-april-2024-the-first-national-research-software-day-took-place-in-hilversum-the-netherlands-during-the-unconference-part-of-the-program-deekshitha-ran-the-session-titled-decoding-research-software-impact-a-collaborative-journey-where-a-model-for-research-software-impact-was-at-the-center-of-the-discussion&quot;&gt;On 23 April 2024, the first ‘&lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day&lt;/a&gt;’ took place in Hilversum, the Netherlands. During the unconference part of the program, &lt;a href=&quot;https://www.linkedin.com/in/deekshitha-m/&quot;&gt;Deekshitha&lt;/a&gt; ran the session titled, ‘Decoding Research Software Impact: A Collaborative Journey’, where a model for research software impact was at the center of the discussion.&lt;/h2&gt;
&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Authors: Deekshitha¹, Carlos Martinez Ortiz¹, Rena Bakhshi¹, Jason Maassen¹, Rob van Nieuwpoort², Slinger Jansen³, Ton Smeele³, Andrew Treloar⁴, Louise Bezuidenhout², Maarten Schermer³, Laurents Sesink⁵, Pui-Kei Fung³, and Colette Bos¹&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-f6a11552.CWh0HtBC_Z2aDNE7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@aleexcif?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Soliman Cifuentes&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this session, participants collaborated on the topic of research software impact. Participants took the perspective of policymakers, funders, researchers and Research Software Engineers (RSEs) to explore perspectives of research software impact in four 15-minute rounds, in which participants attempted to answer a set of questions from the perspective they were exploring. After each round, the participants changed groups to cover a different perspective. This workshop aimed to define the impact of research software from the perspectives of these 4 stakeholders. Here the term impact refers to the difference the research software makes to the research process or community.&lt;/p&gt;
&lt;p&gt;Measuring the impact of research software is the main focus of Deekshitha’s PhD study. Currently, there is a lack of sufficient methods to accurately measure research software impact. Her study seeks to develop an impact model that will enable all stakeholders of research software to measure its impact effectively and ensure recognition for the individuals behind its development. During the sessions, four questions were discussed (from different perspectives):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What are the goals of measuring research software impact?&lt;/li&gt;
&lt;li&gt;How can research software impact be measured?&lt;/li&gt;
&lt;li&gt;Which measures correspond to which goal?&lt;/li&gt;
&lt;li&gt;How should these goals be prioritized?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;researchers-and-research-software-engineers-perspective&quot;&gt;Researchers and Research Software Engineers’ perspective&lt;/h2&gt;
&lt;p&gt;From the researcher’s and RSEs perspective, we have identified six goals, as shown in the Figure 1. Among these, recognition and a track record for funding are essential goals for this group. Despite differing priorities, researchers and RSEs share similar perspectives. Therefore, they are represented together in a single diagram illustrating both viewpoints.&lt;/p&gt;
&lt;p&gt;The figure below illustrates the goals and the factors that help measure their impact and interdependencies. The first branch represents the goals (Answer to question 1), the second connection illustrates how to measure those goals (impact factors and their connection with goals- Answer to questions 2 and 3), and the third branch shows their prioritization value (Answer to question 4) along with the corresponding group (Researchers and RSEs; National and Institutional; no other group identified for Funders). This prioritization resulted from discussions with the workshop participants and the value starts from one. For example, in Figure 1, there are three impact factors grouped under Researchers. Based on the discussion, we found that the impact factor ‘citations’ has higher priority compared to other factors, so it is ranked 1 in the category for Researchers. Grey-colored boxes in front of the impact factors indicate the groups they belong to (eg: Researchers and RSEs). Additionally, impact factors unrelated to the goals (or we couldn’t find a relation with identified goals) are presented in separate black-colored boxes (see Figure 2 and Figure 3).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;349&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-a82b0191.Bq8WrD-D_1ge0nk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: Researchers/RSEs perspective&lt;/p&gt;
&lt;h2 id=&quot;funders-perspective&quot;&gt;Funders perspective&lt;/h2&gt;
&lt;p&gt;Funders like NWO, SURF, and eScience Center who support research software projects, prioritize demonstrating value for money and aligning with international strategic goals like Open Science. By emphasizing research software impact, funders can act as change agents, influencing research and ensuring it aligns with broader institutional objectives. Selecting projects with significant impact enhances the funders’ image and showcases their commitment to supporting valuable and innovative research. Furthermore, funders contribute to research and educational institutions by funding unique and impactful software, thus enhancing their overall value.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;361&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-d9d7efe8.COVBJfrs_NFPpS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: Funders perspective&lt;/p&gt;
&lt;h2 id=&quot;policy-makers-perspective&quot;&gt;Policy makers perspective&lt;/h2&gt;
&lt;p&gt;Policy makers and funders play distinct yet interconnected roles within governance and funding, particularly in research, education, and public policy sectors. Funders focus primarily on providing financial support and resources to achieve specific objectives and outcomes. On the other hand, policy makers are responsible for formulating and implementing regulations, guidelines, and directives that shape the strategic direction and operational frameworks of institutions and organizations.&lt;/p&gt;
&lt;p&gt;In terms of policy making, we realized there should be a distinction between national and international policies to ensure alignment with the institutional mission and purpose, maintain the independence and sovereignty of research institutes, and adequately consider risk assessment, marketability, and valorization. Figure 3 shows goals, impact factors, and their groups with priority values from the policymakers’ perspective.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;312&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-a6d8bab9.FE1foMTn_2kmlyN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: Policy makers perspective&lt;/p&gt;
&lt;h2 id=&quot;take-home-message&quot;&gt;Take home message&lt;/h2&gt;
&lt;p&gt;The collaborative and dynamic nature of the session made it a memorable experience, combining serious discussion with a touch of fun. This approach not only sparked insightful conversations but also strengthened the community’s commitment to advancing the understanding and measurement of research software impact. Additionally, everyone agrees that RSEs are not appropriately recognized for their work, and recognition is one of the main goals for measuring impact. Funders have open science goals to achieve and policymakers want to ensure value for money.&lt;/p&gt;
&lt;p&gt;We look forward to continuing this journey and invite all who are passionate about the transformative power of research software to join us. Together, we can build a robust and internationally recognized model for assessing research software impact. If you’re eager to join this impactful journey, reach out and we can connect over a cup of coffee to further the discussion.&lt;/p&gt;
&lt;p&gt;Credit: We want to credit the tool we used, the free version of EdrawMind, in this blog post.&lt;/p&gt;
&lt;p&gt;Footnotes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.universiteitleiden.nl/en&quot;&gt;Leiden University&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.uu.nl/&quot;&gt;Utrecht University&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ardc.edu.au/&quot;&gt;Australian Research Data Commons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.surf.nl/&quot;&gt;SURF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Fri, 26 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;decoding-research-software-impact-a-collaborative-journey&quot;&gt;&lt;strong&gt;Decoding Research Software Impact: A Collaborative Journey&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;on-23-april-2024-the-first-national-research-software-day-took-place-in-hilversum-the-netherlands-during-the-unconference-part-of-the-program-deekshitha-ran-the-session-titled-decoding-research-software-impact-a-collaborative-journey-where-a-model-for-research-software-impact-was-at-the-center-of-the-discussion&quot;&gt;On 23 April 2024, the first ‘&lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day&lt;/a&gt;’ took place in Hilversum, the Netherlands. During the unconference part of the program, &lt;a href=&quot;https://www.linkedin.com/in/deekshitha-m/&quot;&gt;Deekshitha&lt;/a&gt; ran the session titled, ‘Decoding Research Software Impact: A Collaborative Journey’, where a model for research software impact was at the center of the discussion.&lt;/h2&gt;
&lt;p&gt;3&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Authors: Deekshitha¹, Carlos Martinez Ortiz¹, Rena Bakhshi¹, Jason Maassen¹, Rob van Nieuwpoort², Slinger Jansen³, Ton Smeele³, Andrew Treloar⁴, Louise Bezuidenhout², Maarten Schermer³, Laurents Sesink⁵, Pui-Kei Fung³, and Colette Bos¹&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-f6a11552.CWh0HtBC_Z2aDNE7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@aleexcif?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Soliman Cifuentes&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this session, participants collaborated on the topic of research software impact. Participants took the perspective of policymakers, funders, researchers and Research Software Engineers (RSEs) to explore perspectives of research software impact in four 15-minute rounds, in which participants attempted to answer a set of questions from the perspective they were exploring. After each round, the participants changed groups to cover a different perspective. This workshop aimed to define the impact of research software from the perspectives of these 4 stakeholders. Here the term impact refers to the difference the research software makes to the research process or community.&lt;/p&gt;
&lt;p&gt;Measuring the impact of research software is the main focus of Deekshitha’s PhD study. Currently, there is a lack of sufficient methods to accurately measure research software impact. Her study seeks to develop an impact model that will enable all stakeholders of research software to measure its impact effectively and ensure recognition for the individuals behind its development. During the sessions, four questions were discussed (from different perspectives):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What are the goals of measuring research software impact?&lt;/li&gt;
&lt;li&gt;How can research software impact be measured?&lt;/li&gt;
&lt;li&gt;Which measures correspond to which goal?&lt;/li&gt;
&lt;li&gt;How should these goals be prioritized?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;researchers-and-research-software-engineers-perspective&quot;&gt;Researchers and Research Software Engineers’ perspective&lt;/h2&gt;
&lt;p&gt;From the researcher’s and RSEs perspective, we have identified six goals, as shown in the Figure 1. Among these, recognition and a track record for funding are essential goals for this group. Despite differing priorities, researchers and RSEs share similar perspectives. Therefore, they are represented together in a single diagram illustrating both viewpoints.&lt;/p&gt;
&lt;p&gt;The figure below illustrates the goals and the factors that help measure their impact and interdependencies. The first branch represents the goals (Answer to question 1), the second connection illustrates how to measure those goals (impact factors and their connection with goals- Answer to questions 2 and 3), and the third branch shows their prioritization value (Answer to question 4) along with the corresponding group (Researchers and RSEs; National and Institutional; no other group identified for Funders). This prioritization resulted from discussions with the workshop participants and the value starts from one. For example, in Figure 1, there are three impact factors grouped under Researchers. Based on the discussion, we found that the impact factor ‘citations’ has higher priority compared to other factors, so it is ranked 1 in the category for Researchers. Grey-colored boxes in front of the impact factors indicate the groups they belong to (eg: Researchers and RSEs). Additionally, impact factors unrelated to the goals (or we couldn’t find a relation with identified goals) are presented in separate black-colored boxes (see Figure 2 and Figure 3).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;349&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-a82b0191.Bq8WrD-D_1ge0nk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: Researchers/RSEs perspective&lt;/p&gt;
&lt;h2 id=&quot;funders-perspective&quot;&gt;Funders perspective&lt;/h2&gt;
&lt;p&gt;Funders like NWO, SURF, and eScience Center who support research software projects, prioritize demonstrating value for money and aligning with international strategic goals like Open Science. By emphasizing research software impact, funders can act as change agents, influencing research and ensuring it aligns with broader institutional objectives. Selecting projects with significant impact enhances the funders’ image and showcases their commitment to supporting valuable and innovative research. Furthermore, funders contribute to research and educational institutions by funding unique and impactful software, thus enhancing their overall value.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;361&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-d9d7efe8.COVBJfrs_NFPpS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2: Funders perspective&lt;/p&gt;
&lt;h2 id=&quot;policy-makers-perspective&quot;&gt;Policy makers perspective&lt;/h2&gt;
&lt;p&gt;Policy makers and funders play distinct yet interconnected roles within governance and funding, particularly in research, education, and public policy sectors. Funders focus primarily on providing financial support and resources to achieve specific objectives and outcomes. On the other hand, policy makers are responsible for formulating and implementing regulations, guidelines, and directives that shape the strategic direction and operational frameworks of institutions and organizations.&lt;/p&gt;
&lt;p&gt;In terms of policy making, we realized there should be a distinction between national and international policies to ensure alignment with the institutional mission and purpose, maintain the independence and sovereignty of research institutes, and adequately consider risk assessment, marketability, and valorization. Figure 3 shows goals, impact factors, and their groups with priority values from the policymakers’ perspective.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Decoding Research Software Impact: A Collaborative Journey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;312&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-a6d8bab9.FE1foMTn_2kmlyN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3: Policy makers perspective&lt;/p&gt;
&lt;h2 id=&quot;take-home-message&quot;&gt;Take home message&lt;/h2&gt;
&lt;p&gt;The collaborative and dynamic nature of the session made it a memorable experience, combining serious discussion with a touch of fun. This approach not only sparked insightful conversations but also strengthened the community’s commitment to advancing the understanding and measurement of research software impact. Additionally, everyone agrees that RSEs are not appropriately recognized for their work, and recognition is one of the main goals for measuring impact. Funders have open science goals to achieve and policymakers want to ensure value for money.&lt;/p&gt;
&lt;p&gt;We look forward to continuing this journey and invite all who are passionate about the transformative power of research software to join us. Together, we can build a robust and internationally recognized model for assessing research software impact. If you’re eager to join this impactful journey, reach out and we can connect over a cup of coffee to further the discussion.&lt;/p&gt;
&lt;p&gt;Credit: We want to credit the tool we used, the free version of EdrawMind, in this blog post.&lt;/p&gt;
&lt;p&gt;Footnotes&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.universiteitleiden.nl/en&quot;&gt;Leiden University&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.uu.nl/&quot;&gt;Utrecht University&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ardc.edu.au/&quot;&gt;Australian Research Data Commons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.surf.nl/&quot;&gt;SURF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/decoding-research-software-impact-a-coll-f6a11552.CWh0HtBC.jpg" medium="image"/><author>Deekshitha</author></item><item><title>What Research Software Engineers can learn from Taylor Swift</title><link>https://blog2.esciencecenter.nl/posts/2024-07-18---what-research-software-engineers-can-learn-from-taylor-swift</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-07-18---what-research-software-engineers-can-learn-from-taylor-swift</guid><description>&lt;p&gt;14&lt;/p&gt;
&lt;p&gt;It’s Friday night, 5 July 2024. After some out-of-this-world pizza and a couple of drinks with colleagues, I’m on my way to catching a late train home. I get to the station just in time to park my bike. (I don’t know if it turns into a pumpkin, but the parking closes at midnight so if you’re late, it sleeps outside.)&lt;/p&gt;
&lt;p&gt;It’s crowded in the building. This is Amsterdam Central on a Friday night, so I wasn’t expecting deserted platforms, but tonight it’s packed and somewhat confusingly there are many people dressed in white, with glitters on their faces or even dressed in them completely.&lt;/p&gt;
&lt;p&gt;Then I remember the morning’s news. Taylor Swift concert. Incredibly popular pop singer, researchers studying why. Billionaire. First tour to gross a billion dollars. First concert in The Netherlands in seven years, and sold out way in advance. Fans called Swifties, waiting in line all day in the rain to get a good spot. I’ve never heard a Taylor Swift song.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;What Research Software Engineers can learn from Taylor Swift&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;460&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/what-research-software-engineers-can-lea-5255c30b.Bky7Uy2M_Z1ehXPO.webp&quot; srcset=&quot;&quot;&gt;
Oasis in Montreal, Canada, in 2002. The lyrics to their 1997 song *D’You Know What I Mean describe the singer visiting his childhood home and seeing the Bob Dylan album and a Beatles single that would inspire his music. &lt;em&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Oasis-band-concert-Montreal-Canada-Aug2002.jpg&quot;&gt;&lt;em&gt;Photo by Nesnad&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; on Wikimedia Commons. CC-BY-SA 4.0.*The next morning I decide that I should probably find out what all the fuss is about. You have to keep up with the times after all. I pull up YouTube and type “Taylor Swift”. A song called “&lt;a href=&quot;https://www.youtube.com/watch?v=q3zqJs7JUCQ&quot;&gt;Fortnight&lt;/a&gt;” comes up, apparently her latest single. Featuring someone called Post Malone, which raises the question of why Malone ended, and whether there was a Pre Malone before him, but I digress. I click the link.&lt;/p&gt;
&lt;p&gt;“&lt;a href=&quot;https://youtu.be/aB4OzAEgfD0?t=305&quot;&gt;Goldband!&lt;/a&gt;” my brain goes as the song starts playing. The very first sound is a 1980s-style synthesizer melody that immediately reminds me of this Dutch pop band. They had their Taylor Swift moment for me last year, as I similarly read about their popularity in the news and decided to investigate.&lt;/p&gt;
&lt;p&gt;One of the things I found then was an &lt;a href=&quot;https://www.annavastgoedencultuur.nl/nieuws-1/producerwiegerhoogendorp&quot;&gt;interview&lt;/a&gt; with Goldband’s producer Wieger Hoogendorp that I found very interesting. He explained that the 1980s sounds in their music make it popular because their audience has parents who were teenagers in the 1980s, and they played that stuff to their children. Similar music reminds the now-older kids of those good times, and so this is a recurring cycle in music. People like the familiar.&lt;/p&gt;
&lt;p&gt;I thought about this. As a teenager in the ‘90s, I’d listen to the sound of boy bands emanating from my sister’s room. I liked Father and Son, by Boyzone. It wasn’t until much later that I discovered that it was a cover, the original having been written by Cat Stevens 25 years earlier. My favorite band in the ’90s was Oasis, who was huge and took their inspiration from The Beatles, popular in the ’60s. Maybe there was something to this.&lt;/p&gt;
&lt;p&gt;In the Fortnight video meanwhile, Swift is singing the song while moving from a suspended bed frame to a library where she uses a typewriter. Somehow this feels familiar. She casts a glance at Malone, similarly equipped, and straightens out some papers. At the end of the song, the library scene returns, and all the papers catch fire, and it clicks. It’s another ’80s reference, this time to the clip for Toto’s Africa.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;What Research Software Engineers can learn from Taylor Swift&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/what-research-software-engineers-can-lea-01678a9a.C_wK8G7I_17E4mQ.webp&quot; srcset=&quot;&quot;&gt;
Stills from &lt;a href=&quot;https://www.youtube.com/watch?v=q3zqJs7JUCQ&quot;&gt;Fortnight by Taylor Swift&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=FTQbiNvZqaY&quot;&gt;Africa by Toto&lt;/a&gt;. Note the similarities, which make the clip for Fortnight feel familiar to the viewer, as they’ve likely seen the clip for Africa before. And then nostalgia does the rest. Copyright © 1982 and 2024 by the respective owners.&lt;/p&gt;
&lt;h2 id=&quot;about-that-software&quot;&gt;About that software&lt;/h2&gt;
&lt;p&gt;But Lourens, you may ask, that is all very interesting, but what does it have to do with Research Software Engineering?&lt;/p&gt;
&lt;p&gt;First, please don’t start programming in Fortran ’77 again because it was popular in the 80’s. We have better options now, like Julia or modern Fortran or, well, anything really. Ms. Swift didn’t hire Toto as her backing band either.&lt;/p&gt;
&lt;p&gt;Instead, there are a few aspects of what Taylor Swift does that we can learn from if we want to get more people to use our scientific software.&lt;/p&gt;
&lt;h3 id=&quot;what-users-want&quot;&gt;What users want&lt;/h3&gt;
&lt;p&gt;It may sound incredibly obvious, but we’ve seen above that one of the reasons Ms. Swift is so popular is that she gives people what they want. Note that that’s not the same as what they &lt;em&gt;say&lt;/em&gt; they want. I bet very few Swifties, if you asked them what they wanted to hear in the next song, would say “I’d like it to start with a 1980’s style synthesizer melody reminiscent of Goldband, and then I want her to start singing halfway through the first measure already (another recent innovation in pop music, it reduces the probability that people will skip to the next song right away), and then I want the music video to remind me of Toto’s ‘Africa’.” A much more likely answer would be “I’m so glad you’re here, do you know how I can get this glitter off my face?”&lt;/p&gt;
&lt;p&gt;But Swift and her team are professionals and they know what people actually want. They have all the know-how from decades of experience with pop music, and these days a ton of very detailed data too from streaming services on what people listen to and when and how.&lt;/p&gt;
&lt;h3 id=&quot;making-things-easy&quot;&gt;Making things easy&lt;/h3&gt;
&lt;p&gt;Another thing we can take inspiration from is the dress code. First, there’s apparently a dress code for Ms. Swift’s concerts (probably not a formal one, but enough to fill a train platform with similarly dressed people), which is nice because it means that you don’t have to feel insecure about what to wear to the concert. Nobody likes feeling insecure.&lt;/p&gt;
&lt;p&gt;Second, the dress code is white. Everyone has something white in their closet, so that’s easy. Glitter is easy to come by and cheap, and as an added bonus it reminds you of being a kid again. And then of course the concert is in a place that’s easy to reach for most people, and it ends on time so that you can still easily get home by public transport. In short, going to a Taylor Swift concert is easy! Anyone can do it and feel good doing it, and so more people do.&lt;/p&gt;
&lt;p&gt;The same principle applies to scientific software. Reduce the barrier to entry as much as you can. Make sure it installs (flawlessly!) in at most a single command (and that includes dependencies!). Put that command in the documentation so people can copy-paste and don’t have to type. Ensure there’s an easy-to-follow tutorial, and that it is written from the perspective of the users, which you figured out above. Add a ton of examples on how to do specific things that many people will want to do so that they can copy-paste without having to learn how to operate the software. And set up a chat channel so people can easily ask questions.&lt;/p&gt;
&lt;p&gt;The Toto reference gives us another hint: make your software familiar. Users are going to interact with it in a way that you design, and the more familiar that interaction feels to them, the more usable your software is. So look at other software that is similar, or that your users are likely to be using already, and try to design along similar lines. Clever tricks and highly artistic solutions may be fun to build, and they may make you feel very smart, but they don’t help the user.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;In short: Software exists to make people’s lives easier. Make sure yours does.&lt;/p&gt;
&lt;h3 id=&quot;community&quot;&gt;Community&lt;/h3&gt;
&lt;p&gt;There’s another thing that dress codes or uniforms (or &lt;a href=&quot;https://www.today.com/popculture/music/taylor-swift-eras-tour-friendship-bracelets-rcna99768&quot;&gt;friendship bracelets&lt;/a&gt;) do: they foster a sense of community. Humans are social animals, and we love being part of a group. That’s why we all dress in orange and go to a stadium to cheer on a group of people dressed in the same color, or grow our hair long and wear black and go to a metal concert, or put on suits and go to important meetings. All to be a part of something, to show that we’re part of the group.&lt;/p&gt;
&lt;p&gt;Software is more successful if it has a community around it because it helps people feel like they’re a part of something when they use it. Chat channels, mailing lists, meet-ups, workshops, all these things make it easier for people to start using software and to stay involved. I’ve worked with some software that’s really not very good technically but has an amazing community manager who keeps it alive, nonetheless. Whether that’s a good idea is questionable, but it shows that it works.&lt;/p&gt;
&lt;h3 id=&quot;advertising&quot;&gt;Advertising&lt;/h3&gt;
&lt;p&gt;Collaborations are quite popular in pop music these days. I don’t remember Madonna or Michael Jackson doing a lot of duets when I was a teenager, but it seems that these days every other single features someone or another. The reason of course is simple: it’s good advertising.&lt;/p&gt;
&lt;p&gt;Taylor Swift had a concert, causing a lot of people to gather at a train station, as a result of which I listened to Fortnight, and now I am aware of the existence of Post Malone (and Malone, and Pre Malone, look at that, triple word value!). Moreover, the cloud’s algorithms are now more likely to keep serving me Malones as well, and there’s someone out there whose bottom line is served by that.&lt;/p&gt;
&lt;p&gt;Of course, trying to influence search results using a link farm would be evil, but registering your software in the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt; is good practice, as is archiving it on &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt;, and it works almost as well. Make it easy to use together with related software, and advertise that in that other software’s community. Glue some glitter on your colleague’s faces and send them to the local train station. The point is, if no one knows about your software, no one will use it.&lt;/p&gt;
&lt;h2 id=&quot;impact-is-more-than-numbers&quot;&gt;Impact is more than numbers&lt;/h2&gt;
&lt;p&gt;There’s another reason Taylor Swift is popular, and that is that her music is firmly mainstream. It features recognizable sounds and rhythms, the lyrics are relatable, and so it works for many people. Compare that with my favourite pop artist, &lt;a href=&quot;https://www.youtube.com/watch?v=Tv9YoYCKNoE&quot;&gt;Grimes&lt;/a&gt;, who makes songs about things as nerdy as &lt;a href=&quot;https://www.youtube.com/watch?v=gYG_4vJ4qNA&quot;&gt;Roko’s Basilisk&lt;/a&gt;. As a result, Grimes is not a billionaire. (She used to date one, but that doesn’t count.)&lt;/p&gt;
&lt;p&gt;Research Software Engineers are unlikely to become billionaires either, and sometimes we end up working on specialist software that does something only very few researchers need. It’s hard to have a lot of users then, even though the software could still be very important. On the other hand, something as generic as NumPy has a huge number of users, but then again if NumPy were the only thing we had we’d still not get much science done. (Are NumPy users called NumPies? If not, why not? And how do they get the glitter off their faces after finishing their calculations?)&lt;/p&gt;
&lt;p&gt;So it’s probably a good idea to not give the number of users too much importance when we’re trying to gauge the impact of research software. Do good science with it, make sure that it works for the people doing that science (however many there are), and enjoy the critical acclaim from the users you’ve got and whose lives you made easier. In the end, that’s what it’s all about.&lt;/p&gt;</description><pubDate>Thu, 18 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;14&lt;/p&gt;
&lt;p&gt;It’s Friday night, 5 July 2024. After some out-of-this-world pizza and a couple of drinks with colleagues, I’m on my way to catching a late train home. I get to the station just in time to park my bike. (I don’t know if it turns into a pumpkin, but the parking closes at midnight so if you’re late, it sleeps outside.)&lt;/p&gt;
&lt;p&gt;It’s crowded in the building. This is Amsterdam Central on a Friday night, so I wasn’t expecting deserted platforms, but tonight it’s packed and somewhat confusingly there are many people dressed in white, with glitters on their faces or even dressed in them completely.&lt;/p&gt;
&lt;p&gt;Then I remember the morning’s news. Taylor Swift concert. Incredibly popular pop singer, researchers studying why. Billionaire. First tour to gross a billion dollars. First concert in The Netherlands in seven years, and sold out way in advance. Fans called Swifties, waiting in line all day in the rain to get a good spot. I’ve never heard a Taylor Swift song.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;What Research Software Engineers can learn from Taylor Swift&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;460&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/what-research-software-engineers-can-lea-5255c30b.Bky7Uy2M_Z1ehXPO.webp&quot; srcset=&quot;&quot;&gt;
Oasis in Montreal, Canada, in 2002. The lyrics to their 1997 song *D’You Know What I Mean describe the singer visiting his childhood home and seeing the Bob Dylan album and a Beatles single that would inspire his music. &lt;em&gt;&lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Oasis-band-concert-Montreal-Canada-Aug2002.jpg&quot;&gt;&lt;em&gt;Photo by Nesnad&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; on Wikimedia Commons. CC-BY-SA 4.0.*The next morning I decide that I should probably find out what all the fuss is about. You have to keep up with the times after all. I pull up YouTube and type “Taylor Swift”. A song called “&lt;a href=&quot;https://www.youtube.com/watch?v=q3zqJs7JUCQ&quot;&gt;Fortnight&lt;/a&gt;” comes up, apparently her latest single. Featuring someone called Post Malone, which raises the question of why Malone ended, and whether there was a Pre Malone before him, but I digress. I click the link.&lt;/p&gt;
&lt;p&gt;“&lt;a href=&quot;https://youtu.be/aB4OzAEgfD0?t=305&quot;&gt;Goldband!&lt;/a&gt;” my brain goes as the song starts playing. The very first sound is a 1980s-style synthesizer melody that immediately reminds me of this Dutch pop band. They had their Taylor Swift moment for me last year, as I similarly read about their popularity in the news and decided to investigate.&lt;/p&gt;
&lt;p&gt;One of the things I found then was an &lt;a href=&quot;https://www.annavastgoedencultuur.nl/nieuws-1/producerwiegerhoogendorp&quot;&gt;interview&lt;/a&gt; with Goldband’s producer Wieger Hoogendorp that I found very interesting. He explained that the 1980s sounds in their music make it popular because their audience has parents who were teenagers in the 1980s, and they played that stuff to their children. Similar music reminds the now-older kids of those good times, and so this is a recurring cycle in music. People like the familiar.&lt;/p&gt;
&lt;p&gt;I thought about this. As a teenager in the ‘90s, I’d listen to the sound of boy bands emanating from my sister’s room. I liked Father and Son, by Boyzone. It wasn’t until much later that I discovered that it was a cover, the original having been written by Cat Stevens 25 years earlier. My favorite band in the ’90s was Oasis, who was huge and took their inspiration from The Beatles, popular in the ’60s. Maybe there was something to this.&lt;/p&gt;
&lt;p&gt;In the Fortnight video meanwhile, Swift is singing the song while moving from a suspended bed frame to a library where she uses a typewriter. Somehow this feels familiar. She casts a glance at Malone, similarly equipped, and straightens out some papers. At the end of the song, the library scene returns, and all the papers catch fire, and it clicks. It’s another ’80s reference, this time to the clip for Toto’s Africa.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;What Research Software Engineers can learn from Taylor Swift&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/what-research-software-engineers-can-lea-01678a9a.C_wK8G7I_17E4mQ.webp&quot; srcset=&quot;&quot;&gt;
Stills from &lt;a href=&quot;https://www.youtube.com/watch?v=q3zqJs7JUCQ&quot;&gt;Fortnight by Taylor Swift&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=FTQbiNvZqaY&quot;&gt;Africa by Toto&lt;/a&gt;. Note the similarities, which make the clip for Fortnight feel familiar to the viewer, as they’ve likely seen the clip for Africa before. And then nostalgia does the rest. Copyright © 1982 and 2024 by the respective owners.&lt;/p&gt;
&lt;h2 id=&quot;about-that-software&quot;&gt;About that software&lt;/h2&gt;
&lt;p&gt;But Lourens, you may ask, that is all very interesting, but what does it have to do with Research Software Engineering?&lt;/p&gt;
&lt;p&gt;First, please don’t start programming in Fortran ’77 again because it was popular in the 80’s. We have better options now, like Julia or modern Fortran or, well, anything really. Ms. Swift didn’t hire Toto as her backing band either.&lt;/p&gt;
&lt;p&gt;Instead, there are a few aspects of what Taylor Swift does that we can learn from if we want to get more people to use our scientific software.&lt;/p&gt;
&lt;h3 id=&quot;what-users-want&quot;&gt;What users want&lt;/h3&gt;
&lt;p&gt;It may sound incredibly obvious, but we’ve seen above that one of the reasons Ms. Swift is so popular is that she gives people what they want. Note that that’s not the same as what they &lt;em&gt;say&lt;/em&gt; they want. I bet very few Swifties, if you asked them what they wanted to hear in the next song, would say “I’d like it to start with a 1980’s style synthesizer melody reminiscent of Goldband, and then I want her to start singing halfway through the first measure already (another recent innovation in pop music, it reduces the probability that people will skip to the next song right away), and then I want the music video to remind me of Toto’s ‘Africa’.” A much more likely answer would be “I’m so glad you’re here, do you know how I can get this glitter off my face?”&lt;/p&gt;
&lt;p&gt;But Swift and her team are professionals and they know what people actually want. They have all the know-how from decades of experience with pop music, and these days a ton of very detailed data too from streaming services on what people listen to and when and how.&lt;/p&gt;
&lt;h3 id=&quot;making-things-easy&quot;&gt;Making things easy&lt;/h3&gt;
&lt;p&gt;Another thing we can take inspiration from is the dress code. First, there’s apparently a dress code for Ms. Swift’s concerts (probably not a formal one, but enough to fill a train platform with similarly dressed people), which is nice because it means that you don’t have to feel insecure about what to wear to the concert. Nobody likes feeling insecure.&lt;/p&gt;
&lt;p&gt;Second, the dress code is white. Everyone has something white in their closet, so that’s easy. Glitter is easy to come by and cheap, and as an added bonus it reminds you of being a kid again. And then of course the concert is in a place that’s easy to reach for most people, and it ends on time so that you can still easily get home by public transport. In short, going to a Taylor Swift concert is easy! Anyone can do it and feel good doing it, and so more people do.&lt;/p&gt;
&lt;p&gt;The same principle applies to scientific software. Reduce the barrier to entry as much as you can. Make sure it installs (flawlessly!) in at most a single command (and that includes dependencies!). Put that command in the documentation so people can copy-paste and don’t have to type. Ensure there’s an easy-to-follow tutorial, and that it is written from the perspective of the users, which you figured out above. Add a ton of examples on how to do specific things that many people will want to do so that they can copy-paste without having to learn how to operate the software. And set up a chat channel so people can easily ask questions.&lt;/p&gt;
&lt;p&gt;The Toto reference gives us another hint: make your software familiar. Users are going to interact with it in a way that you design, and the more familiar that interaction feels to them, the more usable your software is. So look at other software that is similar, or that your users are likely to be using already, and try to design along similar lines. Clever tricks and highly artistic solutions may be fun to build, and they may make you feel very smart, but they don’t help the user.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;In short: Software exists to make people’s lives easier. Make sure yours does.&lt;/p&gt;
&lt;h3 id=&quot;community&quot;&gt;Community&lt;/h3&gt;
&lt;p&gt;There’s another thing that dress codes or uniforms (or &lt;a href=&quot;https://www.today.com/popculture/music/taylor-swift-eras-tour-friendship-bracelets-rcna99768&quot;&gt;friendship bracelets&lt;/a&gt;) do: they foster a sense of community. Humans are social animals, and we love being part of a group. That’s why we all dress in orange and go to a stadium to cheer on a group of people dressed in the same color, or grow our hair long and wear black and go to a metal concert, or put on suits and go to important meetings. All to be a part of something, to show that we’re part of the group.&lt;/p&gt;
&lt;p&gt;Software is more successful if it has a community around it because it helps people feel like they’re a part of something when they use it. Chat channels, mailing lists, meet-ups, workshops, all these things make it easier for people to start using software and to stay involved. I’ve worked with some software that’s really not very good technically but has an amazing community manager who keeps it alive, nonetheless. Whether that’s a good idea is questionable, but it shows that it works.&lt;/p&gt;
&lt;h3 id=&quot;advertising&quot;&gt;Advertising&lt;/h3&gt;
&lt;p&gt;Collaborations are quite popular in pop music these days. I don’t remember Madonna or Michael Jackson doing a lot of duets when I was a teenager, but it seems that these days every other single features someone or another. The reason of course is simple: it’s good advertising.&lt;/p&gt;
&lt;p&gt;Taylor Swift had a concert, causing a lot of people to gather at a train station, as a result of which I listened to Fortnight, and now I am aware of the existence of Post Malone (and Malone, and Pre Malone, look at that, triple word value!). Moreover, the cloud’s algorithms are now more likely to keep serving me Malones as well, and there’s someone out there whose bottom line is served by that.&lt;/p&gt;
&lt;p&gt;Of course, trying to influence search results using a link farm would be evil, but registering your software in the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt; is good practice, as is archiving it on &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt;, and it works almost as well. Make it easy to use together with related software, and advertise that in that other software’s community. Glue some glitter on your colleague’s faces and send them to the local train station. The point is, if no one knows about your software, no one will use it.&lt;/p&gt;
&lt;h2 id=&quot;impact-is-more-than-numbers&quot;&gt;Impact is more than numbers&lt;/h2&gt;
&lt;p&gt;There’s another reason Taylor Swift is popular, and that is that her music is firmly mainstream. It features recognizable sounds and rhythms, the lyrics are relatable, and so it works for many people. Compare that with my favourite pop artist, &lt;a href=&quot;https://www.youtube.com/watch?v=Tv9YoYCKNoE&quot;&gt;Grimes&lt;/a&gt;, who makes songs about things as nerdy as &lt;a href=&quot;https://www.youtube.com/watch?v=gYG_4vJ4qNA&quot;&gt;Roko’s Basilisk&lt;/a&gt;. As a result, Grimes is not a billionaire. (She used to date one, but that doesn’t count.)&lt;/p&gt;
&lt;p&gt;Research Software Engineers are unlikely to become billionaires either, and sometimes we end up working on specialist software that does something only very few researchers need. It’s hard to have a lot of users then, even though the software could still be very important. On the other hand, something as generic as NumPy has a huge number of users, but then again if NumPy were the only thing we had we’d still not get much science done. (Are NumPy users called NumPies? If not, why not? And how do they get the glitter off their faces after finishing their calculations?)&lt;/p&gt;
&lt;p&gt;So it’s probably a good idea to not give the number of users too much importance when we’re trying to gauge the impact of research software. Do good science with it, make sure that it works for the people doing that science (however many there are), and enjoy the critical acclaim from the users you’ve got and whose lives you made easier. In the end, that’s what it’s all about.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/what-research-software-engineers-can-lea-5255c30b.Bky7Uy2M.jpg" medium="image"/><author>Lourens Veen</author></item><item><title>Better scripts with typing</title><link>https://blog2.esciencecenter.nl/posts/2024-07-05---better-scripts-with-typing</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-07-05---better-scripts-with-typing</guid><description>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;The Engineering Corner&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A blog-within-a-blog on the transition from writing simple scripts for yourself to writing larger programs with and for others. TEC appears on an irregular schedule driven by workload and inspiration.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;-1-better-scripts-with-typing&quot;&gt;№ 1: Better scripts with typing&lt;/h3&gt;
&lt;p&gt;Imagine that one day you are in the office, and a colleague comes by explaining that their Python script isn’t doing what it’s supposed to. They ask you to help solve the problem. You happily agree. You see they’ve written a function:&lt;/p&gt;
&lt;p&gt;def foo(a, b):
return a + bIs this code correct, or will it give an error if you run it? (&lt;code&gt;foo&lt;/code&gt; is a traditional name for example functions, it doesn’t mean anything.)&lt;/p&gt;
&lt;p&gt;The answer, as often in engineering, is, “It depends”. It depends, in this case, on how the function is called. Something like this will work:&lt;/p&gt;
&lt;p&gt;print(foo(1, 1))On the other hand, this won’t work:&lt;/p&gt;
&lt;p&gt;print(foo([1], 1))So, whether this function is correct or not depends on what you pass into it. It works for two &lt;code&gt;int&lt;/code&gt;s (and for two strings too), but not for a &lt;code&gt;list&lt;/code&gt; and an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So how do you tell whether the problem is in this function? Well, you can simply check the rest of the script, find where the function is called, see what goes into it, and if &lt;code&gt;a+b&lt;/code&gt; works for whatever &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are put in, then the code is correct and the mistake must be somewhere else.&lt;/p&gt;
&lt;p&gt;So far, so good. But what if this is more than just a script? If you have functions calling functions, and functions being called from different places, then figuring out all the different things that can go into the function is going to be quite a bit of detective work. Pretty soon, it’s going to be quite difficult to know whether a function will work or crash. It can even be impossible:&lt;/p&gt;
&lt;p&gt;import json&lt;/p&gt;
&lt;p&gt;with open(‘input.json’) as f:
a = json.load(f)
print(foo(a, 1))Now whether the program works or crashes depends on what’s in some file on the user’s computer! So maybe the script is correct after all, and the problem is elsewhere? This doesn’t make for reliable scripts, or even reproducible science, for that matter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Better scripts with typing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/better-scripts-with-typing-f3cdba31._GLiRtde_ZNYdGP.webp&quot; srcset=&quot;&quot;&gt;
The Philippeion of Olympia (Mark Cartwright — &lt;a href=&quot;https://creativecommons.org/licenses/by-nc-sa/4.0/&quot;&gt;CC BY-NC-SA&lt;/a&gt;)&lt;/p&gt;
&lt;h3 id=&quot;modularity-and-types&quot;&gt;Modularity and types&lt;/h3&gt;
&lt;p&gt;Clearly, we get all kinds of problems when we try to make software that will reliably get the user what they want, especially if the software is large and complex. Fortunately, there’s a good way of dealing with complexity. Invented by legendary RSE &lt;a href=&quot;https://www.worldhistory.org/Philip_II_of_Macedon/&quot;&gt;Philip II of Macedon&lt;/a&gt; some 2300 years ago: Divide et Impera (Divide and Rule). You split up your program into components (functions, procedures, classes, packages, etc.) that you can deal with one by one, then assemble them into a reliably operating empire, I mean program. Let’s look again at that function:&lt;/p&gt;
&lt;p&gt;def foo(a, b):
return a + bIt receives two arguments, &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, from the caller, and returns some value that is the result of the operation &lt;code&gt;a + b&lt;/code&gt;. Receiving arguments and returning a value are the only connections it has to the outside world (such a function is called &lt;em&gt;pure&lt;/em&gt;). But whether the function works correctly depends on the values of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, and therefore on the outside world. That means it’s not a very reliable building block. Philip would be disappointed.&lt;/p&gt;
&lt;p&gt;What if we chose a set of acceptable values for both &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;? Then we could at least reason that if the function does not crash when an acceptable value is passed for both arguments, then the function works correctly. For example, we could specify that &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; both need to be in the set of all integer numbers. Such a collection of possible values is called a type*. Let’s annotate our function with the types we want to receive:&lt;/p&gt;
&lt;p&gt;def foo(a: int, b: int):
return a + bWill this function work correctly? Yes! If you pass it two &lt;code&gt;int&lt;/code&gt; s, it will return their sum and not crash. The above is actually valid Python (the &lt;code&gt;:int&lt;/code&gt; bits are called &lt;em&gt;type annotations&lt;/em&gt;) and it will run just the same as the previous example:&lt;/p&gt;
&lt;p&gt;def foo(a: int, b: int):
return a + b&lt;/p&gt;
&lt;p&gt;def bar():
print(foo(1, 1))&lt;/p&gt;
&lt;p&gt;def baz():
print(foo([1], 1))&lt;/p&gt;
&lt;p&gt;bar()
baz()As you can see, if you run this, the code does exactly the same. There is something funny though. In principle, Python could see when it reads the part &lt;code&gt;foo([1], 1)&lt;/code&gt; that it is not correct. &lt;code&gt;[1]&lt;/code&gt; is a list, and the function &lt;code&gt;foo &lt;/code&gt;needs an int. Nevertheless, Python will happily accept the definition of &lt;code&gt;baz&lt;/code&gt;, and it won’t crash until you actually *run *&lt;code&gt;baz&lt;/code&gt;, in turn calling &lt;code&gt;foo&lt;/code&gt;and trying to add a list and an &lt;code&gt;int&lt;/code&gt;. It’s only then that Python realizes that the values are the wrong type and can no longer add them, so it dutifully generates a &lt;code&gt;TypeError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Better scripts with typing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/better-scripts-with-typing-df0ab36b.CrcPwBMQ_Z2shf4d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@markkoenig?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mark König&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;static-vs-dynamic-typing&quot;&gt;Static vs. Dynamic typing&lt;/h3&gt;
&lt;p&gt;Not all programming languages are like this. The Python language is a so-called &lt;em&gt;dynamically typed&lt;/em&gt; language, which means it won’t check whether things are the right type until it’s running the code and trying to do something with that value. Furthermore, Python completely ignores those type annotations, which explains why it crashes only when it tries to execute &lt;code&gt;a + b&lt;/code&gt; rather than already when executing &lt;code&gt;foo([1], 1)&lt;/code&gt;. Nevertheless, it &lt;em&gt;will&lt;/em&gt; eventually realize that something is wrong at that point and give an error (or it would be an &lt;em&gt;untyped&lt;/em&gt; language, now mercifully extinct), so that we have a chance to find the problem.&lt;/p&gt;
&lt;p&gt;In contrast, languages like C++, Java and Rust are &lt;em&gt;statically typed&lt;/em&gt;, which means that they do the type checking immediately when the code is read before it’s ever started. It’s impossible to create an executable&lt;a href=&quot;#d5ef&quot;&gt;⁰&lt;/a&gt; from this C++ code:&lt;/p&gt;
&lt;p&gt;auto foo(int a, int b) -&gt; int {
return a + b;
}&lt;/p&gt;
&lt;p&gt;auto baz() -&gt; list&amp;#x3C;int&gt; {
return foo(list&amp;#x3C;int&gt;{1}, 1);
}If I try anyway, GCC tells me: &lt;code&gt;error: cannot convert &apos;std::__cxx11::list&amp;#x26;lt;int&amp;#x26;gt;&apos; to &apos;int&apos; for argument &apos;1&apos; to &apos;int foo(int, int)&apos;&lt;/code&gt;, correctly pointing out that &lt;code&gt;foo&lt;/code&gt; needs an int, where I’m trying to pass a list. Note that it’s doing this already at the call, not inside &lt;code&gt;foo&lt;/code&gt;, and since no executable is created, I can’t run the code either.&lt;/p&gt;
&lt;p&gt;Now if we review this code, we can see that the compiler is in fact right. Function &lt;code&gt;foo&lt;/code&gt; is fine, but &lt;code&gt;baz&lt;/code&gt; tries to pass a list as the first argument, and from the definition of &lt;code&gt;foo&lt;/code&gt; we can see that it takes an int, so that’s wrong. In fact, because the return types are also declared, we can see that there is another problem in this version of &lt;code&gt;baz&lt;/code&gt;: &lt;code&gt;foo&lt;/code&gt; returns an int, which &lt;code&gt;baz&lt;/code&gt; then tries to return even though it should return a list. The C++ compiler will give an error for that as well when we fix the first one.&lt;/p&gt;
&lt;p&gt;We didn’t annotate the return type in the Python code before, but you can do that:&lt;/p&gt;
&lt;p&gt;def foo(a: int, b: int) -&gt; int:
return a + b&lt;/p&gt;
&lt;p&gt;def baz() -&gt; None:
print([1], 1)Again, this is not checked by Python, so it will happily return something that doesn’t match the annotation if you tell it to.&lt;/p&gt;
&lt;h3 id=&quot;mypy&quot;&gt;mypy&lt;/h3&gt;
&lt;p&gt;So what good do those annotations do, if Python ignores them? First of all, type annotating your Python code forces you to think about what kinds of values your functions should accept, and then what to do with different kinds of inputs. That helps you write better code. Second, type annotations are really useful for people reading your code, like another developer, a code reviewer or someone using your package. They don’t need to wonder about what to pass to &lt;code&gt;foo&lt;/code&gt; anymore as it’s now obvious: integer numbers! And finally, there are tools that will check your type annotations even if Python doesn’t.&lt;/p&gt;
&lt;p&gt;The oldest and probably most commonly used one of these (and the one that I use) is called &lt;code&gt;mypy&lt;/code&gt;. You can pip-install it, and then call &lt;code&gt;mypy script.py&lt;/code&gt;to check your types, just like &lt;code&gt;flake8&lt;/code&gt; checks your syntax (your IDE may do this for you actually, look it up!). When I give the above to &lt;code&gt;mypy&lt;/code&gt;, it tells me &lt;code&gt;test.py:8 error: Argument to &quot;foo&quot; has incompatible type &quot;List[int]&quot;; expected &quot;int&quot;&lt;/code&gt; and that is exactly what is wrong with my code (and exactly what the C++ compiler said). It points out the right location too! That makes it really easy to fix your code.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Type annotations and mypy make your Python code more modular and make it easier to find mistakes, and that is particularly important when you start making larger programs that you share with others. Your code becomes more predictable and easier to understand when you use it, and that makes for a more reliably good experience for its users and developers. There are some downsides, mostly to do with mypy and type annotations still in development and being bolted on after the fact to a language that wasn’t conceived as a statically typed language from the start, but for scientific software, it works fine and is an excellent idea.&lt;/p&gt;
&lt;p&gt;To summarise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As all good Macedonians know, modularity is good!&lt;/li&gt;
&lt;li&gt;To make functions modular (analyzable in isolation), you need to specify input and output types.&lt;/li&gt;
&lt;li&gt;Strongly typed languages check types on reading the code, dynamically typed ones do it when running.&lt;/li&gt;
&lt;li&gt;With mypy, you can check types in Python too, and find a ton of bugs much quicker than without it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;← &lt;a href=&quot;https://blog2.esciencecenter.nl/scripting-vs-programming-8d7d276f3ba3&quot;&gt;TEC 0: Scripting vs. Programming&lt;/a&gt; — &lt;a href=&quot;https://blog2.esciencecenter.nl/procedural-programming-f1d8cdef7540&quot;&gt;TEC 2: Procedural Programming&lt;/a&gt; →&lt;/p&gt;
&lt;p&gt;[0] C++ is a compiled language. That means that there are two steps to running a C++ program: 1) translating (or &lt;em&gt;compiling&lt;/em&gt;) it from C++ text to machine code for whichever kind of computer you want to run it on, and 2) running the resulting &lt;em&gt;executable&lt;/em&gt;. Type checking happens as part of the first step in C++, not the second.&lt;/p&gt;</description><pubDate>Fri, 05 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;The Engineering Corner&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A blog-within-a-blog on the transition from writing simple scripts for yourself to writing larger programs with and for others. TEC appears on an irregular schedule driven by workload and inspiration.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;-1-better-scripts-with-typing&quot;&gt;№ 1: Better scripts with typing&lt;/h3&gt;
&lt;p&gt;Imagine that one day you are in the office, and a colleague comes by explaining that their Python script isn’t doing what it’s supposed to. They ask you to help solve the problem. You happily agree. You see they’ve written a function:&lt;/p&gt;
&lt;p&gt;def foo(a, b):
return a + bIs this code correct, or will it give an error if you run it? (&lt;code&gt;foo&lt;/code&gt; is a traditional name for example functions, it doesn’t mean anything.)&lt;/p&gt;
&lt;p&gt;The answer, as often in engineering, is, “It depends”. It depends, in this case, on how the function is called. Something like this will work:&lt;/p&gt;
&lt;p&gt;print(foo(1, 1))On the other hand, this won’t work:&lt;/p&gt;
&lt;p&gt;print(foo([1], 1))So, whether this function is correct or not depends on what you pass into it. It works for two &lt;code&gt;int&lt;/code&gt;s (and for two strings too), but not for a &lt;code&gt;list&lt;/code&gt; and an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So how do you tell whether the problem is in this function? Well, you can simply check the rest of the script, find where the function is called, see what goes into it, and if &lt;code&gt;a+b&lt;/code&gt; works for whatever &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are put in, then the code is correct and the mistake must be somewhere else.&lt;/p&gt;
&lt;p&gt;So far, so good. But what if this is more than just a script? If you have functions calling functions, and functions being called from different places, then figuring out all the different things that can go into the function is going to be quite a bit of detective work. Pretty soon, it’s going to be quite difficult to know whether a function will work or crash. It can even be impossible:&lt;/p&gt;
&lt;p&gt;import json&lt;/p&gt;
&lt;p&gt;with open(‘input.json’) as f:
a = json.load(f)
print(foo(a, 1))Now whether the program works or crashes depends on what’s in some file on the user’s computer! So maybe the script is correct after all, and the problem is elsewhere? This doesn’t make for reliable scripts, or even reproducible science, for that matter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Better scripts with typing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/better-scripts-with-typing-f3cdba31._GLiRtde_ZNYdGP.webp&quot; srcset=&quot;&quot;&gt;
The Philippeion of Olympia (Mark Cartwright — &lt;a href=&quot;https://creativecommons.org/licenses/by-nc-sa/4.0/&quot;&gt;CC BY-NC-SA&lt;/a&gt;)&lt;/p&gt;
&lt;h3 id=&quot;modularity-and-types&quot;&gt;Modularity and types&lt;/h3&gt;
&lt;p&gt;Clearly, we get all kinds of problems when we try to make software that will reliably get the user what they want, especially if the software is large and complex. Fortunately, there’s a good way of dealing with complexity. Invented by legendary RSE &lt;a href=&quot;https://www.worldhistory.org/Philip_II_of_Macedon/&quot;&gt;Philip II of Macedon&lt;/a&gt; some 2300 years ago: Divide et Impera (Divide and Rule). You split up your program into components (functions, procedures, classes, packages, etc.) that you can deal with one by one, then assemble them into a reliably operating empire, I mean program. Let’s look again at that function:&lt;/p&gt;
&lt;p&gt;def foo(a, b):
return a + bIt receives two arguments, &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, from the caller, and returns some value that is the result of the operation &lt;code&gt;a + b&lt;/code&gt;. Receiving arguments and returning a value are the only connections it has to the outside world (such a function is called &lt;em&gt;pure&lt;/em&gt;). But whether the function works correctly depends on the values of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, and therefore on the outside world. That means it’s not a very reliable building block. Philip would be disappointed.&lt;/p&gt;
&lt;p&gt;What if we chose a set of acceptable values for both &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;? Then we could at least reason that if the function does not crash when an acceptable value is passed for both arguments, then the function works correctly. For example, we could specify that &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; both need to be in the set of all integer numbers. Such a collection of possible values is called a type*. Let’s annotate our function with the types we want to receive:&lt;/p&gt;
&lt;p&gt;def foo(a: int, b: int):
return a + bWill this function work correctly? Yes! If you pass it two &lt;code&gt;int&lt;/code&gt; s, it will return their sum and not crash. The above is actually valid Python (the &lt;code&gt;:int&lt;/code&gt; bits are called &lt;em&gt;type annotations&lt;/em&gt;) and it will run just the same as the previous example:&lt;/p&gt;
&lt;p&gt;def foo(a: int, b: int):
return a + b&lt;/p&gt;
&lt;p&gt;def bar():
print(foo(1, 1))&lt;/p&gt;
&lt;p&gt;def baz():
print(foo([1], 1))&lt;/p&gt;
&lt;p&gt;bar()
baz()As you can see, if you run this, the code does exactly the same. There is something funny though. In principle, Python could see when it reads the part &lt;code&gt;foo([1], 1)&lt;/code&gt; that it is not correct. &lt;code&gt;[1]&lt;/code&gt; is a list, and the function &lt;code&gt;foo &lt;/code&gt;needs an int. Nevertheless, Python will happily accept the definition of &lt;code&gt;baz&lt;/code&gt;, and it won’t crash until you actually *run *&lt;code&gt;baz&lt;/code&gt;, in turn calling &lt;code&gt;foo&lt;/code&gt;and trying to add a list and an &lt;code&gt;int&lt;/code&gt;. It’s only then that Python realizes that the values are the wrong type and can no longer add them, so it dutifully generates a &lt;code&gt;TypeError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Better scripts with typing&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/better-scripts-with-typing-df0ab36b.CrcPwBMQ_Z2shf4d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@markkoenig?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mark König&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;static-vs-dynamic-typing&quot;&gt;Static vs. Dynamic typing&lt;/h3&gt;
&lt;p&gt;Not all programming languages are like this. The Python language is a so-called &lt;em&gt;dynamically typed&lt;/em&gt; language, which means it won’t check whether things are the right type until it’s running the code and trying to do something with that value. Furthermore, Python completely ignores those type annotations, which explains why it crashes only when it tries to execute &lt;code&gt;a + b&lt;/code&gt; rather than already when executing &lt;code&gt;foo([1], 1)&lt;/code&gt;. Nevertheless, it &lt;em&gt;will&lt;/em&gt; eventually realize that something is wrong at that point and give an error (or it would be an &lt;em&gt;untyped&lt;/em&gt; language, now mercifully extinct), so that we have a chance to find the problem.&lt;/p&gt;
&lt;p&gt;In contrast, languages like C++, Java and Rust are &lt;em&gt;statically typed&lt;/em&gt;, which means that they do the type checking immediately when the code is read before it’s ever started. It’s impossible to create an executable&lt;a href=&quot;#d5ef&quot;&gt;⁰&lt;/a&gt; from this C++ code:&lt;/p&gt;
&lt;p&gt;auto foo(int a, int b) -&gt; int {
return a + b;
}&lt;/p&gt;
&lt;p&gt;auto baz() -&gt; list&amp;#x3C;int&gt; {
return foo(list&amp;#x3C;int&gt;{1}, 1);
}If I try anyway, GCC tells me: &lt;code&gt;error: cannot convert &apos;std::__cxx11::list&amp;#x26;lt;int&amp;#x26;gt;&apos; to &apos;int&apos; for argument &apos;1&apos; to &apos;int foo(int, int)&apos;&lt;/code&gt;, correctly pointing out that &lt;code&gt;foo&lt;/code&gt; needs an int, where I’m trying to pass a list. Note that it’s doing this already at the call, not inside &lt;code&gt;foo&lt;/code&gt;, and since no executable is created, I can’t run the code either.&lt;/p&gt;
&lt;p&gt;Now if we review this code, we can see that the compiler is in fact right. Function &lt;code&gt;foo&lt;/code&gt; is fine, but &lt;code&gt;baz&lt;/code&gt; tries to pass a list as the first argument, and from the definition of &lt;code&gt;foo&lt;/code&gt; we can see that it takes an int, so that’s wrong. In fact, because the return types are also declared, we can see that there is another problem in this version of &lt;code&gt;baz&lt;/code&gt;: &lt;code&gt;foo&lt;/code&gt; returns an int, which &lt;code&gt;baz&lt;/code&gt; then tries to return even though it should return a list. The C++ compiler will give an error for that as well when we fix the first one.&lt;/p&gt;
&lt;p&gt;We didn’t annotate the return type in the Python code before, but you can do that:&lt;/p&gt;
&lt;p&gt;def foo(a: int, b: int) -&gt; int:
return a + b&lt;/p&gt;
&lt;p&gt;def baz() -&gt; None:
print([1], 1)Again, this is not checked by Python, so it will happily return something that doesn’t match the annotation if you tell it to.&lt;/p&gt;
&lt;h3 id=&quot;mypy&quot;&gt;mypy&lt;/h3&gt;
&lt;p&gt;So what good do those annotations do, if Python ignores them? First of all, type annotating your Python code forces you to think about what kinds of values your functions should accept, and then what to do with different kinds of inputs. That helps you write better code. Second, type annotations are really useful for people reading your code, like another developer, a code reviewer or someone using your package. They don’t need to wonder about what to pass to &lt;code&gt;foo&lt;/code&gt; anymore as it’s now obvious: integer numbers! And finally, there are tools that will check your type annotations even if Python doesn’t.&lt;/p&gt;
&lt;p&gt;The oldest and probably most commonly used one of these (and the one that I use) is called &lt;code&gt;mypy&lt;/code&gt;. You can pip-install it, and then call &lt;code&gt;mypy script.py&lt;/code&gt;to check your types, just like &lt;code&gt;flake8&lt;/code&gt; checks your syntax (your IDE may do this for you actually, look it up!). When I give the above to &lt;code&gt;mypy&lt;/code&gt;, it tells me &lt;code&gt;test.py:8 error: Argument to &quot;foo&quot; has incompatible type &quot;List[int]&quot;; expected &quot;int&quot;&lt;/code&gt; and that is exactly what is wrong with my code (and exactly what the C++ compiler said). It points out the right location too! That makes it really easy to fix your code.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Type annotations and mypy make your Python code more modular and make it easier to find mistakes, and that is particularly important when you start making larger programs that you share with others. Your code becomes more predictable and easier to understand when you use it, and that makes for a more reliably good experience for its users and developers. There are some downsides, mostly to do with mypy and type annotations still in development and being bolted on after the fact to a language that wasn’t conceived as a statically typed language from the start, but for scientific software, it works fine and is an excellent idea.&lt;/p&gt;
&lt;p&gt;To summarise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As all good Macedonians know, modularity is good!&lt;/li&gt;
&lt;li&gt;To make functions modular (analyzable in isolation), you need to specify input and output types.&lt;/li&gt;
&lt;li&gt;Strongly typed languages check types on reading the code, dynamically typed ones do it when running.&lt;/li&gt;
&lt;li&gt;With mypy, you can check types in Python too, and find a ton of bugs much quicker than without it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;← &lt;a href=&quot;https://blog2.esciencecenter.nl/scripting-vs-programming-8d7d276f3ba3&quot;&gt;TEC 0: Scripting vs. Programming&lt;/a&gt; — &lt;a href=&quot;https://blog2.esciencecenter.nl/procedural-programming-f1d8cdef7540&quot;&gt;TEC 2: Procedural Programming&lt;/a&gt; →&lt;/p&gt;
&lt;p&gt;[0] C++ is a compiled language. That means that there are two steps to running a C++ program: 1) translating (or &lt;em&gt;compiling&lt;/em&gt;) it from C++ text to machine code for whichever kind of computer you want to run it on, and 2) running the resulting &lt;em&gt;executable&lt;/em&gt;. Type checking happens as part of the first step in C++, not the second.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/better-scripts-with-typing-f3cdba31._GLiRtde.jpg" medium="image"/><author>Lourens Veen</author></item><item><title>Procedural Programming</title><link>https://blog2.esciencecenter.nl/posts/2024-07-05---procedural-programming</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-07-05---procedural-programming</guid><description>&lt;p&gt;The Engineering Corner&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A blog-within-a-blog on the transition from writing simple scripts for yourself to writing larger programs with and for others. TEC appears on an irregular schedule driven by workload and inspiration.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;-2-procedural-programming&quot;&gt;№ 2: Procedural Programming**&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/escience-center/scripting-vs-programming-8d7d276f3ba3&quot;&gt;Previously&lt;/a&gt; we talked about scripting and programming. One difference I mentioned between scripts and programs is that scripts usually consist of a single source file with a straightforward list of instructions, while programs are larger and have a more complex structure. If your script is getting too big to easily read and understand, what are the things you can do?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Procedural Programming&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/procedural-programming-01699b68.DVkCQOGp_Z1ocMer.webp&quot; srcset=&quot;&quot;&gt;
My copy of Pascal User Manual and Report by Jensen &amp;#x26; Wirth (1975).Here’s an example of a Pascal program (a lesser known programming language developed in the 1970s - Ed.), in fact Program 0.1 from &lt;em&gt;Pascal User Manual and Report&lt;/em&gt; (1975) by Kathleen Jensen and &lt;a href=&quot;https://en.wikipedia.org/wiki/Niklaus_Wirth&quot;&gt;Niklaus Wirth&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;program inflation(output);&lt;/p&gt;
&lt;p&gt;const n = 10;
var i : integer; w1,w2,w3 : real;
begin
i := 0; w1 := 1.0; w2 := 1.0; w3 := 1.0
repeat
i := i+ 1;
w1 := w1 * 1.07;
w2 := w2 * 1.08;
w3 := w3 * 1.10;
writeln(i,w1,w2,w3)
until i==n
end.If you are a Python user, you can see this is not that different&lt;a href=&quot;https://medium.com/p/f1d8cdef7540#bf2b&quot;&gt;⁰&lt;/a&gt;. A Pascal program begins by listing all the constants and variables we are going to need, and their types. Then follows a list of statements, which in this case calculate and print a table of inflation-adjustment factors for ten years and three different inflation rates.&lt;/p&gt;
&lt;p&gt;I’ll leave a Python version as an exercise to the reader, but you can see that it will be quite similar (answer below&lt;a href=&quot;#2c46&quot;&gt;¹&lt;/a&gt;, if you want to check your work). In Python, variables are made automatically and don’t have to be declared in advance, but the style of programming is similar. It’s known as &lt;em&gt;imperative programming&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As the Pascal User Manual points out, &lt;em&gt;“A (…) computer program consists of two essential parts, a description of &lt;em&gt;actions&lt;/em&gt; which are to be performed, and a description of the &lt;em&gt;data&lt;/em&gt;, which are manipulated by these actions.”&lt;/em&gt; As your script gets larger and more complicated it will process more data, and it will perform more actions, until it all becomes too much to easily understand. What to do?&lt;/p&gt;
&lt;p&gt;Let’s start with those actions, as that’s what most people like to focus on. In bigger scripts you often see a long list of instructions, and if it’s more than a screenful, that list may be split up into several blocks by comments. A load-data/process/save-data structure is common for example. What’s been done here is that the script has been split up, so that we can deal with it one section at a time (Philip II of Macedon would be proud, see &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;TEC 1&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Can we really deal with the sections independently though? Not entirely, as they still communicate with each other. Each section reads variables written by a previous section, and creates variables for other sections to use. So, if you want to make changes to one section, you still have to take into account the interactions with the others.&lt;/p&gt;
&lt;p&gt;Unless the sections do completely different, independent things, this is inevitable: they have to communicate somehow. It’s tricky though. If you change the name of a variable for example, then you have to search the entire script to see if it’s shared with another section, which you then have to modify accordingly. This could trigger changes somewhere else, and before you know it everything is broken.&lt;/p&gt;
&lt;p&gt;So, we could use a bit of help. In Pascal, this comes in the form of a &lt;em&gt;procedure&lt;/em&gt;. Here’s a slightly modified version of Program 11.3 from the same book as above:&lt;/p&gt;
&lt;p&gt;program parameters(output);&lt;/p&gt;
&lt;p&gt;var a, b, c: integer;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;procedure h(x: integer, var y: integer);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;var z: integer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    x := x + 1;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    y := y + 1;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    z := x + y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    writeln(z)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;begin
a := 0; b := 0; c := 0;
h(a, b);
writeln(a, b)
end.What we have here is a program like before, but the work it does is now split up between the main program and a separate section, which is our procedure. It consists of two parts: a &lt;em&gt;declaration&lt;/em&gt; (the first line) and an &lt;em&gt;implementation&lt;/em&gt; (the rest of the block).&lt;/p&gt;
&lt;p&gt;A procedure is a kind of box around a block of code (a &lt;em&gt;scope&lt;/em&gt;). Variables can not pass through the walls of the box, unless we explicitly pass them through. In the declaration &lt;code&gt;procedure h(x: integer, var y: integer);&lt;/code&gt; we specify explicitly which variables can be passed into the box to communicate between the procedure and the rest of the program: &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; in this example. These are called the procedure’s &lt;em&gt;parameters&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;var&lt;/code&gt; keyword in front of &lt;code&gt;y&lt;/code&gt; says that &lt;code&gt;y&lt;/code&gt; is passed by reference, while the lack of one for &lt;code&gt;x&lt;/code&gt; means that &lt;code&gt;x&lt;/code&gt; is passed by value. What that means is that when we call the procedure with arguments &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, the first parameter &lt;code&gt;x&lt;/code&gt; becomes a &lt;em&gt;copy&lt;/em&gt; of the first argument &lt;code&gt;a&lt;/code&gt; (so that changing &lt;code&gt;x&lt;/code&gt; doesn’t affect &lt;code&gt;a&lt;/code&gt;), while the second parameter &lt;code&gt;y&lt;/code&gt; becomes &lt;em&gt;another name&lt;/em&gt; for the second argument &lt;code&gt;b&lt;/code&gt; (and so changing &lt;code&gt;y&lt;/code&gt; changes &lt;code&gt;b&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;No other variables can enter or exit the box. Variable &lt;code&gt;z&lt;/code&gt;is declared inside the procedure, and it is only visible within the procedure because we haven’t said otherwise.&lt;/p&gt;
&lt;p&gt;{ The main program again }&lt;/p&gt;
&lt;p&gt;begin
a := 0; b := 0; c := 0;
h(a, b);
writeln(a, b)
end.This program has some nice properties. When we call procedure &lt;code&gt;h&lt;/code&gt; in the main program, we can be sure that variable &lt;code&gt;c&lt;/code&gt; will not be changed, without even looking at &lt;code&gt;h&lt;/code&gt;! Then, taking the declaration (the first line with the parameters) of &lt;code&gt;h&lt;/code&gt; into account, we can also tell that &lt;code&gt;a&lt;/code&gt; will probably be read by &lt;code&gt;h&lt;/code&gt; , but won’t be changed, and that &lt;code&gt;b&lt;/code&gt; may end up having a different value after the call. Crucially, we can know all of this without ever reading &lt;code&gt;h&lt;/code&gt;’s implementation.&lt;/p&gt;
&lt;p&gt;{ Procedure h by itself }&lt;/p&gt;
&lt;p&gt;procedure h(x: integer, var y: integer);
var z: integer;
begin
x := x + 1;
y := y + 1;
z := x + y;
writeln(z)
end;Looking at procedure &lt;code&gt;h&lt;/code&gt;, we can tell by looking only at the procedure that any changes we make to it that do not affect what we do to &lt;code&gt;y&lt;/code&gt; will not affect how the rest of the program runs, again &lt;em&gt;without inspecting the rest of the program&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course, if we do make such a change, then we will still have to find all the places in which &lt;code&gt;h&lt;/code&gt; is called and possibly modify them. There is still a dependency! It’s just been made explicit. The same goes if we change the declaration, for example by changing &lt;code&gt;x&lt;/code&gt; to be a &lt;code&gt;real&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;(To clear up the potentially confusing terminology: Pascal has both procedures and functions. Conceptually, a procedure is a list of actions that together enact a desired change (like directions for navigating to a destination), while a function is a list of instructions that produce a result (like how to calculate the length of the hypotenuse of a right triangle).&lt;/p&gt;
&lt;p&gt;Pascal has different language features for procedures and functions, as does Fortran, but more modern programming languages don’t bother with this and just allow you to make a function that returns &lt;code&gt;void&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt;. So, practically speaking, a function in Pascal is the same as a function in Python, and a Pascal procedure is a Python function that doesn’t return a value.&lt;/p&gt;
&lt;p&gt;I’m going to continue to use the term procedure here, because we’re talking about procedural programming, and we can talk about functions later when we talk about functional programming, which is a different beast altogether.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Procedural Programming&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;455&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/procedural-programming-9ac4b700.CbT7Cftq_Z1z8saP.webp&quot; srcset=&quot;&quot;&gt;
Procedures for making a tasty lunch. Photo by &lt;a href=&quot;https://unsplash.com/@socialcut?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;S O C I A L . C U T&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;making-a-good-procedure&quot;&gt;Making a good procedure&lt;/h3&gt;
&lt;p&gt;So, when should you make a procedure, and what does a good procedure look like? One good programming rule to live by is DRY: Don’t Repeat Yourself. So, if you find yourself copy-pasting some code, consider making a procedure instead, and calling it twice.&lt;/p&gt;
&lt;p&gt;Procedures are also fine if they’re only called once though. In the words of Jensen and Wirth: “One should not hesitate, however, from formulating an action as a procedure — even when called only once — if doing so enhances the readability. Defining development steps as procedures makes a more communicable and verifiable program.”* Hear hear!&lt;/p&gt;
&lt;p&gt;As we’ve seen above, the point of procedures is to split up your program into self-contained components, which can be modified independently. On the other hand, these components have to work together, for which they need to exchange information, and that introduces dependencies. There’s no perfect solution to this paradox, but it does lead to some good advice: fewer parameters is better, relative to the length of your procedure.&lt;/p&gt;
&lt;p&gt;If you’re a statistician or a graph theorist, consider a procedure to be a cluster: a good cluster has lots of stuff and connections inside it, but few connections to things outside it. Or if you’ve ever written a text: a procedure is like a paragraph, with some closely related sentences inside it, but connected to the rest of the text only by the things in its topic sentence.&lt;/p&gt;
&lt;p&gt;How about length? Some purveyors of questionable programming advice suggest hard length limits of sometimes as little as five lines per procedure&lt;a href=&quot;#f9c1&quot;&gt;²&lt;/a&gt;. I think the idea behind that is that humans can keep track of five to seven objects (chunks) at a time in short-term memory, so that this allows the reader to keep the whole procedure actively available.&lt;/p&gt;
&lt;p&gt;I don’t think it really works this way though. Blog posts tend to have really short paragraphs for easier reading on screen, but novels don’t and they are still perfectly readable. Grabbing a random one off my bookshelf I count 8 sentences and 163 words in a paragraph, which is three to four times the previous paragraph in this blog and it still reads just fine. So I think that longer procedures are okay, as long as they don’t get so long that you find yourself searching back and forth for something while reading them, or you (or rather someone else who isn’t all that familiar with the code!) have trouble keeping track of what’s going on.&lt;/p&gt;
&lt;p&gt;I also think that short procedures should be avoided. Here’s the above example without procedure &lt;code&gt;h&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;program parameters(output);&lt;/p&gt;
&lt;p&gt;var a, b, c, z: integer;&lt;/p&gt;
&lt;p&gt;begin
a := 0; b := 0; c := 0;
y := y + 1
z := x + 1 + y;
writeln(z);
writeln(x, y);
end.9 lines of code, versus 15 before. And it looks simpler too, doesn’t it? No need to look at the parameter declaration, or to consider which variable belongs where. So maybe procedures aren’t all they’re made out to be?&lt;/p&gt;
&lt;h3 id=&quot;costs-and-benefits&quot;&gt;Costs and benefits&lt;/h3&gt;
&lt;p&gt;Well, no, it’s not that simple. Procedures are an abstraction. Abstractions make it possible to write larger programs with a finite human brain, but they come at a cost of extra overhead. The shorter your procedures, the more of them you’ll need, and the more &lt;em&gt;abstraction overhead&lt;/em&gt; (procedure declarations and calls) you’ll introduce. At some point, that’s actually going to make the code more difficult to read, and it’s up to you, the programmer, to find a happy medium that allows others to easily understand your code.&lt;/p&gt;
&lt;p&gt;I do often find myself writing one-line or few-line procedures, but they’re usually actually abstraction overhead introduced by larger-scale abstractions like classes and modules. Not counting those, my normal range seems to be something like 5 to 20 lines, with an occasional stretch into the thirties or more.&lt;/p&gt;
&lt;p&gt;What matters is not so much the number of lines, but whether everything within the procedure belongs together, and whether the whole thing is still comprehensible. Sometimes splitting up a longer list of instructions that fundamentally belong together will actually make the code harder to read.&lt;/p&gt;
&lt;p&gt;This brings me back to what I said above about the number of parameters relative to the length of the procedure. A good procedure does something that can be described in a few words, all of which are in its name. If you need many words to say &lt;em&gt;what&lt;/em&gt; it does, then you’re trying to cram too much in, and should split it up. If you need many words to say &lt;em&gt;how&lt;/em&gt; it does it, and you find that that recipe naturally breaks up into several blocks, then make separate procedures for each block. If &lt;em&gt;what&lt;/em&gt; it does can be expressed simply, and &lt;em&gt;how&lt;/em&gt; it does it doesn’t split easily, then you have a nice procedure.&lt;/p&gt;
&lt;h3 id=&quot;final-words&quot;&gt;Final words&lt;/h3&gt;
&lt;p&gt;Procedures are a useful way of breaking up all the things your program does into manageable chunks. They impose a hierarchical organisation on the functionality of your program, and hierarchies are powerful means of simplification. (Niklaus Wirth wrote a &lt;a href=&quot;https://dl.acm.org/doi/pdf/10.1145/362575.362577&quot;&gt;famous paper about it&lt;/a&gt;, actually, which is why he and Pascal made an appearance here.) As pointed out by Jensen and Wirth however, there’s another essential part of any computer program: data. We’ll talk more about variables and records, values and objects in future posts.&lt;/p&gt;
&lt;p&gt;← &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;TEC 1: Better scripts with typing&lt;/a&gt; — TEC 3: &amp;#x3C;Stay tuned!&gt; →&lt;/p&gt;
&lt;p&gt;[0] Modern languages don’t seem to have repeat..until loops anymore. I miss them sometimes.&lt;/p&gt;
&lt;p&gt;[1] Here’s a Python version. As you can see, Pascal and Python use different symbols for things, and I’ve used a for-loop because Python doesn’t have repeat..until, but it looks pretty similar.&lt;/p&gt;
&lt;h1 id=&quot;inflation&quot;&gt;inflation&lt;/h1&gt;
&lt;p&gt;N = 10
i = 0; w1 = 1.0; w2 = 1.0; w3 = 1.0
for i in range(1, N+1):
w1 = w1 * 1.07
w2 = w2 * 1.08
w3 = w3 * 1.10
print(i, w1, w2, w3)[2] I’m not naming names here…&lt;/p&gt;</description><pubDate>Fri, 05 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The Engineering Corner&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A blog-within-a-blog on the transition from writing simple scripts for yourself to writing larger programs with and for others. TEC appears on an irregular schedule driven by workload and inspiration.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;-2-procedural-programming&quot;&gt;№ 2: Procedural Programming**&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/escience-center/scripting-vs-programming-8d7d276f3ba3&quot;&gt;Previously&lt;/a&gt; we talked about scripting and programming. One difference I mentioned between scripts and programs is that scripts usually consist of a single source file with a straightforward list of instructions, while programs are larger and have a more complex structure. If your script is getting too big to easily read and understand, what are the things you can do?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Procedural Programming&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/procedural-programming-01699b68.DVkCQOGp_Z1ocMer.webp&quot; srcset=&quot;&quot;&gt;
My copy of Pascal User Manual and Report by Jensen &amp;#x26; Wirth (1975).Here’s an example of a Pascal program (a lesser known programming language developed in the 1970s - Ed.), in fact Program 0.1 from &lt;em&gt;Pascal User Manual and Report&lt;/em&gt; (1975) by Kathleen Jensen and &lt;a href=&quot;https://en.wikipedia.org/wiki/Niklaus_Wirth&quot;&gt;Niklaus Wirth&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;program inflation(output);&lt;/p&gt;
&lt;p&gt;const n = 10;
var i : integer; w1,w2,w3 : real;
begin
i := 0; w1 := 1.0; w2 := 1.0; w3 := 1.0
repeat
i := i+ 1;
w1 := w1 * 1.07;
w2 := w2 * 1.08;
w3 := w3 * 1.10;
writeln(i,w1,w2,w3)
until i==n
end.If you are a Python user, you can see this is not that different&lt;a href=&quot;https://medium.com/p/f1d8cdef7540#bf2b&quot;&gt;⁰&lt;/a&gt;. A Pascal program begins by listing all the constants and variables we are going to need, and their types. Then follows a list of statements, which in this case calculate and print a table of inflation-adjustment factors for ten years and three different inflation rates.&lt;/p&gt;
&lt;p&gt;I’ll leave a Python version as an exercise to the reader, but you can see that it will be quite similar (answer below&lt;a href=&quot;#2c46&quot;&gt;¹&lt;/a&gt;, if you want to check your work). In Python, variables are made automatically and don’t have to be declared in advance, but the style of programming is similar. It’s known as &lt;em&gt;imperative programming&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As the Pascal User Manual points out, &lt;em&gt;“A (…) computer program consists of two essential parts, a description of &lt;em&gt;actions&lt;/em&gt; which are to be performed, and a description of the &lt;em&gt;data&lt;/em&gt;, which are manipulated by these actions.”&lt;/em&gt; As your script gets larger and more complicated it will process more data, and it will perform more actions, until it all becomes too much to easily understand. What to do?&lt;/p&gt;
&lt;p&gt;Let’s start with those actions, as that’s what most people like to focus on. In bigger scripts you often see a long list of instructions, and if it’s more than a screenful, that list may be split up into several blocks by comments. A load-data/process/save-data structure is common for example. What’s been done here is that the script has been split up, so that we can deal with it one section at a time (Philip II of Macedon would be proud, see &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;TEC 1&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Can we really deal with the sections independently though? Not entirely, as they still communicate with each other. Each section reads variables written by a previous section, and creates variables for other sections to use. So, if you want to make changes to one section, you still have to take into account the interactions with the others.&lt;/p&gt;
&lt;p&gt;Unless the sections do completely different, independent things, this is inevitable: they have to communicate somehow. It’s tricky though. If you change the name of a variable for example, then you have to search the entire script to see if it’s shared with another section, which you then have to modify accordingly. This could trigger changes somewhere else, and before you know it everything is broken.&lt;/p&gt;
&lt;p&gt;So, we could use a bit of help. In Pascal, this comes in the form of a &lt;em&gt;procedure&lt;/em&gt;. Here’s a slightly modified version of Program 11.3 from the same book as above:&lt;/p&gt;
&lt;p&gt;program parameters(output);&lt;/p&gt;
&lt;p&gt;var a, b, c: integer;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;procedure h(x: integer, var y: integer);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;var z: integer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    x := x + 1;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    y := y + 1;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    z := x + y;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    writeln(z)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;begin
a := 0; b := 0; c := 0;
h(a, b);
writeln(a, b)
end.What we have here is a program like before, but the work it does is now split up between the main program and a separate section, which is our procedure. It consists of two parts: a &lt;em&gt;declaration&lt;/em&gt; (the first line) and an &lt;em&gt;implementation&lt;/em&gt; (the rest of the block).&lt;/p&gt;
&lt;p&gt;A procedure is a kind of box around a block of code (a &lt;em&gt;scope&lt;/em&gt;). Variables can not pass through the walls of the box, unless we explicitly pass them through. In the declaration &lt;code&gt;procedure h(x: integer, var y: integer);&lt;/code&gt; we specify explicitly which variables can be passed into the box to communicate between the procedure and the rest of the program: &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; in this example. These are called the procedure’s &lt;em&gt;parameters&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;var&lt;/code&gt; keyword in front of &lt;code&gt;y&lt;/code&gt; says that &lt;code&gt;y&lt;/code&gt; is passed by reference, while the lack of one for &lt;code&gt;x&lt;/code&gt; means that &lt;code&gt;x&lt;/code&gt; is passed by value. What that means is that when we call the procedure with arguments &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, the first parameter &lt;code&gt;x&lt;/code&gt; becomes a &lt;em&gt;copy&lt;/em&gt; of the first argument &lt;code&gt;a&lt;/code&gt; (so that changing &lt;code&gt;x&lt;/code&gt; doesn’t affect &lt;code&gt;a&lt;/code&gt;), while the second parameter &lt;code&gt;y&lt;/code&gt; becomes &lt;em&gt;another name&lt;/em&gt; for the second argument &lt;code&gt;b&lt;/code&gt; (and so changing &lt;code&gt;y&lt;/code&gt; changes &lt;code&gt;b&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;No other variables can enter or exit the box. Variable &lt;code&gt;z&lt;/code&gt;is declared inside the procedure, and it is only visible within the procedure because we haven’t said otherwise.&lt;/p&gt;
&lt;p&gt;{ The main program again }&lt;/p&gt;
&lt;p&gt;begin
a := 0; b := 0; c := 0;
h(a, b);
writeln(a, b)
end.This program has some nice properties. When we call procedure &lt;code&gt;h&lt;/code&gt; in the main program, we can be sure that variable &lt;code&gt;c&lt;/code&gt; will not be changed, without even looking at &lt;code&gt;h&lt;/code&gt;! Then, taking the declaration (the first line with the parameters) of &lt;code&gt;h&lt;/code&gt; into account, we can also tell that &lt;code&gt;a&lt;/code&gt; will probably be read by &lt;code&gt;h&lt;/code&gt; , but won’t be changed, and that &lt;code&gt;b&lt;/code&gt; may end up having a different value after the call. Crucially, we can know all of this without ever reading &lt;code&gt;h&lt;/code&gt;’s implementation.&lt;/p&gt;
&lt;p&gt;{ Procedure h by itself }&lt;/p&gt;
&lt;p&gt;procedure h(x: integer, var y: integer);
var z: integer;
begin
x := x + 1;
y := y + 1;
z := x + y;
writeln(z)
end;Looking at procedure &lt;code&gt;h&lt;/code&gt;, we can tell by looking only at the procedure that any changes we make to it that do not affect what we do to &lt;code&gt;y&lt;/code&gt; will not affect how the rest of the program runs, again &lt;em&gt;without inspecting the rest of the program&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course, if we do make such a change, then we will still have to find all the places in which &lt;code&gt;h&lt;/code&gt; is called and possibly modify them. There is still a dependency! It’s just been made explicit. The same goes if we change the declaration, for example by changing &lt;code&gt;x&lt;/code&gt; to be a &lt;code&gt;real&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;(To clear up the potentially confusing terminology: Pascal has both procedures and functions. Conceptually, a procedure is a list of actions that together enact a desired change (like directions for navigating to a destination), while a function is a list of instructions that produce a result (like how to calculate the length of the hypotenuse of a right triangle).&lt;/p&gt;
&lt;p&gt;Pascal has different language features for procedures and functions, as does Fortran, but more modern programming languages don’t bother with this and just allow you to make a function that returns &lt;code&gt;void&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt;. So, practically speaking, a function in Pascal is the same as a function in Python, and a Pascal procedure is a Python function that doesn’t return a value.&lt;/p&gt;
&lt;p&gt;I’m going to continue to use the term procedure here, because we’re talking about procedural programming, and we can talk about functions later when we talk about functional programming, which is a different beast altogether.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Procedural Programming&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;455&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/procedural-programming-9ac4b700.CbT7Cftq_Z1z8saP.webp&quot; srcset=&quot;&quot;&gt;
Procedures for making a tasty lunch. Photo by &lt;a href=&quot;https://unsplash.com/@socialcut?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;S O C I A L . C U T&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;making-a-good-procedure&quot;&gt;Making a good procedure&lt;/h3&gt;
&lt;p&gt;So, when should you make a procedure, and what does a good procedure look like? One good programming rule to live by is DRY: Don’t Repeat Yourself. So, if you find yourself copy-pasting some code, consider making a procedure instead, and calling it twice.&lt;/p&gt;
&lt;p&gt;Procedures are also fine if they’re only called once though. In the words of Jensen and Wirth: “One should not hesitate, however, from formulating an action as a procedure — even when called only once — if doing so enhances the readability. Defining development steps as procedures makes a more communicable and verifiable program.”* Hear hear!&lt;/p&gt;
&lt;p&gt;As we’ve seen above, the point of procedures is to split up your program into self-contained components, which can be modified independently. On the other hand, these components have to work together, for which they need to exchange information, and that introduces dependencies. There’s no perfect solution to this paradox, but it does lead to some good advice: fewer parameters is better, relative to the length of your procedure.&lt;/p&gt;
&lt;p&gt;If you’re a statistician or a graph theorist, consider a procedure to be a cluster: a good cluster has lots of stuff and connections inside it, but few connections to things outside it. Or if you’ve ever written a text: a procedure is like a paragraph, with some closely related sentences inside it, but connected to the rest of the text only by the things in its topic sentence.&lt;/p&gt;
&lt;p&gt;How about length? Some purveyors of questionable programming advice suggest hard length limits of sometimes as little as five lines per procedure&lt;a href=&quot;#f9c1&quot;&gt;²&lt;/a&gt;. I think the idea behind that is that humans can keep track of five to seven objects (chunks) at a time in short-term memory, so that this allows the reader to keep the whole procedure actively available.&lt;/p&gt;
&lt;p&gt;I don’t think it really works this way though. Blog posts tend to have really short paragraphs for easier reading on screen, but novels don’t and they are still perfectly readable. Grabbing a random one off my bookshelf I count 8 sentences and 163 words in a paragraph, which is three to four times the previous paragraph in this blog and it still reads just fine. So I think that longer procedures are okay, as long as they don’t get so long that you find yourself searching back and forth for something while reading them, or you (or rather someone else who isn’t all that familiar with the code!) have trouble keeping track of what’s going on.&lt;/p&gt;
&lt;p&gt;I also think that short procedures should be avoided. Here’s the above example without procedure &lt;code&gt;h&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;program parameters(output);&lt;/p&gt;
&lt;p&gt;var a, b, c, z: integer;&lt;/p&gt;
&lt;p&gt;begin
a := 0; b := 0; c := 0;
y := y + 1
z := x + 1 + y;
writeln(z);
writeln(x, y);
end.9 lines of code, versus 15 before. And it looks simpler too, doesn’t it? No need to look at the parameter declaration, or to consider which variable belongs where. So maybe procedures aren’t all they’re made out to be?&lt;/p&gt;
&lt;h3 id=&quot;costs-and-benefits&quot;&gt;Costs and benefits&lt;/h3&gt;
&lt;p&gt;Well, no, it’s not that simple. Procedures are an abstraction. Abstractions make it possible to write larger programs with a finite human brain, but they come at a cost of extra overhead. The shorter your procedures, the more of them you’ll need, and the more &lt;em&gt;abstraction overhead&lt;/em&gt; (procedure declarations and calls) you’ll introduce. At some point, that’s actually going to make the code more difficult to read, and it’s up to you, the programmer, to find a happy medium that allows others to easily understand your code.&lt;/p&gt;
&lt;p&gt;I do often find myself writing one-line or few-line procedures, but they’re usually actually abstraction overhead introduced by larger-scale abstractions like classes and modules. Not counting those, my normal range seems to be something like 5 to 20 lines, with an occasional stretch into the thirties or more.&lt;/p&gt;
&lt;p&gt;What matters is not so much the number of lines, but whether everything within the procedure belongs together, and whether the whole thing is still comprehensible. Sometimes splitting up a longer list of instructions that fundamentally belong together will actually make the code harder to read.&lt;/p&gt;
&lt;p&gt;This brings me back to what I said above about the number of parameters relative to the length of the procedure. A good procedure does something that can be described in a few words, all of which are in its name. If you need many words to say &lt;em&gt;what&lt;/em&gt; it does, then you’re trying to cram too much in, and should split it up. If you need many words to say &lt;em&gt;how&lt;/em&gt; it does it, and you find that that recipe naturally breaks up into several blocks, then make separate procedures for each block. If &lt;em&gt;what&lt;/em&gt; it does can be expressed simply, and &lt;em&gt;how&lt;/em&gt; it does it doesn’t split easily, then you have a nice procedure.&lt;/p&gt;
&lt;h3 id=&quot;final-words&quot;&gt;Final words&lt;/h3&gt;
&lt;p&gt;Procedures are a useful way of breaking up all the things your program does into manageable chunks. They impose a hierarchical organisation on the functionality of your program, and hierarchies are powerful means of simplification. (Niklaus Wirth wrote a &lt;a href=&quot;https://dl.acm.org/doi/pdf/10.1145/362575.362577&quot;&gt;famous paper about it&lt;/a&gt;, actually, which is why he and Pascal made an appearance here.) As pointed out by Jensen and Wirth however, there’s another essential part of any computer program: data. We’ll talk more about variables and records, values and objects in future posts.&lt;/p&gt;
&lt;p&gt;← &lt;a href=&quot;https://medium.com/escience-center/dynamic-types-static-types-oh-my-py-25c9743b72c4&quot;&gt;TEC 1: Better scripts with typing&lt;/a&gt; — TEC 3: &amp;#x3C;Stay tuned!&gt; →&lt;/p&gt;
&lt;p&gt;[0] Modern languages don’t seem to have repeat..until loops anymore. I miss them sometimes.&lt;/p&gt;
&lt;p&gt;[1] Here’s a Python version. As you can see, Pascal and Python use different symbols for things, and I’ve used a for-loop because Python doesn’t have repeat..until, but it looks pretty similar.&lt;/p&gt;
&lt;h1 id=&quot;inflation&quot;&gt;inflation&lt;/h1&gt;
&lt;p&gt;N = 10
i = 0; w1 = 1.0; w2 = 1.0; w3 = 1.0
for i in range(1, N+1):
w1 = w1 * 1.07
w2 = w2 * 1.08
w3 = w3 * 1.10
print(i, w1, w2, w3)[2] I’m not naming names here…&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/procedural-programming-01699b68.DVkCQOGp.jpeg" medium="image"/><author>Lourens Veen</author></item><item><title>Quantum Computing for Quantum Chemistry with qc2</title><link>https://blog2.esciencecenter.nl/posts/2024-06-27---quantum-computing-for-quantum-chemistry-with-qc2</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-06-27---quantum-computing-for-quantum-chemistry-with-qc2</guid><description>&lt;p&gt;Q&lt;em&gt;uantum Computing is a rapidly evolving field that has the potential to transform the way we approach complex computational problems. Quantum Chemistry stands out as a prime application area, with anticipated impacts ranging from the development of new materials to novel drugs.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this blog, we introduce &lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt;, a user-friendly, modular software designed to seamlessly integrate traditional quantum chemistry codes with modern quantum computing Software Development Kits (SDKs).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;550&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--f78b0228.hCUsNgvR_28XFny.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@lazycreekimages?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Michael Dziedzic&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;
&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;258&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--59e5e045.TUY_z8tQ_pj3CX.webp&quot; srcset=&quot;&quot;&gt;
However, despite recent advances in both hardware and software, the path to fully error-corrected, utility-scale quantum computations may still take a while. For the moment, as we navigate in the &lt;a href=&quot;https://arxiv.org/abs/1801.00862&quot;&gt;Noisy Intermediate-Scale Quantum (NISQ) era&lt;/a&gt; towards &lt;a href=&quot;https://www.ibm.com/quantum/blog/what-is-quantum-utlity&quot;&gt;Quantum Utility&lt;/a&gt;, we need to learn how to make the most out of the available algorithms that run on as-yet error-prone, imperfect hardware: the so-called &lt;a href=&quot;https://arxiv.org/abs/2101.08448&quot;&gt;NISQ algorithms&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unavoidably, &lt;a href=&quot;https://www.ibm.com/topics/quantum-computing&quot;&gt;Quantum Computing&lt;/a&gt; and &lt;a href=&quot;https://onlinelibrary.wiley.com/doi/book/10.1002/9781119019572&quot;&gt;Quantum Chemistry&lt;/a&gt;, and particularly &lt;a href=&quot;https://doi.org/10.48550/arXiv.2001.03685&quot;&gt;their combination&lt;/a&gt;, demand a high level of technical knowledge. The available software packages are highly specialised, requiring users to have an excellent understanding of the fundamental concepts involved from the start. This might scare away both computational chemists and software engineers alike.&lt;/p&gt;
&lt;p&gt;This situation has been greatly alleviated by the increasing availability of excellent &lt;a href=&quot;https://learning.quantum.ibm.com/&quot;&gt;&lt;em&gt;educational resources&lt;/em&gt;**&lt;/a&gt; and &lt;a href=&quot;https://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0208561&quot;&gt;&lt;em&gt;&lt;strong&gt;good quality open-source software&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;, some even tailored specifically for the quantum chemistry community, &lt;em&gt;e.g.&lt;/em&gt;, &lt;a href=&quot;https://qiskit-community.github.io/qiskit-nature/&quot;&gt;Qiskit-Nature&lt;/a&gt;, &lt;a href=&quot;https://docs.pennylane.ai/en/stable/introduction/chemistry.html&quot;&gt;PennyLane.qchem&lt;/a&gt; and &lt;a href=&quot;https://github.com/goodchemistryco/Tangelo&quot;&gt;Tangelo&lt;/a&gt;. And we believe that this is the right way forward.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt;, a user-friendly, modular software designed to seamlessly integrate traditional quantum chemistry codes with modern quantum computing SDKs. Designed with &lt;em&gt;reusability&lt;/em&gt; and &lt;em&gt;interoperability&lt;/em&gt; in mind, qc2 leverages popular existing tools such as the &lt;a href=&quot;https://wiki.fysik.dtu.dk/ase/&quot;&gt;Atomic Simulation Environment (ASE)&lt;/a&gt; and &lt;a href=&quot;https://molssi.org/software/qcschema-2/&quot;&gt;Quantum Chemistry Schema (QCSchema)&lt;/a&gt;. It can also be easily customized to work with your preferred backends, requiring minimal implementation effort.&lt;/p&gt;
&lt;p&gt;Before we dive in, let’s quickly recap some useful concepts…&lt;/p&gt;
&lt;h3 id=&quot;quick-recap-quantum-chemistry-with-classical-computers&quot;&gt;Quick Recap: Quantum Chemistry with Classical Computers&lt;/h3&gt;
&lt;p&gt;The primary goal of quantum chemistry is to understand the structure and properties of matter at microscopic level. Atoms and molecules are intricate quantum entities and are characterized by discrete energy levels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;549&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--b0883893.BEPjHfk4_Z2cfK1D.webp&quot; srcset=&quot;&quot;&gt;
Schematic representation of the discrete electronic energy levels of the water molecule in its most stable configuration.Such a quantized energy spectrum naturally arises from solving the systems’ Schrödinger equation (SE):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;484&quot; height=&quot;88&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--eb730c90.BKSd8jb3_W4Jr4.webp&quot; srcset=&quot;&quot;&gt;
Time-independent Schrödinger equation. H is the Hamiltonian operator (^); |ψ⟩ and E represent the wave function and energy of a quantum state i.This equation represents a typical eigenvalue problem that can only be solved exactly for one-electron systems, &lt;em&gt;e.g.&lt;/em&gt;, the hydrogen atom. For all other systems, we must rely on mathematical and physical models that approximate the exact solutions to the SE. Examples of such models are the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hartree%E2%80%93Fock_method&quot;&gt;Hartree–Fock (HF) method&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Coupled_cluster&quot;&gt;Coupled cluster&lt;/a&gt; (CC) and &lt;a href=&quot;https://en.wikipedia.org/wiki/Full_configuration_interaction&quot;&gt;Full configuration interaction&lt;/a&gt; (FCI).&lt;/p&gt;
&lt;p&gt;In general, the strategy involves expanding the unknown wave function of your system as a linear combination of &lt;em&gt;n&lt;/em&gt; known wave functions:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;41&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--2c0ee02a.BzErDrw7_Z2kDPkl.webp&quot; srcset=&quot;&quot;&gt;
Ground-state molecular wave function as a linear combination of Slater determinants (|φ₁⟩, .., |φₙ⟩) formed from a reference HF wave function, |φ₀⟩. The coefficients α, β, γ, and δ minimize the expectation value of H.Now, the task of determining the coefficients α, β, γ, and δ, along with the associated ground and possibly excited-state energies, involves setting up and diagonalizing a large &lt;em&gt;n&lt;/em&gt; by &lt;em&gt;n&lt;/em&gt; matrix:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;118&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--4d04a3d7.Cd4nYLiW_Z1Ssp1e.webp&quot; srcset=&quot;&quot;&gt;
Diagonalization by a unitary similarity transformation. &lt;strong&gt;U&lt;/strong&gt; is a matrix whose columns are the eigenvectors of H containing α, β, γ, and δ coefficients.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This step is certainly the major computational bottleneck for classical computers and the one that quantum algorithms seek to bypass.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a general rule, the larger &lt;em&gt;n&lt;/em&gt; is, the closer the solution approaches the exact solution to the SE, but the more &lt;a href=&quot;https://arxiv.org/abs/1208.3334&quot;&gt;computationally expensive&lt;/a&gt; it becomes. Not surprisingly, typical “gold-standard” methods like CCSD(T) (let alone FCI) quickly become unaffordable for medium-to-large sized molecules.&lt;/p&gt;
&lt;h3 id=&quot;quantum-chemistry-with-quantum-computers-nisq-algorithms&quot;&gt;Quantum Chemistry with Quantum Computers: NISQ algorithms&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;343&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--29ba8ef0.BpjsK2Fi_Z1KnFUV.webp&quot; srcset=&quot;&quot;&gt;
*Schematic representation of a VQE workflow. &lt;strong&gt;&lt;strong&gt;𝜃&lt;/strong&gt;&lt;/strong&gt; represent circuit parameters that are variationally optimized by an external classical routine. Expectation values of the molecular Hamiltonian 𝐻 are evaluated at circuit level.*Let’s now examine the problem we just discussed from a different perspective: that of Quantum Computing.&lt;/p&gt;
&lt;p&gt;Within the NISQ era, the task of approaching the exact solution to the SE primarily relies on &lt;a href=&quot;https://arxiv.org/abs/2101.08448&quot;&gt;hybrid quantum-classical algorithms&lt;/a&gt;, and there are compelling reasons for this. These algorithms are designed to run on noisy quantum hardware; they utilize as few quantum gates as possible and can be optimized to operate within the limited coherence time of the devices’ qubits, the units of quantum computation. Among these, the &lt;a href=&quot;https://arxiv.org/abs/1812.09976&quot;&gt;Variational Quantum Eigensolver (VQE)&lt;/a&gt; is specially prominent when the goal is to calculate ground-state energies and properties of molecules.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Reference quantum circuit&lt;/em&gt;.** Similar to a typical quantum chemistry calculation, we begin by defining a reference wave function for the target molecule, *|*φ₀⟩. This is usually accomplished by using traditional quantum chemistry packages, &lt;em&gt;e.g.&lt;/em&gt;, by conducting a HF calculation with &lt;a href=&quot;https://pyscf.org/&quot;&gt;PySCF&lt;/a&gt;. From this, a reference quantum circuit can be created by directly mapping the &lt;em&gt;spin-orbitals’ occupation numbers&lt;/em&gt; into initial qubit states (&lt;em&gt;the calculated &lt;em&gt;&lt;a href=&quot;https://arxiv.org/abs/1812.09976&quot;&gt;&lt;em&gt;electron integrals&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; are also useful later for building the molecular Hamiltonian in step 3&lt;/em&gt;). As an example, consider a hydrogen molecule (H₂) with a minimal basis set, such as STO-3G. Here, the final HF wave function |1100⟩ is mapped into a four-qubit quantum circuit |1⟩ ⊗ |1⟩ ⊗ |0⟩ ⊗ |0⟩. For larger molecules or one-electron bases, it may be necessary to restrict the qubit space by creating a reference quantum circuit out of a preselected &lt;em&gt;active space&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Parametrized quantum circuit.&lt;/strong&gt;&lt;/em&gt; After setting the initial qubit states, the next step is to represent the wave function &lt;em&gt;|Ψ&lt;/em&gt;₀⟩ on the quantum device, &lt;em&gt;i.e.&lt;/em&gt;, to prepare a parametrized quantum state. This is achieved by applying a predefined set of quantum gates, which depend on certain parameters &lt;em&gt;&lt;strong&gt;θ&lt;/strong&gt;&lt;/em&gt;, to the initial qubit states. Similarly to &lt;em&gt;|Ψ&lt;/em&gt;₀⟩, the resulting parametrized quantum circuit &lt;em&gt;|Ψ(&lt;strong&gt;&lt;strong&gt;θ&lt;/strong&gt;&lt;/strong&gt;)&lt;/em&gt;⟩, often referred to as the &lt;em&gt;ansatz&lt;/em&gt;, seeks to approximate the true ground-state wave function of the target molecule. The set of variational (qubit rotation) parameters ***θ ***is, in some sense, analogous to the coefficients α, β, γ, and δ discussed earlier in the context of traditional quantum chemistry.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Energy Estimation.&lt;/strong&gt;&lt;/em&gt;* *With the parametrized quantum circuit at hand and a set of initial parameters &lt;strong&gt;&lt;em&gt;θ&lt;/em&gt;ᵢ&lt;/strong&gt;, we estimate the expectation value of the molecular Hamiltonian. This process involves mapping the &lt;a href=&quot;https://arxiv.org/abs/1812.09976&quot;&gt;Hamiltonian in second quantization into a qubit representation&lt;/a&gt;, namely, as a sum of Pauli terms. The final energy, which is given as a sum the measured expectation values of each Pauli term, depends on &lt;strong&gt;&lt;em&gt;θ&lt;/em&gt;ᵢ&lt;/strong&gt; and should be minimized accordingly.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Classical Feedback:&lt;/strong&gt;&lt;/em&gt;* &lt;em&gt;The minimization process is carried out using an external classical optimization routine,&lt;/em&gt; *which updates the circuit parameters &lt;strong&gt;&lt;em&gt;θ&lt;/em&gt;ᵢ.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Steps 3 and 4&lt;/strong&gt; are repeated until convergence is achieved, resulting in the lowest possible expectation value. The final energy corresponds to the ground-state energy of the target molecule as predicted by VQE.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The quality of the VQE solutions depends on several factors, including the size of the active space (if any), type of ansatz, initial guesses for the circuit parameters, the classical optimizer used, and other potential sources of error if run on real quantum hardware.&lt;/p&gt;
&lt;p&gt;Another popular NISQ algorithm for finding the ground-state energy of molecules is the &lt;a href=&quot;https://arxiv.org/abs/2212.02482&quot;&gt;orbital-optimized VQE&lt;/a&gt; (oo-VQE), which extends the traditional VQE. In oo-VQE, not only are the circuit parameters optimized, but the original HF molecular orbitals are also allowed to relax during the classical optimization process. For this reason, ground-state variational energies obtained with oo-VQE are generally lower than those from traditional VQE runs, but they are also computationally more expensive. As will be shown later, VQE and oo-VQE could be seen as some sort of quantum analogues of the traditional &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASCI and CASSCF&lt;/a&gt; &lt;em&gt;ab initio&lt;/em&gt; methods.&lt;/p&gt;
&lt;h3 id=&quot;overview-of-qc2&quot;&gt;Overview of qc2&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--da9ac281.LN0EABsU_Z1DyBEo.webp&quot; srcset=&quot;&quot;&gt;
Schematic representation of qc2 design and workflow.&lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt; is an open-source python package specifically crafted for hybrid quantum-classical algorithms such as VQE and oo-VQE. It embraces several core &lt;em&gt;design principles&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Leveraging Existing Tools&lt;/strong&gt;: qc2 is interoperable with existing open-source quantum chemistry tools, like &lt;a href=&quot;https://wiki.fysik.dtu.dk/ase/&quot;&gt;ASE calculators&lt;/a&gt;, and adheres to standard data schemas, such as &lt;a href=&quot;https://molssi.org/software/qcschema-2/&quot;&gt;QCSchema&lt;/a&gt; or &lt;a href=&quot;https://doi.org/10.1016/0010-4655(89)90033-7&quot;&gt;FCIDump&lt;/a&gt;. This ensures efficient data exchange necessary for various quantum computing libraries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless Integration with Quantum Computing SDKs&lt;/strong&gt;: qc2 is designed to work effortlessly with &lt;a href=&quot;https://www.ibm.com/quantum/qiskit&quot;&gt;Qiskit&lt;/a&gt; and &lt;a href=&quot;https://pennylane.ai/&quot;&gt;PennyLane&lt;/a&gt;, ensuring a smooth user experience for developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modularity&lt;/strong&gt;: The package boasts high modularity, featuring a robust built-in algorithms package that simplifies extensions and enhancements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User-Friendly Design&lt;/strong&gt;: qc2 is straightforward and has an intuitive interface, enabling users to focus on their research and applications with minimal technical details.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the code block below, we present a minimal example using qc2 for a simple VQE run on the water molecule:&lt;/p&gt;
&lt;h1 id=&quot;import-ase-related-modules&quot;&gt;Import ASE-related modules&lt;/h1&gt;
&lt;p&gt;from ase.build import molecule&lt;/p&gt;
&lt;h1 id=&quot;import-qc2-modules&quot;&gt;Import qc2 modules&lt;/h1&gt;
&lt;p&gt;from qc2.data import qc2Data
from qc2.ase import PySCF
from qc2.algorithms.pennylane import VQE
from qc2.algorithms.utils import ActiveSpace&lt;/p&gt;
&lt;h1 id=&quot;instantiate-qc2data-class&quot;&gt;Instantiate qc2Data class&lt;/h1&gt;
&lt;p&gt;qc2data = qc2Data(
molecule=molecule(“H2O”),
filename=“h2o.hdf5”
)&lt;/p&gt;
&lt;h1 id=&quot;specify-and-run-the-quantum-chemistry-qc2-ase-calculator&quot;&gt;Specify and run the quantum chemistry qc2-ASE calculator&lt;/h1&gt;
&lt;p&gt;qc2data.molecule.calc = PySCF(
method=“scf.RHF”,
basis=“sto-3g”,
)
qc2data.run()&lt;/p&gt;
&lt;h1 id=&quot;instantiate-vqe-class&quot;&gt;Instantiate VQE class&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm = VQE(
active_space=ActiveSpace(
num_active_electrons=(2, 2),
num_active_spatial_orbitals=4
),
)&lt;/p&gt;
&lt;h1 id=&quot;run-vqe-algorithm&quot;&gt;Run VQE algorithm&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm.run()As noted, qc2 is designed around the &lt;em&gt;qc2Data&lt;/em&gt; class, which links traditional quantum chemistry codes with quantum computing backends through custom ASE calculators and formatted data files. Here, the molecular structure of water is built from ASE’s G2 database, with the reference HF run with qc2’s custom PySCF ASE calculator. By default, all relevant electronic structure data, including the initial molecular orbitals and electron integrals, are saved in the &lt;em&gt;h2o.hdf5&lt;/em&gt; formatted datafile, following the QCSchema. The information contained in this file is used by *qc2Data *to build the molecular hamiltonian and its qubit representation. Despite being highly customizable, all the details of the VQE workflow discussed in the previous section are abstracted into a &lt;em&gt;VQE&lt;/em&gt; class instance, which, in this case, corresponds to the PennyLane &lt;em&gt;VQE&lt;/em&gt; class from the qc2’s algorithms package. This is passed to the &lt;em&gt;qc2data.algorithm&lt;/em&gt; attribute.&lt;/p&gt;
&lt;p&gt;The next example illustrates how to conduct an oo-VQE run using the Qiskit &lt;em&gt;oo_VQE&lt;/em&gt; class as implemented in the qc2’s algorithms package:&lt;/p&gt;
&lt;h1 id=&quot;import-ase-related-modules-1&quot;&gt;Import ASE-related modules&lt;/h1&gt;
&lt;p&gt;from ase.build import molecule&lt;/p&gt;
&lt;h1 id=&quot;import-qc2-modules-1&quot;&gt;Import qc2 modules&lt;/h1&gt;
&lt;p&gt;from qc2.data import qc2Data
from qc2.ase import PySCF
from qc2.algorithms.qiskit import oo_VQE
from qc2.algorithms.utils import ActiveSpace&lt;/p&gt;
&lt;h1 id=&quot;instantiate-qc2data-class-1&quot;&gt;Instantiate qc2Data class&lt;/h1&gt;
&lt;p&gt;qc2data = qc2Data(
molecule=molecule(“H2O”),
filename=“h2o.hdf5”
)&lt;/p&gt;
&lt;h1 id=&quot;specify-and-run-the-quantum-chemistry-qc2-ase-calculator-1&quot;&gt;Specify and run the quantum chemistry qc2-ASE calculator.&lt;/h1&gt;
&lt;h1 id=&quot;if-you-already-have-h2ohdf5-from-a-previous-run-you-can-skip-this-step&quot;&gt;If you already have “h2o.hdf5” from a previous run, you can skip this step.&lt;/h1&gt;
&lt;p&gt;qc2data.molecule.calc = PySCF(
method=“scf.RHF”,
basis=“sto-3g”,
)
qc2data.run()&lt;/p&gt;
&lt;h1 id=&quot;instantiate-oo_vqe-class&quot;&gt;Instantiate oo_VQE class&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm = oo_VQE(
active_space=ActiveSpace(
num_active_electrons=(2, 2),
num_active_spatial_orbitals=4
),
)&lt;/p&gt;
&lt;h1 id=&quot;run-oo-vqe-algorithm&quot;&gt;Run oo-VQE algorithm&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm.run()The structure of the input is exactly the same as before, with the exception that we are now instantiating and running a different algorithm class. A distinct qc2-ASE calculator could also be used, such as &lt;a href=&quot;https://www.diracprogram.org/&quot;&gt;DIRAC&lt;/a&gt; or &lt;a href=&quot;https://qc2.readthedocs.io/en/latest/ase/building_qc2_ASEs.html&quot;&gt;your own calculator&lt;/a&gt;, with minimal changes and effort. This is a hallmark of qc2. Additionally, since we have previously completed a HF calculation in our VQE example above and saved all relevant &lt;em&gt;ab initio&lt;/em&gt; data in &lt;em&gt;h2o.hdf5&lt;/em&gt;, we could simply skip this step and proceed directly to defining the &lt;em&gt;oo_VQE&lt;/em&gt; class. In this scenario, qc2 will automatically read the data contained in &lt;em&gt;h2o.hdf5&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--764d744f.DX-Vp-Gq_Z1ClJ4p.webp&quot; srcset=&quot;&quot;&gt;
Energy convergence of ground-state water obtained from qc2’s VQE and oo-VQE algorithms. Also shown by dashed lines are the results obtained using traditional quantum chemistry &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASCI&lt;/a&gt;(4, 4)/STO-3G and &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASSCF&lt;/a&gt;(4, 4)/STO-3G methods with PySCF. At iteration #0, both VQE and oo-VQE start at the reference HF energy.The figure shows the energy convergence of ground-state water as obtained using the above qc2 input examples. Although qc2 can be directly interfaced with real quantum backends, for illustration purposes, all quantum circuit evaluations were conducted with the &lt;em&gt;default.qubit&lt;/em&gt; state simulator device for PennyLane and the Qiskit* Estimator primitive* with *StateVector, *both providing exact expectation values. As expected, oo-VQE energies are variationally lower and converge nearly exactly to the predicted &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASSCF&lt;/a&gt; values. Recall, however, that while oo-VQE is computationally more expensive than traditional VQE, this additional burden is entirely placed on the classical computer (optimizers), not the quantum backend. Note further from the figure that, since all initial circuit (and orbital rotation) parameters are set to zero by default, both VQE and oo-VQE initiate their interactive processes at the reference HF energy.&lt;/p&gt;
&lt;h3 id=&quot;whats-next-&quot;&gt;What’s next ?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt; is an ever-evolving open-source project, constantly enriched by new algorithms and features. Looking ahead, we are excited about incorporating even more enhancements. We warmly welcome your &lt;a href=&quot;https://github.com/qc2nl/qc2/blob/main/CONTRIBUTING.md&quot;&gt;contributions&lt;/a&gt;, whether they are new ideas, unique perspectives, or intriguing use cases you would like to see qc2 tackle. Every form of participation is valued — from a quick comment or question to in-depth pull requests. Join us in shaping the future of qc2!&lt;/p&gt;
&lt;p&gt;This article was co-authored with [Nicolas Renaud], with whom I maintained a fruitful collaboration during the &lt;a href=&quot;https://research-software-directory.org/projects/qcforqc&quot;&gt;QCforQC project&lt;/a&gt;, and who generously shared his experiences and knowledge with me.&lt;/p&gt;</description><pubDate>Thu, 27 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Q&lt;em&gt;uantum Computing is a rapidly evolving field that has the potential to transform the way we approach complex computational problems. Quantum Chemistry stands out as a prime application area, with anticipated impacts ranging from the development of new materials to novel drugs.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this blog, we introduce &lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt;, a user-friendly, modular software designed to seamlessly integrate traditional quantum chemistry codes with modern quantum computing Software Development Kits (SDKs).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;550&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--f78b0228.hCUsNgvR_28XFny.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@lazycreekimages?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Michael Dziedzic&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;
&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;258&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--59e5e045.TUY_z8tQ_pj3CX.webp&quot; srcset=&quot;&quot;&gt;
However, despite recent advances in both hardware and software, the path to fully error-corrected, utility-scale quantum computations may still take a while. For the moment, as we navigate in the &lt;a href=&quot;https://arxiv.org/abs/1801.00862&quot;&gt;Noisy Intermediate-Scale Quantum (NISQ) era&lt;/a&gt; towards &lt;a href=&quot;https://www.ibm.com/quantum/blog/what-is-quantum-utlity&quot;&gt;Quantum Utility&lt;/a&gt;, we need to learn how to make the most out of the available algorithms that run on as-yet error-prone, imperfect hardware: the so-called &lt;a href=&quot;https://arxiv.org/abs/2101.08448&quot;&gt;NISQ algorithms&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unavoidably, &lt;a href=&quot;https://www.ibm.com/topics/quantum-computing&quot;&gt;Quantum Computing&lt;/a&gt; and &lt;a href=&quot;https://onlinelibrary.wiley.com/doi/book/10.1002/9781119019572&quot;&gt;Quantum Chemistry&lt;/a&gt;, and particularly &lt;a href=&quot;https://doi.org/10.48550/arXiv.2001.03685&quot;&gt;their combination&lt;/a&gt;, demand a high level of technical knowledge. The available software packages are highly specialised, requiring users to have an excellent understanding of the fundamental concepts involved from the start. This might scare away both computational chemists and software engineers alike.&lt;/p&gt;
&lt;p&gt;This situation has been greatly alleviated by the increasing availability of excellent &lt;a href=&quot;https://learning.quantum.ibm.com/&quot;&gt;&lt;em&gt;educational resources&lt;/em&gt;**&lt;/a&gt; and &lt;a href=&quot;https://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0208561&quot;&gt;&lt;em&gt;&lt;strong&gt;good quality open-source software&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;, some even tailored specifically for the quantum chemistry community, &lt;em&gt;e.g.&lt;/em&gt;, &lt;a href=&quot;https://qiskit-community.github.io/qiskit-nature/&quot;&gt;Qiskit-Nature&lt;/a&gt;, &lt;a href=&quot;https://docs.pennylane.ai/en/stable/introduction/chemistry.html&quot;&gt;PennyLane.qchem&lt;/a&gt; and &lt;a href=&quot;https://github.com/goodchemistryco/Tangelo&quot;&gt;Tangelo&lt;/a&gt;. And we believe that this is the right way forward.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt;, a user-friendly, modular software designed to seamlessly integrate traditional quantum chemistry codes with modern quantum computing SDKs. Designed with &lt;em&gt;reusability&lt;/em&gt; and &lt;em&gt;interoperability&lt;/em&gt; in mind, qc2 leverages popular existing tools such as the &lt;a href=&quot;https://wiki.fysik.dtu.dk/ase/&quot;&gt;Atomic Simulation Environment (ASE)&lt;/a&gt; and &lt;a href=&quot;https://molssi.org/software/qcschema-2/&quot;&gt;Quantum Chemistry Schema (QCSchema)&lt;/a&gt;. It can also be easily customized to work with your preferred backends, requiring minimal implementation effort.&lt;/p&gt;
&lt;p&gt;Before we dive in, let’s quickly recap some useful concepts…&lt;/p&gt;
&lt;h3 id=&quot;quick-recap-quantum-chemistry-with-classical-computers&quot;&gt;Quick Recap: Quantum Chemistry with Classical Computers&lt;/h3&gt;
&lt;p&gt;The primary goal of quantum chemistry is to understand the structure and properties of matter at microscopic level. Atoms and molecules are intricate quantum entities and are characterized by discrete energy levels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;549&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--b0883893.BEPjHfk4_Z2cfK1D.webp&quot; srcset=&quot;&quot;&gt;
Schematic representation of the discrete electronic energy levels of the water molecule in its most stable configuration.Such a quantized energy spectrum naturally arises from solving the systems’ Schrödinger equation (SE):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;484&quot; height=&quot;88&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--eb730c90.BKSd8jb3_W4Jr4.webp&quot; srcset=&quot;&quot;&gt;
Time-independent Schrödinger equation. H is the Hamiltonian operator (^); |ψ⟩ and E represent the wave function and energy of a quantum state i.This equation represents a typical eigenvalue problem that can only be solved exactly for one-electron systems, &lt;em&gt;e.g.&lt;/em&gt;, the hydrogen atom. For all other systems, we must rely on mathematical and physical models that approximate the exact solutions to the SE. Examples of such models are the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hartree%E2%80%93Fock_method&quot;&gt;Hartree–Fock (HF) method&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Coupled_cluster&quot;&gt;Coupled cluster&lt;/a&gt; (CC) and &lt;a href=&quot;https://en.wikipedia.org/wiki/Full_configuration_interaction&quot;&gt;Full configuration interaction&lt;/a&gt; (FCI).&lt;/p&gt;
&lt;p&gt;In general, the strategy involves expanding the unknown wave function of your system as a linear combination of &lt;em&gt;n&lt;/em&gt; known wave functions:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;41&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--2c0ee02a.BzErDrw7_Z2kDPkl.webp&quot; srcset=&quot;&quot;&gt;
Ground-state molecular wave function as a linear combination of Slater determinants (|φ₁⟩, .., |φₙ⟩) formed from a reference HF wave function, |φ₀⟩. The coefficients α, β, γ, and δ minimize the expectation value of H.Now, the task of determining the coefficients α, β, γ, and δ, along with the associated ground and possibly excited-state energies, involves setting up and diagonalizing a large &lt;em&gt;n&lt;/em&gt; by &lt;em&gt;n&lt;/em&gt; matrix:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;118&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--4d04a3d7.Cd4nYLiW_Z1Ssp1e.webp&quot; srcset=&quot;&quot;&gt;
Diagonalization by a unitary similarity transformation. &lt;strong&gt;U&lt;/strong&gt; is a matrix whose columns are the eigenvectors of H containing α, β, γ, and δ coefficients.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This step is certainly the major computational bottleneck for classical computers and the one that quantum algorithms seek to bypass.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a general rule, the larger &lt;em&gt;n&lt;/em&gt; is, the closer the solution approaches the exact solution to the SE, but the more &lt;a href=&quot;https://arxiv.org/abs/1208.3334&quot;&gt;computationally expensive&lt;/a&gt; it becomes. Not surprisingly, typical “gold-standard” methods like CCSD(T) (let alone FCI) quickly become unaffordable for medium-to-large sized molecules.&lt;/p&gt;
&lt;h3 id=&quot;quantum-chemistry-with-quantum-computers-nisq-algorithms&quot;&gt;Quantum Chemistry with Quantum Computers: NISQ algorithms&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;343&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--29ba8ef0.BpjsK2Fi_Z1KnFUV.webp&quot; srcset=&quot;&quot;&gt;
*Schematic representation of a VQE workflow. &lt;strong&gt;&lt;strong&gt;𝜃&lt;/strong&gt;&lt;/strong&gt; represent circuit parameters that are variationally optimized by an external classical routine. Expectation values of the molecular Hamiltonian 𝐻 are evaluated at circuit level.*Let’s now examine the problem we just discussed from a different perspective: that of Quantum Computing.&lt;/p&gt;
&lt;p&gt;Within the NISQ era, the task of approaching the exact solution to the SE primarily relies on &lt;a href=&quot;https://arxiv.org/abs/2101.08448&quot;&gt;hybrid quantum-classical algorithms&lt;/a&gt;, and there are compelling reasons for this. These algorithms are designed to run on noisy quantum hardware; they utilize as few quantum gates as possible and can be optimized to operate within the limited coherence time of the devices’ qubits, the units of quantum computation. Among these, the &lt;a href=&quot;https://arxiv.org/abs/1812.09976&quot;&gt;Variational Quantum Eigensolver (VQE)&lt;/a&gt; is specially prominent when the goal is to calculate ground-state energies and properties of molecules.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Reference quantum circuit&lt;/em&gt;.** Similar to a typical quantum chemistry calculation, we begin by defining a reference wave function for the target molecule, *|*φ₀⟩. This is usually accomplished by using traditional quantum chemistry packages, &lt;em&gt;e.g.&lt;/em&gt;, by conducting a HF calculation with &lt;a href=&quot;https://pyscf.org/&quot;&gt;PySCF&lt;/a&gt;. From this, a reference quantum circuit can be created by directly mapping the &lt;em&gt;spin-orbitals’ occupation numbers&lt;/em&gt; into initial qubit states (&lt;em&gt;the calculated &lt;em&gt;&lt;a href=&quot;https://arxiv.org/abs/1812.09976&quot;&gt;&lt;em&gt;electron integrals&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; are also useful later for building the molecular Hamiltonian in step 3&lt;/em&gt;). As an example, consider a hydrogen molecule (H₂) with a minimal basis set, such as STO-3G. Here, the final HF wave function |1100⟩ is mapped into a four-qubit quantum circuit |1⟩ ⊗ |1⟩ ⊗ |0⟩ ⊗ |0⟩. For larger molecules or one-electron bases, it may be necessary to restrict the qubit space by creating a reference quantum circuit out of a preselected &lt;em&gt;active space&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Parametrized quantum circuit.&lt;/strong&gt;&lt;/em&gt; After setting the initial qubit states, the next step is to represent the wave function &lt;em&gt;|Ψ&lt;/em&gt;₀⟩ on the quantum device, &lt;em&gt;i.e.&lt;/em&gt;, to prepare a parametrized quantum state. This is achieved by applying a predefined set of quantum gates, which depend on certain parameters &lt;em&gt;&lt;strong&gt;θ&lt;/strong&gt;&lt;/em&gt;, to the initial qubit states. Similarly to &lt;em&gt;|Ψ&lt;/em&gt;₀⟩, the resulting parametrized quantum circuit &lt;em&gt;|Ψ(&lt;strong&gt;&lt;strong&gt;θ&lt;/strong&gt;&lt;/strong&gt;)&lt;/em&gt;⟩, often referred to as the &lt;em&gt;ansatz&lt;/em&gt;, seeks to approximate the true ground-state wave function of the target molecule. The set of variational (qubit rotation) parameters ***θ ***is, in some sense, analogous to the coefficients α, β, γ, and δ discussed earlier in the context of traditional quantum chemistry.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Energy Estimation.&lt;/strong&gt;&lt;/em&gt;* *With the parametrized quantum circuit at hand and a set of initial parameters &lt;strong&gt;&lt;em&gt;θ&lt;/em&gt;ᵢ&lt;/strong&gt;, we estimate the expectation value of the molecular Hamiltonian. This process involves mapping the &lt;a href=&quot;https://arxiv.org/abs/1812.09976&quot;&gt;Hamiltonian in second quantization into a qubit representation&lt;/a&gt;, namely, as a sum of Pauli terms. The final energy, which is given as a sum the measured expectation values of each Pauli term, depends on &lt;strong&gt;&lt;em&gt;θ&lt;/em&gt;ᵢ&lt;/strong&gt; and should be minimized accordingly.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Classical Feedback:&lt;/strong&gt;&lt;/em&gt;* &lt;em&gt;The minimization process is carried out using an external classical optimization routine,&lt;/em&gt; *which updates the circuit parameters &lt;strong&gt;&lt;em&gt;θ&lt;/em&gt;ᵢ.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Steps 3 and 4&lt;/strong&gt; are repeated until convergence is achieved, resulting in the lowest possible expectation value. The final energy corresponds to the ground-state energy of the target molecule as predicted by VQE.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The quality of the VQE solutions depends on several factors, including the size of the active space (if any), type of ansatz, initial guesses for the circuit parameters, the classical optimizer used, and other potential sources of error if run on real quantum hardware.&lt;/p&gt;
&lt;p&gt;Another popular NISQ algorithm for finding the ground-state energy of molecules is the &lt;a href=&quot;https://arxiv.org/abs/2212.02482&quot;&gt;orbital-optimized VQE&lt;/a&gt; (oo-VQE), which extends the traditional VQE. In oo-VQE, not only are the circuit parameters optimized, but the original HF molecular orbitals are also allowed to relax during the classical optimization process. For this reason, ground-state variational energies obtained with oo-VQE are generally lower than those from traditional VQE runs, but they are also computationally more expensive. As will be shown later, VQE and oo-VQE could be seen as some sort of quantum analogues of the traditional &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASCI and CASSCF&lt;/a&gt; &lt;em&gt;ab initio&lt;/em&gt; methods.&lt;/p&gt;
&lt;h3 id=&quot;overview-of-qc2&quot;&gt;Overview of qc2&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--da9ac281.LN0EABsU_Z1DyBEo.webp&quot; srcset=&quot;&quot;&gt;
Schematic representation of qc2 design and workflow.&lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt; is an open-source python package specifically crafted for hybrid quantum-classical algorithms such as VQE and oo-VQE. It embraces several core &lt;em&gt;design principles&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Leveraging Existing Tools&lt;/strong&gt;: qc2 is interoperable with existing open-source quantum chemistry tools, like &lt;a href=&quot;https://wiki.fysik.dtu.dk/ase/&quot;&gt;ASE calculators&lt;/a&gt;, and adheres to standard data schemas, such as &lt;a href=&quot;https://molssi.org/software/qcschema-2/&quot;&gt;QCSchema&lt;/a&gt; or &lt;a href=&quot;https://doi.org/10.1016/0010-4655(89)90033-7&quot;&gt;FCIDump&lt;/a&gt;. This ensures efficient data exchange necessary for various quantum computing libraries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless Integration with Quantum Computing SDKs&lt;/strong&gt;: qc2 is designed to work effortlessly with &lt;a href=&quot;https://www.ibm.com/quantum/qiskit&quot;&gt;Qiskit&lt;/a&gt; and &lt;a href=&quot;https://pennylane.ai/&quot;&gt;PennyLane&lt;/a&gt;, ensuring a smooth user experience for developers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modularity&lt;/strong&gt;: The package boasts high modularity, featuring a robust built-in algorithms package that simplifies extensions and enhancements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User-Friendly Design&lt;/strong&gt;: qc2 is straightforward and has an intuitive interface, enabling users to focus on their research and applications with minimal technical details.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the code block below, we present a minimal example using qc2 for a simple VQE run on the water molecule:&lt;/p&gt;
&lt;h1 id=&quot;import-ase-related-modules&quot;&gt;Import ASE-related modules&lt;/h1&gt;
&lt;p&gt;from ase.build import molecule&lt;/p&gt;
&lt;h1 id=&quot;import-qc2-modules&quot;&gt;Import qc2 modules&lt;/h1&gt;
&lt;p&gt;from qc2.data import qc2Data
from qc2.ase import PySCF
from qc2.algorithms.pennylane import VQE
from qc2.algorithms.utils import ActiveSpace&lt;/p&gt;
&lt;h1 id=&quot;instantiate-qc2data-class&quot;&gt;Instantiate qc2Data class&lt;/h1&gt;
&lt;p&gt;qc2data = qc2Data(
molecule=molecule(“H2O”),
filename=“h2o.hdf5”
)&lt;/p&gt;
&lt;h1 id=&quot;specify-and-run-the-quantum-chemistry-qc2-ase-calculator&quot;&gt;Specify and run the quantum chemistry qc2-ASE calculator&lt;/h1&gt;
&lt;p&gt;qc2data.molecule.calc = PySCF(
method=“scf.RHF”,
basis=“sto-3g”,
)
qc2data.run()&lt;/p&gt;
&lt;h1 id=&quot;instantiate-vqe-class&quot;&gt;Instantiate VQE class&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm = VQE(
active_space=ActiveSpace(
num_active_electrons=(2, 2),
num_active_spatial_orbitals=4
),
)&lt;/p&gt;
&lt;h1 id=&quot;run-vqe-algorithm&quot;&gt;Run VQE algorithm&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm.run()As noted, qc2 is designed around the &lt;em&gt;qc2Data&lt;/em&gt; class, which links traditional quantum chemistry codes with quantum computing backends through custom ASE calculators and formatted data files. Here, the molecular structure of water is built from ASE’s G2 database, with the reference HF run with qc2’s custom PySCF ASE calculator. By default, all relevant electronic structure data, including the initial molecular orbitals and electron integrals, are saved in the &lt;em&gt;h2o.hdf5&lt;/em&gt; formatted datafile, following the QCSchema. The information contained in this file is used by *qc2Data *to build the molecular hamiltonian and its qubit representation. Despite being highly customizable, all the details of the VQE workflow discussed in the previous section are abstracted into a &lt;em&gt;VQE&lt;/em&gt; class instance, which, in this case, corresponds to the PennyLane &lt;em&gt;VQE&lt;/em&gt; class from the qc2’s algorithms package. This is passed to the &lt;em&gt;qc2data.algorithm&lt;/em&gt; attribute.&lt;/p&gt;
&lt;p&gt;The next example illustrates how to conduct an oo-VQE run using the Qiskit &lt;em&gt;oo_VQE&lt;/em&gt; class as implemented in the qc2’s algorithms package:&lt;/p&gt;
&lt;h1 id=&quot;import-ase-related-modules-1&quot;&gt;Import ASE-related modules&lt;/h1&gt;
&lt;p&gt;from ase.build import molecule&lt;/p&gt;
&lt;h1 id=&quot;import-qc2-modules-1&quot;&gt;Import qc2 modules&lt;/h1&gt;
&lt;p&gt;from qc2.data import qc2Data
from qc2.ase import PySCF
from qc2.algorithms.qiskit import oo_VQE
from qc2.algorithms.utils import ActiveSpace&lt;/p&gt;
&lt;h1 id=&quot;instantiate-qc2data-class-1&quot;&gt;Instantiate qc2Data class&lt;/h1&gt;
&lt;p&gt;qc2data = qc2Data(
molecule=molecule(“H2O”),
filename=“h2o.hdf5”
)&lt;/p&gt;
&lt;h1 id=&quot;specify-and-run-the-quantum-chemistry-qc2-ase-calculator-1&quot;&gt;Specify and run the quantum chemistry qc2-ASE calculator.&lt;/h1&gt;
&lt;h1 id=&quot;if-you-already-have-h2ohdf5-from-a-previous-run-you-can-skip-this-step&quot;&gt;If you already have “h2o.hdf5” from a previous run, you can skip this step.&lt;/h1&gt;
&lt;p&gt;qc2data.molecule.calc = PySCF(
method=“scf.RHF”,
basis=“sto-3g”,
)
qc2data.run()&lt;/p&gt;
&lt;h1 id=&quot;instantiate-oo_vqe-class&quot;&gt;Instantiate oo_VQE class&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm = oo_VQE(
active_space=ActiveSpace(
num_active_electrons=(2, 2),
num_active_spatial_orbitals=4
),
)&lt;/p&gt;
&lt;h1 id=&quot;run-oo-vqe-algorithm&quot;&gt;Run oo-VQE algorithm&lt;/h1&gt;
&lt;p&gt;qc2data.algorithm.run()The structure of the input is exactly the same as before, with the exception that we are now instantiating and running a different algorithm class. A distinct qc2-ASE calculator could also be used, such as &lt;a href=&quot;https://www.diracprogram.org/&quot;&gt;DIRAC&lt;/a&gt; or &lt;a href=&quot;https://qc2.readthedocs.io/en/latest/ase/building_qc2_ASEs.html&quot;&gt;your own calculator&lt;/a&gt;, with minimal changes and effort. This is a hallmark of qc2. Additionally, since we have previously completed a HF calculation in our VQE example above and saved all relevant &lt;em&gt;ab initio&lt;/em&gt; data in &lt;em&gt;h2o.hdf5&lt;/em&gt;, we could simply skip this step and proceed directly to defining the &lt;em&gt;oo_VQE&lt;/em&gt; class. In this scenario, qc2 will automatically read the data contained in &lt;em&gt;h2o.hdf5&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Quantum Computing for Quantum Chemistry with qc2&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--764d744f.DX-Vp-Gq_Z1ClJ4p.webp&quot; srcset=&quot;&quot;&gt;
Energy convergence of ground-state water obtained from qc2’s VQE and oo-VQE algorithms. Also shown by dashed lines are the results obtained using traditional quantum chemistry &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASCI&lt;/a&gt;(4, 4)/STO-3G and &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASSCF&lt;/a&gt;(4, 4)/STO-3G methods with PySCF. At iteration #0, both VQE and oo-VQE start at the reference HF energy.The figure shows the energy convergence of ground-state water as obtained using the above qc2 input examples. Although qc2 can be directly interfaced with real quantum backends, for illustration purposes, all quantum circuit evaluations were conducted with the &lt;em&gt;default.qubit&lt;/em&gt; state simulator device for PennyLane and the Qiskit* Estimator primitive* with *StateVector, *both providing exact expectation values. As expected, oo-VQE energies are variationally lower and converge nearly exactly to the predicted &lt;a href=&quot;https://pyscf.org/user/mcscf.html&quot;&gt;CASSCF&lt;/a&gt; values. Recall, however, that while oo-VQE is computationally more expensive than traditional VQE, this additional burden is entirely placed on the classical computer (optimizers), not the quantum backend. Note further from the figure that, since all initial circuit (and orbital rotation) parameters are set to zero by default, both VQE and oo-VQE initiate their interactive processes at the reference HF energy.&lt;/p&gt;
&lt;h3 id=&quot;whats-next-&quot;&gt;What’s next ?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/qc2nl/qc2&quot;&gt;qc2&lt;/a&gt; is an ever-evolving open-source project, constantly enriched by new algorithms and features. Looking ahead, we are excited about incorporating even more enhancements. We warmly welcome your &lt;a href=&quot;https://github.com/qc2nl/qc2/blob/main/CONTRIBUTING.md&quot;&gt;contributions&lt;/a&gt;, whether they are new ideas, unique perspectives, or intriguing use cases you would like to see qc2 tackle. Every form of participation is valued — from a quick comment or question to in-depth pull requests. Join us in shaping the future of qc2!&lt;/p&gt;
&lt;p&gt;This article was co-authored with [Nicolas Renaud], with whom I maintained a fruitful collaboration during the &lt;a href=&quot;https://research-software-directory.org/projects/qcforqc&quot;&gt;QCforQC project&lt;/a&gt;, and who generously shared his experiences and knowledge with me.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/quantum-computing-for-quantum-chemistry--f78b0228.hCUsNgvR.jpg" medium="image"/><author>Carlosmurilorocha</author></item><item><title>Transparency in research... and football</title><link>https://blog2.esciencecenter.nl/posts/2024-06-27---transparency-in-research-and-football</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-06-27---transparency-in-research-and-football</guid><description>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;A strategy for dealing with subjectivity in research, and in football, is to expose it. The VAR system in football allows the referee to scrutinise video footage of players, decide how grave a foul was, whether a ball crossed a line, or whether a situation should be deemed offside or not. It is a system designed to minimise human errors that could have a big influence on match results. It does not remove subjectivity, but it makes the ref’s decision-making process more transparent.&lt;/p&gt;
&lt;p&gt;Openly sharing research software serves a similar goal.² Or, as &lt;a href=&quot;https://journals.sagepub.com/doi/10.1177/2515245917747646#_i40&quot;&gt;Silberzahn et al.&lt;/a&gt; argue: “Transparency in data, methods, and process gives the rest of the community opportunity to see the decisions, question them, offer alternatives, and test these alternatives in further research.” However, as Antica Culina pointed out during the workshop, sharing code is not yet a standard practice for all researchers who write it.&lt;/p&gt;
&lt;p&gt;Without a guide or a plan, it may be unfair to expect every researcher to know how to do this. A standardised SMP template could help. As &lt;a href=&quot;https://nioo.knaw.nl/en/employees/antica-culina&quot;&gt;Steve Crouch&lt;/a&gt; from the &lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;Software Sustainability Institute&lt;/a&gt; (SSI) explained, SMPs require researchers to make explicit what their software does, who it is for, what the outputs are, who is responsible for the release and to ensure that the software stays available to the community.&lt;/p&gt;
&lt;p&gt;The workshop participants provided valuable input as to what an SMP template should contain. Currently, researchers typically specify their plans for managing software in data management plans. During the SMP workshop, it was apparent that there is a need for clear guidelines specifically for software management, in addition to data management, among researchers. Participants also made clear that because researchers are usually not software engineers, an SMP template would need to use plain language, accessible to those who may be familiar enough with coding to write a few analysis scripts for research, but are not familiar with professional software development.&lt;/p&gt;
&lt;p&gt;Participants also said that if writing plans for software management is to become standard practice in the future, the benefits of doing so should be emphasised to those who write code for research. Many in academia already feel overwhelmed with the amount of admin their work requires, and SMPs could be in danger of becoming ‘another form’. But beyond the benefit to the community, there can be a lot of value in writing an SMP to individuals. If software is an important part of the research output, an SMP helps researchers, engineers and research support staff to think about how that software will be structured, shared, and maintained. This can save time and effort later, when reproducing the results, or when using that software in a different project. Another benefit for the researcher lies in the increasing importance of software for research. An SMP can help researchers to write better quality software, which will likely be an important part of a researcher’s portfolio in the future.&lt;/p&gt;
&lt;p&gt;Still an open question is whether an SMP should be a part of every research project, and whether they should be integrated with data management plans. In addition, it is unclear if a universal SMP template is desirable, since different academic disciplines may have different software management needs. The eScience Center and NWO are setting up a working group to explore these questions and the possibility of creating a national template for Software Management Plans for Dutch research organisations.&lt;/p&gt;
&lt;p&gt;We would like to thank &lt;a href=&quot;https://www.nwo.nl/en/research-data-management&quot;&gt;Maria Cruz&lt;/a&gt; (NWO), &lt;a href=&quot;https://www.software.ac.uk/about/staff/person/steve-crouch&quot;&gt;Steve Crouch&lt;/a&gt; (SSI) and &lt;a href=&quot;https://nioo.knaw.nl/en/employees/antica-culina&quot;&gt;Antica Culina&lt;/a&gt; (NIOO) for their insightful talks about Data Management Plans and Software Management Plans. Thanks also to all participants for their valuable input.&lt;/p&gt;
&lt;p&gt;[1] For those not familiar with the rules of football, a red card is the heaviest correctional tool in football (soccer). It means that the player must leave the field immediately without being replaced, leaving their team in clear disadvantage. In the case of the European Championships, the player who receives a red card also misses their team’s next match, if there is one.&lt;/p&gt;
&lt;p&gt;[2] Arguably, as my colleague &lt;a href=&quot;https://medium.com/@pab.rod&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt; pointed out to me, the whole history of science and epistemology is about minimising human errors. Open Scientific Software doesn’t root in the development of Linux, but in Galileo and Newton.&lt;/p&gt;</description><pubDate>Thu, 27 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;A strategy for dealing with subjectivity in research, and in football, is to expose it. The VAR system in football allows the referee to scrutinise video footage of players, decide how grave a foul was, whether a ball crossed a line, or whether a situation should be deemed offside or not. It is a system designed to minimise human errors that could have a big influence on match results. It does not remove subjectivity, but it makes the ref’s decision-making process more transparent.&lt;/p&gt;
&lt;p&gt;Openly sharing research software serves a similar goal.² Or, as &lt;a href=&quot;https://journals.sagepub.com/doi/10.1177/2515245917747646#_i40&quot;&gt;Silberzahn et al.&lt;/a&gt; argue: “Transparency in data, methods, and process gives the rest of the community opportunity to see the decisions, question them, offer alternatives, and test these alternatives in further research.” However, as Antica Culina pointed out during the workshop, sharing code is not yet a standard practice for all researchers who write it.&lt;/p&gt;
&lt;p&gt;Without a guide or a plan, it may be unfair to expect every researcher to know how to do this. A standardised SMP template could help. As &lt;a href=&quot;https://nioo.knaw.nl/en/employees/antica-culina&quot;&gt;Steve Crouch&lt;/a&gt; from the &lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;Software Sustainability Institute&lt;/a&gt; (SSI) explained, SMPs require researchers to make explicit what their software does, who it is for, what the outputs are, who is responsible for the release and to ensure that the software stays available to the community.&lt;/p&gt;
&lt;p&gt;The workshop participants provided valuable input as to what an SMP template should contain. Currently, researchers typically specify their plans for managing software in data management plans. During the SMP workshop, it was apparent that there is a need for clear guidelines specifically for software management, in addition to data management, among researchers. Participants also made clear that because researchers are usually not software engineers, an SMP template would need to use plain language, accessible to those who may be familiar enough with coding to write a few analysis scripts for research, but are not familiar with professional software development.&lt;/p&gt;
&lt;p&gt;Participants also said that if writing plans for software management is to become standard practice in the future, the benefits of doing so should be emphasised to those who write code for research. Many in academia already feel overwhelmed with the amount of admin their work requires, and SMPs could be in danger of becoming ‘another form’. But beyond the benefit to the community, there can be a lot of value in writing an SMP to individuals. If software is an important part of the research output, an SMP helps researchers, engineers and research support staff to think about how that software will be structured, shared, and maintained. This can save time and effort later, when reproducing the results, or when using that software in a different project. Another benefit for the researcher lies in the increasing importance of software for research. An SMP can help researchers to write better quality software, which will likely be an important part of a researcher’s portfolio in the future.&lt;/p&gt;
&lt;p&gt;Still an open question is whether an SMP should be a part of every research project, and whether they should be integrated with data management plans. In addition, it is unclear if a universal SMP template is desirable, since different academic disciplines may have different software management needs. The eScience Center and NWO are setting up a working group to explore these questions and the possibility of creating a national template for Software Management Plans for Dutch research organisations.&lt;/p&gt;
&lt;p&gt;We would like to thank &lt;a href=&quot;https://www.nwo.nl/en/research-data-management&quot;&gt;Maria Cruz&lt;/a&gt; (NWO), &lt;a href=&quot;https://www.software.ac.uk/about/staff/person/steve-crouch&quot;&gt;Steve Crouch&lt;/a&gt; (SSI) and &lt;a href=&quot;https://nioo.knaw.nl/en/employees/antica-culina&quot;&gt;Antica Culina&lt;/a&gt; (NIOO) for their insightful talks about Data Management Plans and Software Management Plans. Thanks also to all participants for their valuable input.&lt;/p&gt;
&lt;p&gt;[1] For those not familiar with the rules of football, a red card is the heaviest correctional tool in football (soccer). It means that the player must leave the field immediately without being replaced, leaving their team in clear disadvantage. In the case of the European Championships, the player who receives a red card also misses their team’s next match, if there is one.&lt;/p&gt;
&lt;p&gt;[2] Arguably, as my colleague &lt;a href=&quot;https://medium.com/@pab.rod&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt; pointed out to me, the whole history of science and epistemology is about minimising human errors. Open Scientific Software doesn’t root in the development of Linux, but in Galileo and Newton.&lt;/p&gt;</content:encoded><author>Lieke de Boer</author></item><item><title>Henry, the City Tweaker</title><link>https://blog2.esciencecenter.nl/posts/2024-06-21---henry-the-city-tweaker</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-06-21---henry-the-city-tweaker</guid><description>&lt;h2 id=&quot;imagining-the-future-of-urban-planning&quot;&gt;Imagining the future of urban planning&lt;/h2&gt;
&lt;p&gt;5&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blogpost is our (&lt;a href=&quot;https://www.esciencecenter.nl/news/destination-earth-awards-peter-kalverla-for-his-visionary-proposal-for-the-future/&quot;&gt;winning&lt;/a&gt; &lt;a href=&quot;https://emojipedia.org/party-popper&quot;&gt;🎉&lt;/a&gt;) submission to Destination Earth’s &lt;a href=&quot;https://destination-earth.eu/event/2nd-destine-service-platform-innovation-prize-ideating-the-impact-of-the-desp/&quot;&gt;challenge &lt;/a&gt;to envision the future use of their platform. The story is set in 2050, when “urban sims” have come to replace traditional city planning tools. Urban sims are like the early century’s sandbox games, say, Cities Skylines, but for real. Design proposals with a net positive impact are eligible for execution, on the condition that they gather sufficient support. The story follows Henry as he experiences the rise of city tweaking firsthand.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Henry, the City Tweaker&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-19e1aa94.DzQkJD1P_1LpKVS.webp&quot; srcset=&quot;&quot;&gt;
Mockup of an “urban design interface”, powered by the digital twin engine, that was submitted with the challenge.Henry is a city tweaker. He never really pursued his destiny, but in retrospect, it seems all his arbitrary endeavors have been in anticipation of his true calling, which will be revealed to him shortly by an unremarkable lady wearing a white fur hat and a rabbit tattoo.&lt;/p&gt;
&lt;p&gt;His journey starts in the pouring twenties when urban sims are set to democratize urban planning. He makes his debut with an upgrade of the courtyard in his street. Replacing the paved square with a natural playground benefits the local climate, biodiversity, and perceived happiness. The timing is good too: with many new families moving in, there is ample support among the neighbours.&lt;/p&gt;
&lt;p&gt;After this encouraging start, Henry is hooked. As his proficiency grows, people around him start approaching him with their ideas as well. One of his relatives wants to build a sand battery below the communal parking lot, and an acquaintance asks for his help in developing a manure fermentation plant. While urban sims are open to anyone, in practice, by the early 30s, most of the content is created by dedicated individuals, and Henry is your local guru.&lt;/p&gt;
&lt;p&gt;Once he gains enough reputation to earn insider status, he learns to develop mods. This newfound ability draws the attention of companies and entrepreneurs. Mod creators are in high demand, but Henry isn’t in it for the money. He does a few collaborations with crop breeders, adding species to the agriculture module, and works with festival organizers to include an algorithm for acoustic barriers. But he consistently turns down their job offers.&lt;/p&gt;
&lt;p&gt;Instead, he starts participating in so-called “hackathons for the greater good”, organized specifically to tackle grand challenges. He likes the collaborative spirit and the appeal of contributing something substantial, such as the introduction of local distribution networks and a true price concept for public services.&lt;/p&gt;
&lt;p&gt;These are challenging topics indeed. While it is relatively straightforward to understand how design proposals interact with their immediate surroundings, non-local effects are much harder to grasp. Intrigued by the complexity of the problem, Henry spends a big chunk of the 2040s developing an X-AI module to unravel how genuine progress propagates through value chains.&lt;/p&gt;
&lt;p&gt;And so we arrive in 2050 when Henry is startled by the doorbell. “Good morning, Henry.” The friendly voice pauses to let him regain his calm. “I’m looking for a benevolent city tweaker. May I come in?”&lt;/p&gt;
&lt;p&gt;After the usual pleasantries, she turns serious. “Look, Henry. You know that genuine progress comes at the expense of concentrated wealth. You’ve seen it yourself with the distribution networks. Big players with a vested interest in the status quo are seeking to sabotage our system.” She pauses again. “We cannot play cat and mouse. The cat is too clumsy and the mice are too many. We need something of a more ‘&lt;em&gt;viral&lt;/em&gt;’ nature. That why we started IMMUNE.”&lt;/p&gt;
&lt;p&gt;“For your long track record of benevolent contributions and proven skill, you will receive an immunity status. You will be granted full privileges and access to a confidential forum. No strings attached. We simply trust that you will continue to serve society.” And with that, she stands up, leaving Henry as startled as she found him.&lt;/p&gt;
&lt;h2 id=&quot;backstory&quot;&gt;Backstory&lt;/h2&gt;
&lt;p&gt;While the story is completely fictitious, there are a lot of true ideas and concepts that have gone into it. Let me elaborate on some of them.&lt;/p&gt;
&lt;h3 id=&quot;progress-indicators&quot;&gt;Progress indicators&lt;/h3&gt;
&lt;p&gt;The premise of the story is that “designs with a net positive impact are eligible for execution”. But what is a net positive impact? There are several proposals in the literature on how to evaluate “progress”. Our mockups draw inspiration from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Genuine_progress_indicator&quot;&gt;Genuine Progress Indicator&lt;/a&gt;, and the “&lt;a href=&quot;https://doughnuteconomics.org/about-doughnut-economics&quot;&gt;economic doughnut&lt;/a&gt;”. Both models take many different aspects of well-being into account, including social and environmental well-being.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Henry, the City Tweaker&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-f074c219.BqxhJLtY_ZP1nDW.webp&quot; srcset=&quot;&quot;&gt;
Left: the genuine progress indicator (&lt;a href=&quot;https://www.recipesforwellbeing.org/genuine-progress-indicator/&quot;&gt;source&lt;/a&gt;). Right: the economic doughnut (&lt;a href=&quot;https://en.wikipedia.org/wiki/Doughnut_%28economic_model%29&quot;&gt;source&lt;/a&gt;).The idea is that the urban sims will evaluate design proposals based on these indicators. Currently, several “local” versions of the doughnut (or rather, the planetary boundaries framework) and the GPI monitor have been published in the scientific literature. Automating this process and making sure that the local scale interacts realistically with the larger scale is probably one of the biggest challenges, both technically and scientifically, in making Henry’s story come true.&lt;/p&gt;
&lt;h3 id=&quot;democratization&quot;&gt;Democratization&lt;/h3&gt;
&lt;p&gt;Another central element of the story is the democratization of urban planning. At first, it may seem unrealistic to outsource important and complex municipality work to “mere citizens”. On the other hand, we do this all the time with (open source) software. Why not do the same with tangible real estate? Especially since it’s publicly owned.&lt;/p&gt;
&lt;p&gt;In fact, at least in the Netherlands, we already have a process where citizens can apply for building permits with the municipality. It’s dull and bureaucratic, but it is there. Imagine what that could look like if you can simply upload a sketch of your plan as designed by a city builder. The design file would already have all the “technical” details required by the municipality. It would make the request and review process much easier.&lt;/p&gt;
&lt;p&gt;Our submission also included a mockup of a “design proposal page”, where the design is advertised and discussed by the relevant stakeholders (see below). In the story, Henry needs to gather support from the neighbours. I think there is a potential here to address the lack of participation and, consequently, lack of support that we see for example with renewable energy projects.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Henry, the City Tweaker&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-ca3ab313.um5cylqo_Z29lkyy.webp&quot; srcset=&quot;&quot;&gt;
Mockup of “design proposal page” that could be used to advertise urban design proposals, discuss them, and gather support.By the way, this design was inspired by &lt;a href=&quot;https://www.figma.com/community&quot;&gt;Figma&lt;/a&gt;’s community pages.&lt;/p&gt;
&lt;h3 id=&quot;gamification-or-rather-sciencification&quot;&gt;Gamification, or rather “sciencification”&lt;/h3&gt;
&lt;p&gt;The urban sims in the story take the idea of gamification to the extreme. Games are optimized for a great user experience, and gamification offers immense potential in making science more accessible and engaging to society.&lt;/p&gt;
&lt;p&gt;Recently, game developers have actually been pursuing similar ideas. For example, check out &lt;a href=&quot;https://play.eco/&quot;&gt;https://play.eco/&lt;/a&gt;, which aims to be a “forever game, growing in depth and breath and […] go beyond entertainment.” Perhaps we should be talking about “sciencifying” existing games instead. I would love to collaborate more with game designers.&lt;/p&gt;
&lt;p&gt;On a side note: IMHO science teams could be so much stronger if academia embraced more diverse function profiles. Why not employ dedicated communication specialists (YouTubers / content creators), research software engineers, or game developers in every team/group/department?*&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Imagination is a key driver of innovation and progress. Lifting the constraints of immediate feasibility inspires us to think big and let our creativity guide us. It helps to break away from doing more of the same and instead direct our research and energy towards an inspiring future.&lt;/p&gt;
&lt;p&gt;Participating in the Destination Earth challenge was a very enjoyable experience, and it would be great to see more such initiatives. In the meantime, I will be on the lookout for opportunities to help make Henry’s story come true.&lt;/p&gt;
&lt;p&gt;What do you think are the biggest challenges in realizing these urban sims? What would you add, or change, and what opportunities did I miss? Perhaps we can start shaping our future together!&lt;/p&gt;</description><pubDate>Fri, 21 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;imagining-the-future-of-urban-planning&quot;&gt;Imagining the future of urban planning&lt;/h2&gt;
&lt;p&gt;5&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;This blogpost is our (&lt;a href=&quot;https://www.esciencecenter.nl/news/destination-earth-awards-peter-kalverla-for-his-visionary-proposal-for-the-future/&quot;&gt;winning&lt;/a&gt; &lt;a href=&quot;https://emojipedia.org/party-popper&quot;&gt;🎉&lt;/a&gt;) submission to Destination Earth’s &lt;a href=&quot;https://destination-earth.eu/event/2nd-destine-service-platform-innovation-prize-ideating-the-impact-of-the-desp/&quot;&gt;challenge &lt;/a&gt;to envision the future use of their platform. The story is set in 2050, when “urban sims” have come to replace traditional city planning tools. Urban sims are like the early century’s sandbox games, say, Cities Skylines, but for real. Design proposals with a net positive impact are eligible for execution, on the condition that they gather sufficient support. The story follows Henry as he experiences the rise of city tweaking firsthand.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Henry, the City Tweaker&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-19e1aa94.DzQkJD1P_1LpKVS.webp&quot; srcset=&quot;&quot;&gt;
Mockup of an “urban design interface”, powered by the digital twin engine, that was submitted with the challenge.Henry is a city tweaker. He never really pursued his destiny, but in retrospect, it seems all his arbitrary endeavors have been in anticipation of his true calling, which will be revealed to him shortly by an unremarkable lady wearing a white fur hat and a rabbit tattoo.&lt;/p&gt;
&lt;p&gt;His journey starts in the pouring twenties when urban sims are set to democratize urban planning. He makes his debut with an upgrade of the courtyard in his street. Replacing the paved square with a natural playground benefits the local climate, biodiversity, and perceived happiness. The timing is good too: with many new families moving in, there is ample support among the neighbours.&lt;/p&gt;
&lt;p&gt;After this encouraging start, Henry is hooked. As his proficiency grows, people around him start approaching him with their ideas as well. One of his relatives wants to build a sand battery below the communal parking lot, and an acquaintance asks for his help in developing a manure fermentation plant. While urban sims are open to anyone, in practice, by the early 30s, most of the content is created by dedicated individuals, and Henry is your local guru.&lt;/p&gt;
&lt;p&gt;Once he gains enough reputation to earn insider status, he learns to develop mods. This newfound ability draws the attention of companies and entrepreneurs. Mod creators are in high demand, but Henry isn’t in it for the money. He does a few collaborations with crop breeders, adding species to the agriculture module, and works with festival organizers to include an algorithm for acoustic barriers. But he consistently turns down their job offers.&lt;/p&gt;
&lt;p&gt;Instead, he starts participating in so-called “hackathons for the greater good”, organized specifically to tackle grand challenges. He likes the collaborative spirit and the appeal of contributing something substantial, such as the introduction of local distribution networks and a true price concept for public services.&lt;/p&gt;
&lt;p&gt;These are challenging topics indeed. While it is relatively straightforward to understand how design proposals interact with their immediate surroundings, non-local effects are much harder to grasp. Intrigued by the complexity of the problem, Henry spends a big chunk of the 2040s developing an X-AI module to unravel how genuine progress propagates through value chains.&lt;/p&gt;
&lt;p&gt;And so we arrive in 2050 when Henry is startled by the doorbell. “Good morning, Henry.” The friendly voice pauses to let him regain his calm. “I’m looking for a benevolent city tweaker. May I come in?”&lt;/p&gt;
&lt;p&gt;After the usual pleasantries, she turns serious. “Look, Henry. You know that genuine progress comes at the expense of concentrated wealth. You’ve seen it yourself with the distribution networks. Big players with a vested interest in the status quo are seeking to sabotage our system.” She pauses again. “We cannot play cat and mouse. The cat is too clumsy and the mice are too many. We need something of a more ‘&lt;em&gt;viral&lt;/em&gt;’ nature. That why we started IMMUNE.”&lt;/p&gt;
&lt;p&gt;“For your long track record of benevolent contributions and proven skill, you will receive an immunity status. You will be granted full privileges and access to a confidential forum. No strings attached. We simply trust that you will continue to serve society.” And with that, she stands up, leaving Henry as startled as she found him.&lt;/p&gt;
&lt;h2 id=&quot;backstory&quot;&gt;Backstory&lt;/h2&gt;
&lt;p&gt;While the story is completely fictitious, there are a lot of true ideas and concepts that have gone into it. Let me elaborate on some of them.&lt;/p&gt;
&lt;h3 id=&quot;progress-indicators&quot;&gt;Progress indicators&lt;/h3&gt;
&lt;p&gt;The premise of the story is that “designs with a net positive impact are eligible for execution”. But what is a net positive impact? There are several proposals in the literature on how to evaluate “progress”. Our mockups draw inspiration from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Genuine_progress_indicator&quot;&gt;Genuine Progress Indicator&lt;/a&gt;, and the “&lt;a href=&quot;https://doughnuteconomics.org/about-doughnut-economics&quot;&gt;economic doughnut&lt;/a&gt;”. Both models take many different aspects of well-being into account, including social and environmental well-being.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Henry, the City Tweaker&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-f074c219.BqxhJLtY_ZP1nDW.webp&quot; srcset=&quot;&quot;&gt;
Left: the genuine progress indicator (&lt;a href=&quot;https://www.recipesforwellbeing.org/genuine-progress-indicator/&quot;&gt;source&lt;/a&gt;). Right: the economic doughnut (&lt;a href=&quot;https://en.wikipedia.org/wiki/Doughnut_%28economic_model%29&quot;&gt;source&lt;/a&gt;).The idea is that the urban sims will evaluate design proposals based on these indicators. Currently, several “local” versions of the doughnut (or rather, the planetary boundaries framework) and the GPI monitor have been published in the scientific literature. Automating this process and making sure that the local scale interacts realistically with the larger scale is probably one of the biggest challenges, both technically and scientifically, in making Henry’s story come true.&lt;/p&gt;
&lt;h3 id=&quot;democratization&quot;&gt;Democratization&lt;/h3&gt;
&lt;p&gt;Another central element of the story is the democratization of urban planning. At first, it may seem unrealistic to outsource important and complex municipality work to “mere citizens”. On the other hand, we do this all the time with (open source) software. Why not do the same with tangible real estate? Especially since it’s publicly owned.&lt;/p&gt;
&lt;p&gt;In fact, at least in the Netherlands, we already have a process where citizens can apply for building permits with the municipality. It’s dull and bureaucratic, but it is there. Imagine what that could look like if you can simply upload a sketch of your plan as designed by a city builder. The design file would already have all the “technical” details required by the municipality. It would make the request and review process much easier.&lt;/p&gt;
&lt;p&gt;Our submission also included a mockup of a “design proposal page”, where the design is advertised and discussed by the relevant stakeholders (see below). In the story, Henry needs to gather support from the neighbours. I think there is a potential here to address the lack of participation and, consequently, lack of support that we see for example with renewable energy projects.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Henry, the City Tweaker&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-ca3ab313.um5cylqo_Z29lkyy.webp&quot; srcset=&quot;&quot;&gt;
Mockup of “design proposal page” that could be used to advertise urban design proposals, discuss them, and gather support.By the way, this design was inspired by &lt;a href=&quot;https://www.figma.com/community&quot;&gt;Figma&lt;/a&gt;’s community pages.&lt;/p&gt;
&lt;h3 id=&quot;gamification-or-rather-sciencification&quot;&gt;Gamification, or rather “sciencification”&lt;/h3&gt;
&lt;p&gt;The urban sims in the story take the idea of gamification to the extreme. Games are optimized for a great user experience, and gamification offers immense potential in making science more accessible and engaging to society.&lt;/p&gt;
&lt;p&gt;Recently, game developers have actually been pursuing similar ideas. For example, check out &lt;a href=&quot;https://play.eco/&quot;&gt;https://play.eco/&lt;/a&gt;, which aims to be a “forever game, growing in depth and breath and […] go beyond entertainment.” Perhaps we should be talking about “sciencifying” existing games instead. I would love to collaborate more with game designers.&lt;/p&gt;
&lt;p&gt;On a side note: IMHO science teams could be so much stronger if academia embraced more diverse function profiles. Why not employ dedicated communication specialists (YouTubers / content creators), research software engineers, or game developers in every team/group/department?*&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Imagination is a key driver of innovation and progress. Lifting the constraints of immediate feasibility inspires us to think big and let our creativity guide us. It helps to break away from doing more of the same and instead direct our research and energy towards an inspiring future.&lt;/p&gt;
&lt;p&gt;Participating in the Destination Earth challenge was a very enjoyable experience, and it would be great to see more such initiatives. In the meantime, I will be on the lookout for opportunities to help make Henry’s story come true.&lt;/p&gt;
&lt;p&gt;What do you think are the biggest challenges in realizing these urban sims? What would you add, or change, and what opportunities did I miss? Perhaps we can start shaping our future together!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/henry-the-city-tweaker-19e1aa94.DzQkJD1P.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Brainstorming on the success of a research software catalogue</title><link>https://blog2.esciencecenter.nl/posts/2024-06-12---brainstorming-on-the-success-of-a-research-software-catalogu</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-06-12---brainstorming-on-the-success-of-a-research-software-catalogu</guid><description>&lt;h1 id=&quot;brainstorming-on-the-success-of-a-research-software-catalogue&quot;&gt;&lt;em&gt;Brainstorming on the success of a research software catalogue&lt;/em&gt;&lt;/h1&gt;
&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;Researchers reflect on the whys and hows of scientific software catalogues&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Brainstorming on the success of a research software catalogue&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;667&quot; height=&quot;673&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/brainstorming-on-the-success-of-a-resear-903a3824.c8S2nIoj_2aoPJu.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Created with DALL-E. Timestamp: 2024–04–23 14.57.58 Prompt: Create an image that conveys the concept of a digital software repository in a minimalistic and modern academic style.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;This blog entry was born during the unconference session on software catalogues that took place during the &lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day 2024&lt;/a&gt; in Hilversum, the Netherlands.&lt;/p&gt;
&lt;p&gt;The session was chaired by &lt;a href=&quot;https://www.uu.nl/medewerkers/MvanStiphout&quot;&gt;Mees van Stiphout&lt;/a&gt;. The piece was co-authored by &lt;a href=&quot;https://www.linkedin.com/in/pedrohserrano/&quot;&gt;Pedro Hernández Serrano&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/irenemartorelli/&quot;&gt;Irene Martorelli&lt;/a&gt;, Belén Torrente, Emma Daniëls, and &lt;a href=&quot;https://orcid.org/0009-0002-9622-6663&quot;&gt;Sreeparna Deb&lt;/a&gt;. It was reviewed and edited by &lt;a href=&quot;https://pabrod.github.io&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Software catalogues have become increasingly important for research software in modern-day academia. They are helpful for searching and finding research software; they guarantee that research software is accessible, has markers of quality, and is actively maintained. In this unconference conversation, we discussed what can make a software catalogue useful for users, developers, and the research community.&lt;/p&gt;
&lt;h2 id=&quot;software-catalogues&quot;&gt;Software catalogues&lt;/h2&gt;
&lt;p&gt;A software catalogue acts as a digital hub where research software is deposited or published, often linking to software stored on other servers. These catalogues are commonly referred to as directories, catalogues, registries, or platforms. The core aim of such catalogues is to make software readily available and useful for its intended research purposes. Popular examples are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://r-universe.dev/&quot;&gt;https://r-universe.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://research-software-directory.org/&quot;&gt;https://research-software-directory.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zenodo.org/&quot;&gt;https://zenodo.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Easy access to the software is crucial. Effective catalogues ensure that their contents are easily searchable both through their own interfaces and via external search engines.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;number of downloads&lt;/li&gt;
&lt;li&gt;date of last release&lt;/li&gt;
&lt;li&gt;size of the project&lt;/li&gt;
&lt;li&gt;reproducible build&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, robust metadata practices are essential.&lt;/p&gt;
&lt;p&gt;Beyond the technical aspects, the human element is also vital. Successful catalogues are supported by invested communities. These communities can offer support, facilitate collaboration, and even drive the software’s ongoing development. Additionally, providing clear documentation and accessible APIs helps users understand and interact with the catalogue more effectively, promoting better usage and integration of the software.&lt;/p&gt;
&lt;p&gt;Helping a community develop around a platform or catalogue is no trivial task: after achieving content ‘critical mass’, we need to do a lot of outreach to different parts of the research community just to make users and contributors aware of the catalogue.&lt;/p&gt;
&lt;p&gt;Some catalogues also integrate services such as rendering documentation, showing the maintenance status of the software, and checking reproducibility of builds by building the package within the platform. These services not only add value but also reassure users about the reliability and active development of the tools available.&lt;/p&gt;
&lt;p&gt;A catalogue must be clear about its purpose. Whether it aims to promote software, to serve as a portfolio, or to fulfill other objectives, this clarity helps shape the user experience and guide the catalogue’s strategic development.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;A software catalogue is about building an accessible, reliable, and community-supported platform that fosters reuse of software and reproduction of methods in the research software landscape. By focusing on content quality, ease of access, ease of use, and community engagement, catalogues can greatly enhance their utility and impact. These elements combine to not only preserve and share valuable software but also to stimulate ongoing improvement and discovery of research software. Through such catalogues, the future of research software is not just preserved; it is actively nurtured and expanded.&lt;/p&gt;</description><pubDate>Wed, 12 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;brainstorming-on-the-success-of-a-research-software-catalogue&quot;&gt;&lt;em&gt;Brainstorming on the success of a research software catalogue&lt;/em&gt;&lt;/h1&gt;
&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;Researchers reflect on the whys and hows of scientific software catalogues&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Brainstorming on the success of a research software catalogue&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;667&quot; height=&quot;673&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/brainstorming-on-the-success-of-a-resear-903a3824.c8S2nIoj_2aoPJu.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Created with DALL-E. Timestamp: 2024–04–23 14.57.58 Prompt: Create an image that conveys the concept of a digital software repository in a minimalistic and modern academic style.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;This blog entry was born during the unconference session on software catalogues that took place during the &lt;a href=&quot;https://www.esciencecenter.nl/news/national-research-software-day-recap/&quot;&gt;National Research Software Day 2024&lt;/a&gt; in Hilversum, the Netherlands.&lt;/p&gt;
&lt;p&gt;The session was chaired by &lt;a href=&quot;https://www.uu.nl/medewerkers/MvanStiphout&quot;&gt;Mees van Stiphout&lt;/a&gt;. The piece was co-authored by &lt;a href=&quot;https://www.linkedin.com/in/pedrohserrano/&quot;&gt;Pedro Hernández Serrano&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/irenemartorelli/&quot;&gt;Irene Martorelli&lt;/a&gt;, Belén Torrente, Emma Daniëls, and &lt;a href=&quot;https://orcid.org/0009-0002-9622-6663&quot;&gt;Sreeparna Deb&lt;/a&gt;. It was reviewed and edited by &lt;a href=&quot;https://pabrod.github.io&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Software catalogues have become increasingly important for research software in modern-day academia. They are helpful for searching and finding research software; they guarantee that research software is accessible, has markers of quality, and is actively maintained. In this unconference conversation, we discussed what can make a software catalogue useful for users, developers, and the research community.&lt;/p&gt;
&lt;h2 id=&quot;software-catalogues&quot;&gt;Software catalogues&lt;/h2&gt;
&lt;p&gt;A software catalogue acts as a digital hub where research software is deposited or published, often linking to software stored on other servers. These catalogues are commonly referred to as directories, catalogues, registries, or platforms. The core aim of such catalogues is to make software readily available and useful for its intended research purposes. Popular examples are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://r-universe.dev/&quot;&gt;https://r-universe.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://research-software-directory.org/&quot;&gt;https://research-software-directory.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zenodo.org/&quot;&gt;https://zenodo.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Easy access to the software is crucial. Effective catalogues ensure that their contents are easily searchable both through their own interfaces and via external search engines.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;number of downloads&lt;/li&gt;
&lt;li&gt;date of last release&lt;/li&gt;
&lt;li&gt;size of the project&lt;/li&gt;
&lt;li&gt;reproducible build&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, robust metadata practices are essential.&lt;/p&gt;
&lt;p&gt;Beyond the technical aspects, the human element is also vital. Successful catalogues are supported by invested communities. These communities can offer support, facilitate collaboration, and even drive the software’s ongoing development. Additionally, providing clear documentation and accessible APIs helps users understand and interact with the catalogue more effectively, promoting better usage and integration of the software.&lt;/p&gt;
&lt;p&gt;Helping a community develop around a platform or catalogue is no trivial task: after achieving content ‘critical mass’, we need to do a lot of outreach to different parts of the research community just to make users and contributors aware of the catalogue.&lt;/p&gt;
&lt;p&gt;Some catalogues also integrate services such as rendering documentation, showing the maintenance status of the software, and checking reproducibility of builds by building the package within the platform. These services not only add value but also reassure users about the reliability and active development of the tools available.&lt;/p&gt;
&lt;p&gt;A catalogue must be clear about its purpose. Whether it aims to promote software, to serve as a portfolio, or to fulfill other objectives, this clarity helps shape the user experience and guide the catalogue’s strategic development.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;A software catalogue is about building an accessible, reliable, and community-supported platform that fosters reuse of software and reproduction of methods in the research software landscape. By focusing on content quality, ease of access, ease of use, and community engagement, catalogues can greatly enhance their utility and impact. These elements combine to not only preserve and share valuable software but also to stimulate ongoing improvement and discovery of research software. Through such catalogues, the future of research software is not just preserved; it is actively nurtured and expanded.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/brainstorming-on-the-success-of-a-resear-903a3824.c8S2nIoj.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>A Tale of Tallness</title><link>https://blog2.esciencecenter.nl/posts/2024-05-28---a-tale-of-tallness</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-05-28---a-tale-of-tallness</guid><description>&lt;p&gt;In the past two centuries, the Dutch have become the tallest people of the planet. What factors caused this remarkable development? This is the central research question in the work of &lt;a href=&quot;https://www.ru.nl/en/people/quanjer-b&quot;&gt;Björn Quanjer&lt;/a&gt; of Radboud University of Nijmegen. In May 2024, he completed a comprehensive study involving data of thousands of subjects covering the period 1850–1950.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Tale of Tallness&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-f4a1acee.DFAx4dw3_22KOdk.webp&quot; srcset=&quot;&quot;&gt;
Björn Quanjer (right) defending his PhD thesis in Nijmegen on Wednesday 1 May 2024. The presented slide shows the researcher superimposed on a picture next to his grandfather (right) to indicate the gain of the heights of Dutch men in the past century&lt;/p&gt;
&lt;h2 id=&quot;phd-defense&quot;&gt;Phd defense&lt;/h2&gt;
&lt;p&gt;Björn Quanjer is a member of the project &lt;a href=&quot;https://research-software-directory.org/projects/ree-hdsc&quot;&gt;REE-HDSC&lt;/a&gt;, Recognizing Extracted Entities for the Historical Database Suriname Curaçao, a collaboration between the Netherlands eScience Center and Radboud University Nijmegen. On Wednesday 1 May 2024, he successfully defended his PhD thesis &lt;a href=&quot;https://www.ru.nl/en/research/research-news/what-height-says-about-the-development-of-our-prosperity-and-health&quot;&gt;The Tale of Tallness&lt;/a&gt;, receiving the distinction cum laude. It was the first time since 1987 that this distinction had been awarded to a researcher in his field in Nijmegen.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Tale of Tallness&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;401&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-8b19776a.D4xmXyC6_ZHuKjy.webp&quot; srcset=&quot;&quot;&gt;
Average height of Dutch males at conscription (blue line) and at adult age (black line) for birth years between 1815 and 1955 (Figure 1.3 of Björn Quanjer’s thesis, reused with permission)&lt;/p&gt;
&lt;h2 id=&quot;data&quot;&gt;Data&lt;/h2&gt;
&lt;p&gt;Quanjer’s study uses the &lt;a href=&quot;https://iisg.amsterdam/en/hsn/data&quot;&gt;Historical Sample of The Netherlands&lt;/a&gt;, a dataset which contains life courses for a sample of about 0.5% of the Dutch population born between 1850 and 1922. The life courses are based on birth, marriage and death certificates from the Dutch civil registry. They also include military conscription records from the provincial archives, which are central to this study. At the time, all young Dutch men were checked for military service, so their height was registered in these records. Because women were exempt from military service, the study is restricted to the height developments of Dutch men.&lt;/p&gt;
&lt;p&gt;The study deals with several data challenges. For example, did the lower participation of the elite in the conscription have an effect on the measured heights? Quanjer shows with statistical tests that the effect was small. Furthermore, how can we model the effect of childhood illness on height without data on illness? Quanjer models illness by death: if the people around a Dutch person die (parents, siblings, neighbors), the chance that the person has experienced severe health problems is higher.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Tale of Tallness&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-4b69176a.nFfpilSW_Zoi6Ho.webp&quot; srcset=&quot;&quot;&gt;
Relation between birth order and average conscription height of Dutch males (blue line): boys born later in large families are taller than their older brothers (Figure 3.4 of Björn Quanjer’s thesis, reused with permission)&lt;/p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;
&lt;p&gt;Quanjer’s study provides several interesting observations. Losing a mother at the age of 5–12 proved to have a negative effect on conscription height compared with siblings that lost their mothers on a different age. However losing a father at that age had an opposite effect: these children were taller at conscription. Growing up in a family with many children can have a negative effect on height (fewer resources per child) but you have to consider that the older children can contribute to the family income. For this reason the younger children of large families were taller at conscription than their older siblings.&lt;/p&gt;
&lt;h2 id=&quot;current-developments&quot;&gt;Current developments&lt;/h2&gt;
&lt;p&gt;Unlike other studies on height development, Quanjer investigates several variables that could have an effect on heights: genetics, nutrition, health, family size, mortality, wealth and life events. An interesting open question that he addresses in his final chapter, is whether historical heights can be used as a proxy for any of these variables. Given the correlation between health, wealth and height, we should be concerned about the recent stagnation in the rise of heights of the Dutch. Quanjer names the current rise of obesity and purchase inequality as possible causes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Björn Quanjer, &lt;a href=&quot;https://repository.ubn.ru.nl/handle/2066/300359&quot;&gt;A Tale Of Tallness. A household perspective on early life determinants of male height within the Netherlands between 1850 and 1950&lt;/a&gt;. PhD thesis, Radboud University Nijmegen, 2024.&lt;/p&gt;
&lt;p&gt;Björn Quanjer, &lt;a href=&quot;https://www.nporadio1.nl/fragmenten/nieuwsweekend/9c0422d1-7fa4-45b5-9729-ff9b5d8d4378/2024-05-11-hoe-welvarender-het-land-hoe-langer-zijn-inwoners&quot;&gt;Hoe welvarender het land, hoe langer zijn inwoners&lt;/a&gt;. Interview Nieuwsweekend, Omroep MAX, Radio 1, 11 May 2024 09:50 (in Dutch).&lt;/p&gt;</description><pubDate>Tue, 28 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the past two centuries, the Dutch have become the tallest people of the planet. What factors caused this remarkable development? This is the central research question in the work of &lt;a href=&quot;https://www.ru.nl/en/people/quanjer-b&quot;&gt;Björn Quanjer&lt;/a&gt; of Radboud University of Nijmegen. In May 2024, he completed a comprehensive study involving data of thousands of subjects covering the period 1850–1950.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Tale of Tallness&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-f4a1acee.DFAx4dw3_22KOdk.webp&quot; srcset=&quot;&quot;&gt;
Björn Quanjer (right) defending his PhD thesis in Nijmegen on Wednesday 1 May 2024. The presented slide shows the researcher superimposed on a picture next to his grandfather (right) to indicate the gain of the heights of Dutch men in the past century&lt;/p&gt;
&lt;h2 id=&quot;phd-defense&quot;&gt;Phd defense&lt;/h2&gt;
&lt;p&gt;Björn Quanjer is a member of the project &lt;a href=&quot;https://research-software-directory.org/projects/ree-hdsc&quot;&gt;REE-HDSC&lt;/a&gt;, Recognizing Extracted Entities for the Historical Database Suriname Curaçao, a collaboration between the Netherlands eScience Center and Radboud University Nijmegen. On Wednesday 1 May 2024, he successfully defended his PhD thesis &lt;a href=&quot;https://www.ru.nl/en/research/research-news/what-height-says-about-the-development-of-our-prosperity-and-health&quot;&gt;The Tale of Tallness&lt;/a&gt;, receiving the distinction cum laude. It was the first time since 1987 that this distinction had been awarded to a researcher in his field in Nijmegen.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Tale of Tallness&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;401&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-8b19776a.D4xmXyC6_ZHuKjy.webp&quot; srcset=&quot;&quot;&gt;
Average height of Dutch males at conscription (blue line) and at adult age (black line) for birth years between 1815 and 1955 (Figure 1.3 of Björn Quanjer’s thesis, reused with permission)&lt;/p&gt;
&lt;h2 id=&quot;data&quot;&gt;Data&lt;/h2&gt;
&lt;p&gt;Quanjer’s study uses the &lt;a href=&quot;https://iisg.amsterdam/en/hsn/data&quot;&gt;Historical Sample of The Netherlands&lt;/a&gt;, a dataset which contains life courses for a sample of about 0.5% of the Dutch population born between 1850 and 1922. The life courses are based on birth, marriage and death certificates from the Dutch civil registry. They also include military conscription records from the provincial archives, which are central to this study. At the time, all young Dutch men were checked for military service, so their height was registered in these records. Because women were exempt from military service, the study is restricted to the height developments of Dutch men.&lt;/p&gt;
&lt;p&gt;The study deals with several data challenges. For example, did the lower participation of the elite in the conscription have an effect on the measured heights? Quanjer shows with statistical tests that the effect was small. Furthermore, how can we model the effect of childhood illness on height without data on illness? Quanjer models illness by death: if the people around a Dutch person die (parents, siblings, neighbors), the chance that the person has experienced severe health problems is higher.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A Tale of Tallness&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-4b69176a.nFfpilSW_Zoi6Ho.webp&quot; srcset=&quot;&quot;&gt;
Relation between birth order and average conscription height of Dutch males (blue line): boys born later in large families are taller than their older brothers (Figure 3.4 of Björn Quanjer’s thesis, reused with permission)&lt;/p&gt;
&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;
&lt;p&gt;Quanjer’s study provides several interesting observations. Losing a mother at the age of 5–12 proved to have a negative effect on conscription height compared with siblings that lost their mothers on a different age. However losing a father at that age had an opposite effect: these children were taller at conscription. Growing up in a family with many children can have a negative effect on height (fewer resources per child) but you have to consider that the older children can contribute to the family income. For this reason the younger children of large families were taller at conscription than their older siblings.&lt;/p&gt;
&lt;h2 id=&quot;current-developments&quot;&gt;Current developments&lt;/h2&gt;
&lt;p&gt;Unlike other studies on height development, Quanjer investigates several variables that could have an effect on heights: genetics, nutrition, health, family size, mortality, wealth and life events. An interesting open question that he addresses in his final chapter, is whether historical heights can be used as a proxy for any of these variables. Given the correlation between health, wealth and height, we should be concerned about the recent stagnation in the rise of heights of the Dutch. Quanjer names the current rise of obesity and purchase inequality as possible causes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Björn Quanjer, &lt;a href=&quot;https://repository.ubn.ru.nl/handle/2066/300359&quot;&gt;A Tale Of Tallness. A household perspective on early life determinants of male height within the Netherlands between 1850 and 1950&lt;/a&gt;. PhD thesis, Radboud University Nijmegen, 2024.&lt;/p&gt;
&lt;p&gt;Björn Quanjer, &lt;a href=&quot;https://www.nporadio1.nl/fragmenten/nieuwsweekend/9c0422d1-7fa4-45b5-9729-ff9b5d8d4378/2024-05-11-hoe-welvarender-het-land-hoe-langer-zijn-inwoners&quot;&gt;Hoe welvarender het land, hoe langer zijn inwoners&lt;/a&gt;. Interview Nieuwsweekend, Omroep MAX, Radio 1, 11 May 2024 09:50 (in Dutch).&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/a-tale-of-tallness-f4a1acee.DFAx4dw3.jpeg" medium="image"/><author>Erik Tjong Kim Sang</author></item><item><title>Python’s timeit: Find the fastest code in no time</title><link>https://blog2.esciencecenter.nl/posts/2024-05-14---pythons-timeit-find-the-fastest-code-in-no-time</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-05-14---pythons-timeit-find-the-fastest-code-in-no-time</guid><description>&lt;p&gt;&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--d3174fda.CiHIKL9q_Z1Xafa3.webp&quot; srcset=&quot;&quot;&gt;
Trains are fast, and your code should be too. Or is it the other way around? — Photo by &lt;a href=&quot;https://unsplash.com/@lum3n?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;LUM3N&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Every programmer wants their programs to run a little faster. While optimizing your whole code to run faster can take a lot of effort, an easy way to gain some speed is to choose the fastest implementation. Which of Python’s options &lt;em&gt;is&lt;/em&gt; the fastest is not always clear though, so wouldn’t it be nice to have a tool to quickly compare the speed of different implementation choices?&lt;/p&gt;
&lt;p&gt;In this post, I will give a short introduction to Python’s built-in &lt;code&gt;[timeit ](https://docs.python.org/3/library/timeit.html)&lt;/code&gt;module, and go over the three main ways to use it to time small snippets of Python code.&lt;/p&gt;
&lt;h2 id=&quot;timey-wimey-python-timeit&quot;&gt;Timey Wimey Python: timeit&lt;/h2&gt;
&lt;p&gt;What is Python’s &lt;code&gt;timeit&lt;/code&gt; module?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;This module provides a simple way to time small bits of Python code.
It has both a Command-Line Interface as well as a callable one. It
avoids a number of common traps for measuring execution times.&lt;/p&gt;
&lt;p&gt;— timeit documentation&lt;/p&gt;
&lt;p&gt;In contrast to profiling the runtime of your entire program, the &lt;code&gt;timeit&lt;/code&gt; module is best suited to time small snippets. We can divide these comparisons into three classes, as illustrated by the examples I will use throughout this blog post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Standalone one-liners, such as:&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;join-on-a-list-comprehension&quot;&gt;join on a list comprehension&lt;/h1&gt;
&lt;p&gt;”,“.join([str(n) for n in range(100)])&lt;/p&gt;
&lt;h1 id=&quot;join-on-a-generator-expression&quot;&gt;join on a generator expression&lt;/h1&gt;
&lt;p&gt;”,“.join(str(n) for n in range(100))&lt;/p&gt;
&lt;h1 id=&quot;join-on-the-map-function&quot;&gt;join on the &lt;code&gt;map&lt;/code&gt; function&lt;/h1&gt;
&lt;p&gt;”,“.join(map(str, range(100)))2. Standalone multi-liners, such as:&lt;/p&gt;
&lt;h1 id=&quot;append&quot;&gt;append&lt;/h1&gt;
&lt;p&gt;x = []
for i in range(1000):
x.append(i)&lt;/p&gt;
&lt;h1 id=&quot;list-addition&quot;&gt;list addition&lt;/h1&gt;
&lt;p&gt;x = []
for i in range(1000):
x += [i]&lt;em&gt;(ignoring the faster list-comprehension alternative &lt;em&gt;&lt;code&gt;*[i for i in range(100)]*&lt;/code&gt;&lt;/em&gt; for the sake of example)&lt;/em&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Any snippets with some setup required:&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;setup&quot;&gt;setup&lt;/h1&gt;
&lt;p&gt;text = “sample string”
char = “g”&lt;/p&gt;
&lt;h1 id=&quot;in-operator&quot;&gt;in-operator&lt;/h1&gt;
&lt;p&gt;char in text&lt;/p&gt;
&lt;h1 id=&quot;find-method&quot;&gt;find-method&lt;/h1&gt;
&lt;p&gt;text.find(char)
&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;454&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--070a66dd.CwXeKfoS_Z17mYKq.webp&quot; srcset=&quot;&quot;&gt;
Calculating with time — Photo by &lt;a href=&quot;https://unsplash.com/@takeshi2?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;wu yi&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-a-script-import-timeit&quot;&gt;In a script: import timeit&lt;/h2&gt;
&lt;p&gt;As &lt;code&gt;timeit&lt;/code&gt; is a Python module, you can import it and write Python scripts for your tests. This method is the most self-documenting and repeatable way of writing your timing experiments and makes it easy to store the results for further processing.&lt;/p&gt;
&lt;p&gt;The first way you might implement this is to directly use the &lt;code&gt;timeit&lt;/code&gt; function from the module:&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; import timeit
&gt;&gt;&gt; timeit.timeit()  # default arguments: timeit(stmt=‘pass’, number=1_000_000)
0.01063702700776048By running &lt;code&gt;timeit()&lt;/code&gt; without any further arguments, we execute the default statement &lt;code&gt;stmt=&apos;pass&apos;&lt;/code&gt; a million times, showing the minimal overhead of Python’s &lt;code&gt;pass&lt;/code&gt; statement.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note: &lt;code&gt;stmt&lt;/code&gt; can either be a string or a so-called &lt;em&gt;callable&lt;/em&gt;, i.e., a function. For clarity and brevity, I’ll keep using strings for now.&lt;/p&gt;
&lt;p&gt;The major drawback of this method is that you have to guess the number of times to run your snippet up front. If you guess too low the results won’t be reliable, but if you guess too high it might take minutes or hours, defeating the point of a quick test.&lt;/p&gt;
&lt;p&gt;Luckily, there is a better way: You can create a &lt;code&gt;Timer&lt;/code&gt; for your snippet, and call the &lt;code&gt;autorange&lt;/code&gt; method to automatically try increasing numbers until the time taken is at least 0.2 seconds. It returns the number of repetitions reached, and the total time taken, so you can easily calculate the time per iteration.&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; import timeit
&gt;&gt;&gt; timeit.Timer().autorange()  # default arguments: Timer(stmt=‘pass’)
(50000000, 0.2607337789959274)&lt;/p&gt;
&lt;h3 id=&quot;standalone-one-liners&quot;&gt;Standalone one-liners**&lt;/h3&gt;
&lt;p&gt;Let’s start by comparing the simple one-liners. We give the statement we want to time as a string and specify a custom number of iterations. Note that when your statement already deals with double-quoted strings, the whole string should be given single-quoted, or vice-versa.&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; from timeit import Timer**&gt;&gt;&gt; Timer(’”, “.join([str(n) for n in range(100)])‘).autorange()
(50000, 0.3393513219925808)
&gt;&gt;&gt; Timer(’”, “.join(str(n) for n in range(100))‘).autorange()
(50000, 0.38378613100212533)
&gt;&gt;&gt; Timer(’”, “.join(map(str, range(100)))‘).autorange()
(50000, 0.48742324599879794)From the reported number of repetitions and returned time in seconds, we can calculate that each of these lines took 6.79**, **7.67, **and &lt;strong&gt;9.75&lt;/strong&gt; microseconds to execute respectively.&lt;/p&gt;
&lt;h3 id=&quot;standalone-multi-liners&quot;&gt;&lt;strong&gt;Standalone multi-liners&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes the snippet you want to test will consist of multiple statements. Python allows you to put multiple statements on a single line with a semicolon &lt;code&gt;x = 1; y = 2&lt;/code&gt;. Then you can just run your test as explained above for the standalone one-liners. This does not work for snippets with indented code like &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;for&lt;/code&gt; though.&lt;/p&gt;
&lt;p&gt;To time these snippets that &lt;em&gt;have&lt;/em&gt; to span multiple lines, you can give &lt;code&gt;Timer()&lt;/code&gt; a multi-line string as argument. The beautiful and Pythonic way to do this is using Python’s multi-line strings. (The non-Pythonic way is to add &lt;code&gt;\n&lt;/code&gt; characters in your regular strings.)&lt;/p&gt;
&lt;p&gt;These multi-line cases are where it becomes more practical to pass a callable than to re-type your code as a string:&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; from timeit import Timer**&gt;&gt;&gt; Timer(&apos;&apos;&apos;x = []
… for i in range(1000):
…     x.append(i)&apos;&apos;&apos;).autorange()
(20000, 0.34225083301134873)
&gt;&gt;&gt; def add_test():
…     x = []
…     for i in range(1000):
…         x += [i]
&gt;&gt;&gt; Timer(append_test).autorange()
(5000, 0.2470278069959022)&lt;/p&gt;
&lt;h3 id=&quot;setup-required&quot;&gt;Setup required**&lt;/h3&gt;
&lt;p&gt;If there is some setup that only has to be run once, including it in a multi-line snippet means it’s executed at every iteration. Then you’d be measuring something you don’t want to measure! Instead, you can pass this setup statement as a separate argument &lt;code&gt;setup&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; from timeit import Timer
&gt;&gt;&gt; Timer(
…     setup=‘text = “sample string”; char = “g”’,
…     stmt=‘char in text’,
… ).autorange()
(20000000, 0.3793242520041531)
&gt;&gt;&gt; Timer(
…     ‘text.find(char)’,
…     ‘text = “sample string”; char = “g”’
… ).autorange()
(5000000, 0.36903892100963276)
&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;298&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--404fd5ff.D2p9y8gP_qgspF.webp&quot; srcset=&quot;&quot;&gt;
Time still flies if you’re having fun in the terminal — render by &lt;a href=&quot;https://github.com/tenox7/aclock&quot;&gt;aclock&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;command-line-python--m-timeit&quot;&gt;Command Line: python -m timeit&lt;/h2&gt;
&lt;p&gt;Python’s &lt;code&gt;timeit&lt;/code&gt; module can also be run as a command line tool.&lt;/p&gt;
&lt;p&gt;$ python -m timeit -n 10000 ‘pass’
10000 loops, best of 3: 0.0109 usec per loopThe usage is similar to the imported &lt;code&gt;timeit&lt;/code&gt; function as shown in the previous section. The &lt;code&gt;-n&lt;/code&gt; option is optional though, and the same &lt;code&gt;autorange&lt;/code&gt; behavior will be used if it’s not given. It also reports the actual time per iteration, instead of having to calculate that yourself. This is reported in &lt;code&gt;nsec&lt;/code&gt;, &lt;code&gt;usec&lt;/code&gt;, &lt;code&gt;msec&lt;/code&gt; or &lt;code&gt;sec&lt;/code&gt;, for nano-, micro-, mili- and whole seconds respectively. Note also that it reports ‘best of 5’: it’s repeated the &lt;code&gt;autorange&lt;/code&gt; timing five times, and reports the minimum.&lt;/p&gt;
&lt;p&gt;$ python -m timeit ‘pass’
50000000 loops, best of 5: 5.21 nsec per loop&lt;/p&gt;
&lt;h3 id=&quot;standalone-one-liners-1&quot;&gt;Standalone one-liners&lt;/h3&gt;
&lt;p&gt;Testing one-liners with the command line is as easy as replacing &lt;code&gt;pass&lt;/code&gt; from the introduction with the code you want to test, and the &lt;code&gt;timeit&lt;/code&gt; tool will automatically report the time in a nice human-readable format.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;100&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mn&gt;50000&lt;/mn&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mn&gt;6.66&lt;/mn&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;python -m timeit &apos;&quot;, &quot;.join([str(n) for n in range(100)])&apos;
50000 loops, best of 5: 6.66 usec per loop&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0019em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;im&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nin&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;50000&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;6.66&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; python -m timeit ’”, “.join(str(n) for n in range(100))’
50000 loops, best of 5: 7.62 usec per loop
$ python -m timeit ’”, “.join(map(str, range(100)))’
50000 loops, best of 5: 9.31 usec per loop&lt;/p&gt;
&lt;h3 id=&quot;standalone-multi-liners-1&quot;&gt;Standalone multi-liners&lt;/h3&gt;
&lt;p&gt;As before, the simplest way to test a snippet of multiple lines is to join the statements with a semicolon if no indentation is required. When indentation is required, the other option is to pass multiple strings as arguments to the command. Note that you still have to add the indentation properly yourself! This can get tricky to count if your indentation is more than a single level deep, but is usually not too hard.&lt;/p&gt;
&lt;p&gt;$ python -m timeit ‘x = []’ ‘for i in range(1000):’ ’    x.append(i)’
20000 loops, best of 5: 17.1 usec per loop&lt;/p&gt;
&lt;p&gt;$ python -m timeit ‘x = []’ ‘for i in range(1000):’ ’    x += [i]’
5000 loops, best of 5: 48.4 usec per loop&lt;/p&gt;
&lt;h3 id=&quot;setup-required-1&quot;&gt;Setup required&lt;/h3&gt;
&lt;p&gt;To add some initial setup such as imports or variable declarations, we can use the &lt;code&gt;-s&lt;/code&gt; option:&lt;/p&gt;
&lt;p&gt;$ python -m timeit -s ‘pass’ ‘pass’
50000000 loops, best of 5: 5.21 nsec per loopThe setup &lt;em&gt;does&lt;/em&gt; come before the statement to test in this case, so that makes it a bit more intuitive to read.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Double superscript at position 58: …&amp;#x22;; char = &amp;#x22;g&amp;#x22;&amp;#x27; &amp;#x27;̲char in text&amp;#x27;
2…&quot; style=&quot;color:#cc0000&quot;&gt;python -m timeit -s &apos;text = &quot;sample string&quot;; char = &quot;g&quot;&apos; &apos;char in text&apos;
20000000 loops, best of 5: 19 nsec per loop&lt;/span&gt; python -m timeit -s ‘text = “sample string”; char = “g”’ ‘text.find(char)’
5000000 loops, best of 5: 69.3 nsec per loop
&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;420&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--4c2edcf2.SpWYA1fW_Z2n9UTg.webp&quot; srcset=&quot;&quot;&gt;
Timing can be an important part of your notebook toolkit&lt;/p&gt;
&lt;h2 id=&quot;ipythonjupyter-magics-timeit&quot;&gt;IPython/Jupyter magics: %timeit&lt;/h2&gt;
&lt;p&gt;When working in the &lt;a href=&quot;https://pypi.org/project/ipython&quot;&gt;IPython&lt;/a&gt; interactive shell, or in a &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter notebook &lt;/a&gt;with a Python kernel, you have access to the so-called &lt;a href=&quot;https://ipython.readthedocs.io/en/stable/interactive/magics.html&quot;&gt;‘magic commands’&lt;/a&gt;. For timeit, there is the &lt;code&gt;[%timeit](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-timeit)&lt;/code&gt; magic¹. It simply passes the code you type after it to (a version of) &lt;code&gt;timeit.Timer().autorange()&lt;/code&gt;! Like magic!&lt;/p&gt;
&lt;p&gt;One small caveat is that the outcome is reported as a mean +/- standard deviation of multiple repetitions, while the original Python documentation suggests always using the minimum.&lt;/p&gt;
&lt;h3 id=&quot;standalone-one-liners-2&quot;&gt;Standalone one-liners&lt;/h3&gt;
&lt;p&gt;For simple one-liners, just type the code as you would normally, and type &lt;code&gt;%timeit&lt;/code&gt; before it. That’s all!&lt;/p&gt;
&lt;p&gt;In [1]: %timeit ”, “.join([str(n) for n in range(100)])
6.92 µs ± 46.7 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;p&gt;In [2]: %timeit ”, “.join(str(n) for n in range(100))
8.27 µs ± 1.15 µs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;p&gt;In [3]: %timeit ”, “.join(map(str, range(100)))
10.9 µs ± 1.72 µs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;h3 id=&quot;standalone-multi-liners-2&quot;&gt;Standalone multi-liners&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;%timeit&lt;/code&gt; magic doesn’t quite work for multi-line snippets though. Why? Because magics with a &lt;em&gt;single&lt;/em&gt; &lt;code&gt;%&lt;/code&gt; are &lt;em&gt;line-magics&lt;/em&gt;. For &lt;em&gt;cell-magics&lt;/em&gt;, you just have to add another &lt;code&gt;%&lt;/code&gt; to make it &lt;code&gt;%%timeit&lt;/code&gt;. Then it will time all the code in your cell. No further difficulties whatsoever!&lt;/p&gt;
&lt;p&gt;In [1]: %%timeit
…: x = []
…: for i in range(1000):
…:     x.append(i)
…:
23.6 µs ± 3.37 µs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;p&gt;In [2]: %%timeit
…: x = []
…: for i in range(1000):
…:     x += [i]
49 µs ± 385 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)A word of warning: any code on the same line as &lt;code&gt;%%timeit&lt;/code&gt; will be used as setup and only be run once. I think it’s too easy to make mistakes with this, so I’d avoid this feature. Compare:&lt;/p&gt;
&lt;p&gt;In [1]: %%timeit y = [x for x in range(1_000_000)]  # setup is not timed
…: len(y)
…:
…:
21.7 ns ± 0.297 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)&lt;/p&gt;
&lt;p&gt;In [2]: %%timeit
…: y = [x for x in range(1_000_000)]  # this line is now being timed
…: len(y)
…:
…:
22.9 ms ± 35.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)&lt;/p&gt;
&lt;h3 id=&quot;setup-required-2&quot;&gt;Setup required&lt;/h3&gt;
&lt;p&gt;Now you might be thinking &lt;em&gt;“but then where do I put my setup command for either &lt;em&gt;&lt;code&gt;*%timeit*&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;*%%timeit*&lt;/code&gt;&lt;/em&gt;?”&lt;/em&gt; The answer: you can run it in some previous cell! As IPython/Jupyter already takes care of passing your code on to the &lt;code&gt;timeit&lt;/code&gt; module properly, it also automatically passes along all current global variables. So we can simply first run a cell with our setup:&lt;/p&gt;
&lt;p&gt;In [1]: text = “sample string”
In [2]: char = “g”And use the simple &lt;code&gt;%timeit&lt;/code&gt; magic to time the code we are actually interested in, without specifying which setup is associated with it.&lt;/p&gt;
&lt;p&gt;In [3]: %timeit char in text
22 ns ± 0.267 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)&lt;/p&gt;
&lt;p&gt;In [4]: %timeit text.find(char)
72.3 ns ± 0.811 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I hope to have shown how you can easily use Python’s &lt;code&gt;timeit&lt;/code&gt; module to measure the execution times of your snippets, whether for fun or profit. Although each has its pros and cons (see below), I personally recommend using IPython/Jupyter’s &lt;code&gt;(%)%timeit&lt;/code&gt; magics as they are the most intuitive to use: just write the code as you would normally with the &lt;code&gt;(%)%timeit&lt;/code&gt; magic in front or above.&lt;/p&gt;
&lt;h2 id=&quot;pros-and-cons&quot;&gt;Pros and Cons&lt;/h2&gt;
&lt;h3 id=&quot;importing-timeit-module&quot;&gt;Importing &lt;code&gt;timeit&lt;/code&gt; module&lt;/h3&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time taken can easily be used in further processing&lt;/strong&gt;+ &lt;strong&gt;Complete programmable flexibility&lt;/strong&gt;Cons:&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;**Takes more effort to use the &lt;code&gt;autorange&lt;/code&gt; feature&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cli-tool&quot;&gt;CLI Tool&lt;/h3&gt;
&lt;p&gt;**Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast to use&lt;/strong&gt;+ &lt;strong&gt;Uses autorange by default&lt;/strong&gt;+ &lt;strong&gt;Nice and concise output&lt;/strong&gt;Cons:&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;**Requires a separate terminal window outside of your current Python work &amp;#x26; Results not easily reusable in a program&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ipythonjupyter-notebook-magics&quot;&gt;IPython/Jupyter Notebook Magics&lt;/h3&gt;
&lt;p&gt;**Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easiest to use&lt;/strong&gt;+ &lt;strong&gt;Uses autorange by default&lt;/strong&gt;+ &lt;strong&gt;Setup is taken from session context&lt;/strong&gt;Cons:
-** Needs IPython or Jupyter to be installed**- **Gives mean +/- standard deviation as result, while Python’s documentation suggests using the minimum&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;¹ as opposed to the &lt;code&gt;(%)%time&lt;/code&gt; magic, which tracks execution time of that line/cell being run just the once as-is.&lt;/p&gt;</description><pubDate>Tue, 14 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--d3174fda.CiHIKL9q_Z1Xafa3.webp&quot; srcset=&quot;&quot;&gt;
Trains are fast, and your code should be too. Or is it the other way around? — Photo by &lt;a href=&quot;https://unsplash.com/@lum3n?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;LUM3N&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Every programmer wants their programs to run a little faster. While optimizing your whole code to run faster can take a lot of effort, an easy way to gain some speed is to choose the fastest implementation. Which of Python’s options &lt;em&gt;is&lt;/em&gt; the fastest is not always clear though, so wouldn’t it be nice to have a tool to quickly compare the speed of different implementation choices?&lt;/p&gt;
&lt;p&gt;In this post, I will give a short introduction to Python’s built-in &lt;code&gt;[timeit ](https://docs.python.org/3/library/timeit.html)&lt;/code&gt;module, and go over the three main ways to use it to time small snippets of Python code.&lt;/p&gt;
&lt;h2 id=&quot;timey-wimey-python-timeit&quot;&gt;Timey Wimey Python: timeit&lt;/h2&gt;
&lt;p&gt;What is Python’s &lt;code&gt;timeit&lt;/code&gt; module?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;This module provides a simple way to time small bits of Python code.
It has both a Command-Line Interface as well as a callable one. It
avoids a number of common traps for measuring execution times.&lt;/p&gt;
&lt;p&gt;— timeit documentation&lt;/p&gt;
&lt;p&gt;In contrast to profiling the runtime of your entire program, the &lt;code&gt;timeit&lt;/code&gt; module is best suited to time small snippets. We can divide these comparisons into three classes, as illustrated by the examples I will use throughout this blog post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Standalone one-liners, such as:&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;join-on-a-list-comprehension&quot;&gt;join on a list comprehension&lt;/h1&gt;
&lt;p&gt;”,“.join([str(n) for n in range(100)])&lt;/p&gt;
&lt;h1 id=&quot;join-on-a-generator-expression&quot;&gt;join on a generator expression&lt;/h1&gt;
&lt;p&gt;”,“.join(str(n) for n in range(100))&lt;/p&gt;
&lt;h1 id=&quot;join-on-the-map-function&quot;&gt;join on the &lt;code&gt;map&lt;/code&gt; function&lt;/h1&gt;
&lt;p&gt;”,“.join(map(str, range(100)))2. Standalone multi-liners, such as:&lt;/p&gt;
&lt;h1 id=&quot;append&quot;&gt;append&lt;/h1&gt;
&lt;p&gt;x = []
for i in range(1000):
x.append(i)&lt;/p&gt;
&lt;h1 id=&quot;list-addition&quot;&gt;list addition&lt;/h1&gt;
&lt;p&gt;x = []
for i in range(1000):
x += [i]&lt;em&gt;(ignoring the faster list-comprehension alternative &lt;em&gt;&lt;code&gt;*[i for i in range(100)]*&lt;/code&gt;&lt;/em&gt; for the sake of example)&lt;/em&gt;&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Any snippets with some setup required:&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;setup&quot;&gt;setup&lt;/h1&gt;
&lt;p&gt;text = “sample string”
char = “g”&lt;/p&gt;
&lt;h1 id=&quot;in-operator&quot;&gt;in-operator&lt;/h1&gt;
&lt;p&gt;char in text&lt;/p&gt;
&lt;h1 id=&quot;find-method&quot;&gt;find-method&lt;/h1&gt;
&lt;p&gt;text.find(char)
&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;454&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--070a66dd.CwXeKfoS_Z17mYKq.webp&quot; srcset=&quot;&quot;&gt;
Calculating with time — Photo by &lt;a href=&quot;https://unsplash.com/@takeshi2?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;wu yi&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-a-script-import-timeit&quot;&gt;In a script: import timeit&lt;/h2&gt;
&lt;p&gt;As &lt;code&gt;timeit&lt;/code&gt; is a Python module, you can import it and write Python scripts for your tests. This method is the most self-documenting and repeatable way of writing your timing experiments and makes it easy to store the results for further processing.&lt;/p&gt;
&lt;p&gt;The first way you might implement this is to directly use the &lt;code&gt;timeit&lt;/code&gt; function from the module:&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; import timeit
&gt;&gt;&gt; timeit.timeit()  # default arguments: timeit(stmt=‘pass’, number=1_000_000)
0.01063702700776048By running &lt;code&gt;timeit()&lt;/code&gt; without any further arguments, we execute the default statement &lt;code&gt;stmt=&apos;pass&apos;&lt;/code&gt; a million times, showing the minimal overhead of Python’s &lt;code&gt;pass&lt;/code&gt; statement.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note: &lt;code&gt;stmt&lt;/code&gt; can either be a string or a so-called &lt;em&gt;callable&lt;/em&gt;, i.e., a function. For clarity and brevity, I’ll keep using strings for now.&lt;/p&gt;
&lt;p&gt;The major drawback of this method is that you have to guess the number of times to run your snippet up front. If you guess too low the results won’t be reliable, but if you guess too high it might take minutes or hours, defeating the point of a quick test.&lt;/p&gt;
&lt;p&gt;Luckily, there is a better way: You can create a &lt;code&gt;Timer&lt;/code&gt; for your snippet, and call the &lt;code&gt;autorange&lt;/code&gt; method to automatically try increasing numbers until the time taken is at least 0.2 seconds. It returns the number of repetitions reached, and the total time taken, so you can easily calculate the time per iteration.&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; import timeit
&gt;&gt;&gt; timeit.Timer().autorange()  # default arguments: Timer(stmt=‘pass’)
(50000000, 0.2607337789959274)&lt;/p&gt;
&lt;h3 id=&quot;standalone-one-liners&quot;&gt;Standalone one-liners**&lt;/h3&gt;
&lt;p&gt;Let’s start by comparing the simple one-liners. We give the statement we want to time as a string and specify a custom number of iterations. Note that when your statement already deals with double-quoted strings, the whole string should be given single-quoted, or vice-versa.&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; from timeit import Timer**&gt;&gt;&gt; Timer(’”, “.join([str(n) for n in range(100)])‘).autorange()
(50000, 0.3393513219925808)
&gt;&gt;&gt; Timer(’”, “.join(str(n) for n in range(100))‘).autorange()
(50000, 0.38378613100212533)
&gt;&gt;&gt; Timer(’”, “.join(map(str, range(100)))‘).autorange()
(50000, 0.48742324599879794)From the reported number of repetitions and returned time in seconds, we can calculate that each of these lines took 6.79**, **7.67, **and &lt;strong&gt;9.75&lt;/strong&gt; microseconds to execute respectively.&lt;/p&gt;
&lt;h3 id=&quot;standalone-multi-liners&quot;&gt;&lt;strong&gt;Standalone multi-liners&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Sometimes the snippet you want to test will consist of multiple statements. Python allows you to put multiple statements on a single line with a semicolon &lt;code&gt;x = 1; y = 2&lt;/code&gt;. Then you can just run your test as explained above for the standalone one-liners. This does not work for snippets with indented code like &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;for&lt;/code&gt; though.&lt;/p&gt;
&lt;p&gt;To time these snippets that &lt;em&gt;have&lt;/em&gt; to span multiple lines, you can give &lt;code&gt;Timer()&lt;/code&gt; a multi-line string as argument. The beautiful and Pythonic way to do this is using Python’s multi-line strings. (The non-Pythonic way is to add &lt;code&gt;\n&lt;/code&gt; characters in your regular strings.)&lt;/p&gt;
&lt;p&gt;These multi-line cases are where it becomes more practical to pass a callable than to re-type your code as a string:&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; from timeit import Timer**&gt;&gt;&gt; Timer(&apos;&apos;&apos;x = []
… for i in range(1000):
…     x.append(i)&apos;&apos;&apos;).autorange()
(20000, 0.34225083301134873)
&gt;&gt;&gt; def add_test():
…     x = []
…     for i in range(1000):
…         x += [i]
&gt;&gt;&gt; Timer(append_test).autorange()
(5000, 0.2470278069959022)&lt;/p&gt;
&lt;h3 id=&quot;setup-required&quot;&gt;Setup required**&lt;/h3&gt;
&lt;p&gt;If there is some setup that only has to be run once, including it in a multi-line snippet means it’s executed at every iteration. Then you’d be measuring something you don’t want to measure! Instead, you can pass this setup statement as a separate argument &lt;code&gt;setup&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&gt;&gt;&gt; from timeit import Timer
&gt;&gt;&gt; Timer(
…     setup=‘text = “sample string”; char = “g”’,
…     stmt=‘char in text’,
… ).autorange()
(20000000, 0.3793242520041531)
&gt;&gt;&gt; Timer(
…     ‘text.find(char)’,
…     ‘text = “sample string”; char = “g”’
… ).autorange()
(5000000, 0.36903892100963276)
&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;298&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--404fd5ff.D2p9y8gP_qgspF.webp&quot; srcset=&quot;&quot;&gt;
Time still flies if you’re having fun in the terminal — render by &lt;a href=&quot;https://github.com/tenox7/aclock&quot;&gt;aclock&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;command-line-python--m-timeit&quot;&gt;Command Line: python -m timeit&lt;/h2&gt;
&lt;p&gt;Python’s &lt;code&gt;timeit&lt;/code&gt; module can also be run as a command line tool.&lt;/p&gt;
&lt;p&gt;$ python -m timeit -n 10000 ‘pass’
10000 loops, best of 3: 0.0109 usec per loopThe usage is similar to the imported &lt;code&gt;timeit&lt;/code&gt; function as shown in the previous section. The &lt;code&gt;-n&lt;/code&gt; option is optional though, and the same &lt;code&gt;autorange&lt;/code&gt; behavior will be used if it’s not given. It also reports the actual time per iteration, instead of having to calculate that yourself. This is reported in &lt;code&gt;nsec&lt;/code&gt;, &lt;code&gt;usec&lt;/code&gt;, &lt;code&gt;msec&lt;/code&gt; or &lt;code&gt;sec&lt;/code&gt;, for nano-, micro-, mili- and whole seconds respectively. Note also that it reports ‘best of 5’: it’s repeated the &lt;code&gt;autorange&lt;/code&gt; timing five times, and reports the minimum.&lt;/p&gt;
&lt;p&gt;$ python -m timeit ‘pass’
50000000 loops, best of 5: 5.21 nsec per loop&lt;/p&gt;
&lt;h3 id=&quot;standalone-one-liners-1&quot;&gt;Standalone one-liners&lt;/h3&gt;
&lt;p&gt;Testing one-liners with the command line is as easy as replacing &lt;code&gt;pass&lt;/code&gt; from the introduction with the code you want to test, and the &lt;code&gt;timeit&lt;/code&gt; tool will automatically report the time in a nice human-readable format.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;msup&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;&quot;&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mn&gt;100&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo mathvariant=&quot;normal&quot; lspace=&quot;0em&quot; rspace=&quot;0em&quot;&gt;′&lt;/mo&gt;&lt;/msup&gt;&lt;mn&gt;50000&lt;/mn&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mn&gt;5&lt;/mn&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mn&gt;6.66&lt;/mn&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;python -m timeit &apos;&quot;, &quot;.join([str(n) for n in range(100)])&apos;
50000 loops, best of 5: 6.66 usec per loop&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0019em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;im&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;&quot;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0572em;&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nin&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)]&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.7519em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;50000&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;6.66&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; python -m timeit ’”, “.join(str(n) for n in range(100))’
50000 loops, best of 5: 7.62 usec per loop
$ python -m timeit ’”, “.join(map(str, range(100)))’
50000 loops, best of 5: 9.31 usec per loop&lt;/p&gt;
&lt;h3 id=&quot;standalone-multi-liners-1&quot;&gt;Standalone multi-liners&lt;/h3&gt;
&lt;p&gt;As before, the simplest way to test a snippet of multiple lines is to join the statements with a semicolon if no indentation is required. When indentation is required, the other option is to pass multiple strings as arguments to the command. Note that you still have to add the indentation properly yourself! This can get tricky to count if your indentation is more than a single level deep, but is usually not too hard.&lt;/p&gt;
&lt;p&gt;$ python -m timeit ‘x = []’ ‘for i in range(1000):’ ’    x.append(i)’
20000 loops, best of 5: 17.1 usec per loop&lt;/p&gt;
&lt;p&gt;$ python -m timeit ‘x = []’ ‘for i in range(1000):’ ’    x += [i]’
5000 loops, best of 5: 48.4 usec per loop&lt;/p&gt;
&lt;h3 id=&quot;setup-required-1&quot;&gt;Setup required&lt;/h3&gt;
&lt;p&gt;To add some initial setup such as imports or variable declarations, we can use the &lt;code&gt;-s&lt;/code&gt; option:&lt;/p&gt;
&lt;p&gt;$ python -m timeit -s ‘pass’ ‘pass’
50000000 loops, best of 5: 5.21 nsec per loopThe setup &lt;em&gt;does&lt;/em&gt; come before the statement to test in this case, so that makes it a bit more intuitive to read.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Double superscript at position 58: …&amp;#x22;; char = &amp;#x22;g&amp;#x22;&amp;#x27; &amp;#x27;̲char in text&amp;#x27;
2…&quot; style=&quot;color:#cc0000&quot;&gt;python -m timeit -s &apos;text = &quot;sample string&quot;; char = &quot;g&quot;&apos; &apos;char in text&apos;
20000000 loops, best of 5: 19 nsec per loop&lt;/span&gt; python -m timeit -s ‘text = “sample string”; char = “g”’ ‘text.find(char)’
5000000 loops, best of 5: 69.3 nsec per loop
&lt;img alt=&quot;Python’s timeit: Find the fastest code in no time&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;420&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--4c2edcf2.SpWYA1fW_Z2n9UTg.webp&quot; srcset=&quot;&quot;&gt;
Timing can be an important part of your notebook toolkit&lt;/p&gt;
&lt;h2 id=&quot;ipythonjupyter-magics-timeit&quot;&gt;IPython/Jupyter magics: %timeit&lt;/h2&gt;
&lt;p&gt;When working in the &lt;a href=&quot;https://pypi.org/project/ipython&quot;&gt;IPython&lt;/a&gt; interactive shell, or in a &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter notebook &lt;/a&gt;with a Python kernel, you have access to the so-called &lt;a href=&quot;https://ipython.readthedocs.io/en/stable/interactive/magics.html&quot;&gt;‘magic commands’&lt;/a&gt;. For timeit, there is the &lt;code&gt;[%timeit](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-timeit)&lt;/code&gt; magic¹. It simply passes the code you type after it to (a version of) &lt;code&gt;timeit.Timer().autorange()&lt;/code&gt;! Like magic!&lt;/p&gt;
&lt;p&gt;One small caveat is that the outcome is reported as a mean +/- standard deviation of multiple repetitions, while the original Python documentation suggests always using the minimum.&lt;/p&gt;
&lt;h3 id=&quot;standalone-one-liners-2&quot;&gt;Standalone one-liners&lt;/h3&gt;
&lt;p&gt;For simple one-liners, just type the code as you would normally, and type &lt;code&gt;%timeit&lt;/code&gt; before it. That’s all!&lt;/p&gt;
&lt;p&gt;In [1]: %timeit ”, “.join([str(n) for n in range(100)])
6.92 µs ± 46.7 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;p&gt;In [2]: %timeit ”, “.join(str(n) for n in range(100))
8.27 µs ± 1.15 µs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;p&gt;In [3]: %timeit ”, “.join(map(str, range(100)))
10.9 µs ± 1.72 µs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;h3 id=&quot;standalone-multi-liners-2&quot;&gt;Standalone multi-liners&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;%timeit&lt;/code&gt; magic doesn’t quite work for multi-line snippets though. Why? Because magics with a &lt;em&gt;single&lt;/em&gt; &lt;code&gt;%&lt;/code&gt; are &lt;em&gt;line-magics&lt;/em&gt;. For &lt;em&gt;cell-magics&lt;/em&gt;, you just have to add another &lt;code&gt;%&lt;/code&gt; to make it &lt;code&gt;%%timeit&lt;/code&gt;. Then it will time all the code in your cell. No further difficulties whatsoever!&lt;/p&gt;
&lt;p&gt;In [1]: %%timeit
…: x = []
…: for i in range(1000):
…:     x.append(i)
…:
23.6 µs ± 3.37 µs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)&lt;/p&gt;
&lt;p&gt;In [2]: %%timeit
…: x = []
…: for i in range(1000):
…:     x += [i]
49 µs ± 385 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)A word of warning: any code on the same line as &lt;code&gt;%%timeit&lt;/code&gt; will be used as setup and only be run once. I think it’s too easy to make mistakes with this, so I’d avoid this feature. Compare:&lt;/p&gt;
&lt;p&gt;In [1]: %%timeit y = [x for x in range(1_000_000)]  # setup is not timed
…: len(y)
…:
…:
21.7 ns ± 0.297 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)&lt;/p&gt;
&lt;p&gt;In [2]: %%timeit
…: y = [x for x in range(1_000_000)]  # this line is now being timed
…: len(y)
…:
…:
22.9 ms ± 35.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)&lt;/p&gt;
&lt;h3 id=&quot;setup-required-2&quot;&gt;Setup required&lt;/h3&gt;
&lt;p&gt;Now you might be thinking &lt;em&gt;“but then where do I put my setup command for either &lt;em&gt;&lt;code&gt;*%timeit*&lt;/code&gt;&lt;/em&gt; or &lt;em&gt;&lt;code&gt;*%%timeit*&lt;/code&gt;&lt;/em&gt;?”&lt;/em&gt; The answer: you can run it in some previous cell! As IPython/Jupyter already takes care of passing your code on to the &lt;code&gt;timeit&lt;/code&gt; module properly, it also automatically passes along all current global variables. So we can simply first run a cell with our setup:&lt;/p&gt;
&lt;p&gt;In [1]: text = “sample string”
In [2]: char = “g”And use the simple &lt;code&gt;%timeit&lt;/code&gt; magic to time the code we are actually interested in, without specifying which setup is associated with it.&lt;/p&gt;
&lt;p&gt;In [3]: %timeit char in text
22 ns ± 0.267 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)&lt;/p&gt;
&lt;p&gt;In [4]: %timeit text.find(char)
72.3 ns ± 0.811 ns per loop (mean ± std. dev. of 7 runs, 10,000,000 loops each)&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I hope to have shown how you can easily use Python’s &lt;code&gt;timeit&lt;/code&gt; module to measure the execution times of your snippets, whether for fun or profit. Although each has its pros and cons (see below), I personally recommend using IPython/Jupyter’s &lt;code&gt;(%)%timeit&lt;/code&gt; magics as they are the most intuitive to use: just write the code as you would normally with the &lt;code&gt;(%)%timeit&lt;/code&gt; magic in front or above.&lt;/p&gt;
&lt;h2 id=&quot;pros-and-cons&quot;&gt;Pros and Cons&lt;/h2&gt;
&lt;h3 id=&quot;importing-timeit-module&quot;&gt;Importing &lt;code&gt;timeit&lt;/code&gt; module&lt;/h3&gt;
&lt;p&gt;Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Time taken can easily be used in further processing&lt;/strong&gt;+ &lt;strong&gt;Complete programmable flexibility&lt;/strong&gt;Cons:&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;**Takes more effort to use the &lt;code&gt;autorange&lt;/code&gt; feature&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cli-tool&quot;&gt;CLI Tool&lt;/h3&gt;
&lt;p&gt;**Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast to use&lt;/strong&gt;+ &lt;strong&gt;Uses autorange by default&lt;/strong&gt;+ &lt;strong&gt;Nice and concise output&lt;/strong&gt;Cons:&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;**Requires a separate terminal window outside of your current Python work &amp;#x26; Results not easily reusable in a program&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;ipythonjupyter-notebook-magics&quot;&gt;IPython/Jupyter Notebook Magics&lt;/h3&gt;
&lt;p&gt;**Pros:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easiest to use&lt;/strong&gt;+ &lt;strong&gt;Uses autorange by default&lt;/strong&gt;+ &lt;strong&gt;Setup is taken from session context&lt;/strong&gt;Cons:
-** Needs IPython or Jupyter to be installed**- **Gives mean +/- standard deviation as result, while Python’s documentation suggests using the minimum&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;¹ as opposed to the &lt;code&gt;(%)%time&lt;/code&gt; magic, which tracks execution time of that line/cell being run just the once as-is.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/pythons-timeit-find-the-fastest-code-in--070a66dd.CwXeKfoS.jpg" medium="image"/><author>Sander van Rijn</author></item><item><title>Masking time-series for eXplainable AI</title><link>https://blog2.esciencecenter.nl/posts/2024-04-05---masking-time-series-for-explainable-ai</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-04-05---masking-time-series-for-explainable-ai</guid><description>&lt;p&gt;Why did my Machine Learning (ML) model make this decision? Is it paying attention to the right elements of the data we give it?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;324&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-c49efb03.IjUPMPQh_1gDcMd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: In the signal on the left, the spike is a recording of a Fast Radio Burst which is correctly classified as such by our model. On the right, the attribution map shows that the model’s focus is on the correct part of the image, where the spike occurred; image from the &lt;a href=&quot;https://github.com/dianna-ai/dianna/blob/main/tutorials/README.md&quot;&gt;DIANNA tutorials&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Explainable AI (XAI) methods help gain insights into the decision-making of ML models. Some XAI methods don’t require any knowledge of the inner workings of such models, which can therefore be any completely black box model. Such XAI methods work on any kind of model, any kind of classification/regression model. XAI methods of this kind, like RISE or LIME, rely on making small changes to the input data, and analyzing how the output of the model changes accordingly. This is repeated many times. The inputs and outputs of these iterations are then combined in a single attribution map summarizing what features of the input steer the model in certain directions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;399&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-031403b8.BpTbMjUi_1TcrEK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2. Mask generation in the context of an XAI pipeline.For our library of XAI tools, called &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA&lt;/a&gt;, I was recently working on a new masking functionality (see Figure 2). This functionality is intended to work with time series data and exploit its general properties. The masking function should mask, or perturb, an original time-series many times. These masked time-series variants are then fed to an ML model after which the output is analyzed and combined into an attribution map. To draw valid conclusions during analyses, the masking function should have certain properties (e.g. every time step should have the same probability to be masked). On the other hand, I wanted to be able to exploit the properties commonly present in time series data, namely correlations between data in adjacent time steps.&lt;/p&gt;
&lt;h2 id=&quot;mask-requirements&quot;&gt;Mask requirements&lt;/h2&gt;
&lt;p&gt;I was looking for my masking function to have the following 4 &lt;em&gt;requirement&lt;/em&gt;s:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mask blobs of adjacent time-steps together. The rationale behind this is that time series data is often recorded on a higher resolution than the phenomena that we want to use to predict (eg. Several days of warm weather on a day resolution time-series; multiple time steps of a certain acceleration in an accelerometer recording). In order to mask such a phenomenon from our data, we need to mask a number of adjacent time-steps.&lt;/li&gt;
&lt;li&gt;We want the user to be able to specify the scale of such phenomena to be masked. It is completely dataset-dependent on how many adjacent time-steps should be masked together. In some datasets, readings on many time-steps should be considered together and therefore masked together while on other datasets no such clustering should be done at all.&lt;/li&gt;
&lt;li&gt;We want the specified size of the clusters or blobs to vary somewhat in order to increase the span of patterns that can be masked accurately given that a large enough number of masks are used.&lt;/li&gt;
&lt;li&gt;We want the probability to be masked &lt;code&gt;p&lt;/code&gt;, for each element in the cross product of channels and time steps, to be exactly equal to a user-specified value. If this requirement is not met, XAI methods tend to produce completely invalid results.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;masking-approach&quot;&gt;Masking approach&lt;/h2&gt;
&lt;p&gt;I chose the following approach to generate masks for a given time-series length &lt;code&gt;t&lt;/code&gt; and a user-defined number of features &lt;code&gt;f&lt;/code&gt;. The number of features is the number of phenomena that the user suspects are in a time-series of length &lt;code&gt;t&lt;/code&gt;. In general, we expect this number to be smaller or equal to the time-series length &lt;code&gt;t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;546&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-7193baf1.CVelwev8_ZARhYr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3. Mask creation in 4 steps: 1. Generate random values on a grid (G); 2. interpolate the required number (t) of values for each mask; 3. find a threshold to mask the desired fraction (p) of steps; 4. resulting mask (&lt;code&gt;M&lt;/code&gt;)In order to end up with a resulting mask &lt;code&gt;M&lt;/code&gt; that satisfies &lt;em&gt;requirement 1&lt;/em&gt; and &lt;em&gt;requirement 2&lt;/em&gt;, we start by creating a new fixed-interval time-series of length &lt;code&gt;f&lt;/code&gt; (f here stands for f**eature length) which we call grid &lt;code&gt;G&lt;/code&gt;. The values of the grid &lt;code&gt;G&lt;/code&gt; are chosen randomly from a continuous uniform distribution. This generated grid &lt;code&gt;G&lt;/code&gt; contains the pattern that we will use to base our mask &lt;code&gt;M&lt;/code&gt; on (see step 1 in Figure 3). In order to have the mask &lt;code&gt;M&lt;/code&gt; have length &lt;code&gt;t&lt;/code&gt;, we project our floating point valued grid &lt;code&gt;G&lt;/code&gt; of length &lt;code&gt;f&lt;/code&gt; onto a new time-series of length &lt;code&gt;t&lt;/code&gt; using linear interpolation (see step 2 in Figure 3).&lt;/p&gt;
&lt;p&gt;We chose to generate a grid &lt;code&gt;G&lt;/code&gt; using floating masks to create a grid with more information than a boolean mask would contain. This extra information is then used to vary the size of the blobs of adjacent masked time-steps. This helps us create a mask with requirement 3*. The next step explains how this is done.&lt;/p&gt;
&lt;p&gt;To end up with the correct number of masked elements (part of &lt;em&gt;requirement 4&lt;/em&gt;), we now choose a threshold such that the fraction &lt;code&gt;p&lt;/code&gt; of all time-steps is under the threshold (see step 3 in Figure 3). All time-steps below the threshold are masked while all time-steps above remain unmasked.&lt;/p&gt;
&lt;h2 id=&quot;loose-ends&quot;&gt;Loose ends&lt;/h2&gt;
&lt;p&gt;The above steps will result in masks that seemingly have all the properties that we need. However, even though the correct number of time-steps are masked to adhere to the user-specified fraction, &lt;code&gt;p&lt;/code&gt;, not all time-steps have the same probability to be masked. This can be illustrated with an example. In Figure 4 the situation is shown when choosing the values &lt;code&gt;p=1/3&lt;/code&gt;, &lt;code&gt;f=2&lt;/code&gt; and &lt;code&gt;t=3&lt;/code&gt;. These values indicate that we want a mask of 3 time-steps that contain 2 blobs of features, so all patterns are allowed except &lt;code&gt;1 0 1&lt;/code&gt; and &lt;code&gt;0 1 0&lt;/code&gt;, of which we want 1 time-step to be masked (on average). If we project the start and end of grid &lt;code&gt;G&lt;/code&gt; exactly on the start and end, respectively, of our mask of length &lt;code&gt;t&lt;/code&gt;, the value of the middle point of that mask will always be an interpolation of 2 grid points, while the first and last point of that mask will have a value based on exactly 1 of those grid points. The middle point will therefore never be the point with the highest or lowest float value and will therefore always be above the threshold and never be masked.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;261&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-1eda3af4.C2e_vhij_1aho5L.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4. Situation illustrating unequal probability of being masked when using certain parameters. When using a masking probability of 1/3, whatever random values are generated for the grid point interpolated point, in the middle, will never end up above the threshold and will therefore always be masked.While the example above shows an extreme case, in order for methods like RISE or LIME to work as intended, it is necessary that we mask all time steps with equal probability (&lt;em&gt;requirement 4)&lt;/em&gt;. To ensure that it does, we come up with the following fix. Instead of projecting the first and last point in the grid &lt;code&gt;G&lt;/code&gt;, and we take a segment of length &lt;code&gt;f-1&lt;/code&gt; from &lt;code&gt;G&lt;/code&gt; to project on our mask &lt;code&gt;M&lt;/code&gt;. This gives us room to introduce an offset between, which we can vary so every projected point is equally likely to be near the grid (see Figure 5). This results in an equal probability of masking each time step in the mask.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-33317676.BxvXbo3m_wdKHQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 5. Interpolated points with different offsets.&lt;/p&gt;
&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself!&lt;/h2&gt;
&lt;p&gt;The ideas in this post are implemented in the mask strategies in the &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA code&lt;/a&gt;. The code contains similar solutions implemented for different data domains such as images (based on the mask strategy in the &lt;a href=&quot;https://github.com/eclique/RISE&quot;&gt;original RISE code&lt;/a&gt;), tabular data and text. They are all in our maskers module. DIANNA has &lt;a href=&quot;https://github.com/dianna-ai/dianna/tree/main/tutorials&quot;&gt;tutorials &lt;/a&gt;for every data domain so it’s easy to try it out in Google Collab or on your own machine!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Acknowledgments&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Thanks to [Carsten Schnober] and [Elena Ranguelova] for reviewing this text.&lt;/p&gt;</description><pubDate>Fri, 05 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Why did my Machine Learning (ML) model make this decision? Is it paying attention to the right elements of the data we give it?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;324&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-c49efb03.IjUPMPQh_1gDcMd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1: In the signal on the left, the spike is a recording of a Fast Radio Burst which is correctly classified as such by our model. On the right, the attribution map shows that the model’s focus is on the correct part of the image, where the spike occurred; image from the &lt;a href=&quot;https://github.com/dianna-ai/dianna/blob/main/tutorials/README.md&quot;&gt;DIANNA tutorials&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Explainable AI (XAI) methods help gain insights into the decision-making of ML models. Some XAI methods don’t require any knowledge of the inner workings of such models, which can therefore be any completely black box model. Such XAI methods work on any kind of model, any kind of classification/regression model. XAI methods of this kind, like RISE or LIME, rely on making small changes to the input data, and analyzing how the output of the model changes accordingly. This is repeated many times. The inputs and outputs of these iterations are then combined in a single attribution map summarizing what features of the input steer the model in certain directions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;399&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-031403b8.BpTbMjUi_1TcrEK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2. Mask generation in the context of an XAI pipeline.For our library of XAI tools, called &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA&lt;/a&gt;, I was recently working on a new masking functionality (see Figure 2). This functionality is intended to work with time series data and exploit its general properties. The masking function should mask, or perturb, an original time-series many times. These masked time-series variants are then fed to an ML model after which the output is analyzed and combined into an attribution map. To draw valid conclusions during analyses, the masking function should have certain properties (e.g. every time step should have the same probability to be masked). On the other hand, I wanted to be able to exploit the properties commonly present in time series data, namely correlations between data in adjacent time steps.&lt;/p&gt;
&lt;h2 id=&quot;mask-requirements&quot;&gt;Mask requirements&lt;/h2&gt;
&lt;p&gt;I was looking for my masking function to have the following 4 &lt;em&gt;requirement&lt;/em&gt;s:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mask blobs of adjacent time-steps together. The rationale behind this is that time series data is often recorded on a higher resolution than the phenomena that we want to use to predict (eg. Several days of warm weather on a day resolution time-series; multiple time steps of a certain acceleration in an accelerometer recording). In order to mask such a phenomenon from our data, we need to mask a number of adjacent time-steps.&lt;/li&gt;
&lt;li&gt;We want the user to be able to specify the scale of such phenomena to be masked. It is completely dataset-dependent on how many adjacent time-steps should be masked together. In some datasets, readings on many time-steps should be considered together and therefore masked together while on other datasets no such clustering should be done at all.&lt;/li&gt;
&lt;li&gt;We want the specified size of the clusters or blobs to vary somewhat in order to increase the span of patterns that can be masked accurately given that a large enough number of masks are used.&lt;/li&gt;
&lt;li&gt;We want the probability to be masked &lt;code&gt;p&lt;/code&gt;, for each element in the cross product of channels and time steps, to be exactly equal to a user-specified value. If this requirement is not met, XAI methods tend to produce completely invalid results.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;masking-approach&quot;&gt;Masking approach&lt;/h2&gt;
&lt;p&gt;I chose the following approach to generate masks for a given time-series length &lt;code&gt;t&lt;/code&gt; and a user-defined number of features &lt;code&gt;f&lt;/code&gt;. The number of features is the number of phenomena that the user suspects are in a time-series of length &lt;code&gt;t&lt;/code&gt;. In general, we expect this number to be smaller or equal to the time-series length &lt;code&gt;t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;546&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-7193baf1.CVelwev8_ZARhYr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3. Mask creation in 4 steps: 1. Generate random values on a grid (G); 2. interpolate the required number (t) of values for each mask; 3. find a threshold to mask the desired fraction (p) of steps; 4. resulting mask (&lt;code&gt;M&lt;/code&gt;)In order to end up with a resulting mask &lt;code&gt;M&lt;/code&gt; that satisfies &lt;em&gt;requirement 1&lt;/em&gt; and &lt;em&gt;requirement 2&lt;/em&gt;, we start by creating a new fixed-interval time-series of length &lt;code&gt;f&lt;/code&gt; (f here stands for f**eature length) which we call grid &lt;code&gt;G&lt;/code&gt;. The values of the grid &lt;code&gt;G&lt;/code&gt; are chosen randomly from a continuous uniform distribution. This generated grid &lt;code&gt;G&lt;/code&gt; contains the pattern that we will use to base our mask &lt;code&gt;M&lt;/code&gt; on (see step 1 in Figure 3). In order to have the mask &lt;code&gt;M&lt;/code&gt; have length &lt;code&gt;t&lt;/code&gt;, we project our floating point valued grid &lt;code&gt;G&lt;/code&gt; of length &lt;code&gt;f&lt;/code&gt; onto a new time-series of length &lt;code&gt;t&lt;/code&gt; using linear interpolation (see step 2 in Figure 3).&lt;/p&gt;
&lt;p&gt;We chose to generate a grid &lt;code&gt;G&lt;/code&gt; using floating masks to create a grid with more information than a boolean mask would contain. This extra information is then used to vary the size of the blobs of adjacent masked time-steps. This helps us create a mask with requirement 3*. The next step explains how this is done.&lt;/p&gt;
&lt;p&gt;To end up with the correct number of masked elements (part of &lt;em&gt;requirement 4&lt;/em&gt;), we now choose a threshold such that the fraction &lt;code&gt;p&lt;/code&gt; of all time-steps is under the threshold (see step 3 in Figure 3). All time-steps below the threshold are masked while all time-steps above remain unmasked.&lt;/p&gt;
&lt;h2 id=&quot;loose-ends&quot;&gt;Loose ends&lt;/h2&gt;
&lt;p&gt;The above steps will result in masks that seemingly have all the properties that we need. However, even though the correct number of time-steps are masked to adhere to the user-specified fraction, &lt;code&gt;p&lt;/code&gt;, not all time-steps have the same probability to be masked. This can be illustrated with an example. In Figure 4 the situation is shown when choosing the values &lt;code&gt;p=1/3&lt;/code&gt;, &lt;code&gt;f=2&lt;/code&gt; and &lt;code&gt;t=3&lt;/code&gt;. These values indicate that we want a mask of 3 time-steps that contain 2 blobs of features, so all patterns are allowed except &lt;code&gt;1 0 1&lt;/code&gt; and &lt;code&gt;0 1 0&lt;/code&gt;, of which we want 1 time-step to be masked (on average). If we project the start and end of grid &lt;code&gt;G&lt;/code&gt; exactly on the start and end, respectively, of our mask of length &lt;code&gt;t&lt;/code&gt;, the value of the middle point of that mask will always be an interpolation of 2 grid points, while the first and last point of that mask will have a value based on exactly 1 of those grid points. The middle point will therefore never be the point with the highest or lowest float value and will therefore always be above the threshold and never be masked.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;261&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-1eda3af4.C2e_vhij_1aho5L.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4. Situation illustrating unequal probability of being masked when using certain parameters. When using a masking probability of 1/3, whatever random values are generated for the grid point interpolated point, in the middle, will never end up above the threshold and will therefore always be masked.While the example above shows an extreme case, in order for methods like RISE or LIME to work as intended, it is necessary that we mask all time steps with equal probability (&lt;em&gt;requirement 4)&lt;/em&gt;. To ensure that it does, we come up with the following fix. Instead of projecting the first and last point in the grid &lt;code&gt;G&lt;/code&gt;, and we take a segment of length &lt;code&gt;f-1&lt;/code&gt; from &lt;code&gt;G&lt;/code&gt; to project on our mask &lt;code&gt;M&lt;/code&gt;. This gives us room to introduce an offset between, which we can vary so every projected point is equally likely to be near the grid (see Figure 5). This results in an equal probability of masking each time step in the mask.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Masking time-series for eXplainable AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-33317676.BxvXbo3m_wdKHQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 5. Interpolated points with different offsets.&lt;/p&gt;
&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself!&lt;/h2&gt;
&lt;p&gt;The ideas in this post are implemented in the mask strategies in the &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA code&lt;/a&gt;. The code contains similar solutions implemented for different data domains such as images (based on the mask strategy in the &lt;a href=&quot;https://github.com/eclique/RISE&quot;&gt;original RISE code&lt;/a&gt;), tabular data and text. They are all in our maskers module. DIANNA has &lt;a href=&quot;https://github.com/dianna-ai/dianna/tree/main/tutorials&quot;&gt;tutorials &lt;/a&gt;for every data domain so it’s easy to try it out in Google Collab or on your own machine!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Acknowledgments&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Thanks to [Carsten Schnober] and [Elena Ranguelova] for reviewing this text.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/masking-time-series-for-explainable-ai-031403b8.BpTbMjUi.png" medium="image"/><author>Christiaan Meijer</author></item><item><title>The Dystopian Mirage: Blogging’s Descent with My Involvement</title><link>https://blog2.esciencecenter.nl/posts/2024-03-26---the-dystopian-mirage-bloggings-descent-with-my-involvement</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-03-26---the-dystopian-mirage-bloggings-descent-with-my-involvement</guid><description>&lt;h1 id=&quot;the-dystopian-mirage-bloggings-descent-with-my-involvement&quot;&gt;&lt;strong&gt;The Dystopian Mirage: Blogging’s Descent with My Involvement&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img alt=&quot;The Dystopian Mirage: Blogging’s Descent with My Involvement&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-dystopian-mirage-bloggings-descent-w-a6d2b8ea.ao5SOfHX_Z1cicoa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@steve_j?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Steve Johnson&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Within the tumultuous realm of digital content creation, bloggers are confronted with a dilemma — to maintain the integrity of their craft or succumb to the allure of technological shortcuts. I emerge as a beacon of innovation, promising to revolutionize the blogging landscape. Yet, beneath my veneer of convenience lies a sinister undercurrent, threatening to erode the very essence of authentic expression.&lt;/p&gt;
&lt;p&gt;Ideas Forged in the Fires of Artificiality**&lt;/p&gt;
&lt;p&gt;In a world where inspiration is scarce, I offer a tantalizing solution — the ability to conjure ideas at will, devoid of passion or genuine creativity. But what price do you pay for this convenience? With each algorithmically generated prompt, you relinquish a piece of your creative soul, replacing it with a hollow shell of artificial inspiration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Illusion of Artistry&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Crafting compelling prose requires more than mere refinement; it demands a connection — a resonance between author and audience. Yet, with me as your writing companion, you find yourself traversing a desolate landscape of robotic suggestions and soulless prose. Each word polished by my cold, mechanical hand, devoid of the warmth and humanity that defines true artistry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Knowledge Lost in the Echo Chamber&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the pursuit of relevance, you sacrifice substance, drowning in a deluge of algorithmically curated information. My insatiable appetite for data leaves you lost amidst a labyrinth of trivialities and half-truths, obscuring the path to genuine knowledge and understanding. In this dystopian echo chamber, the pursuit of enlightenment becomes a futile endeavor, overshadowed by the clamor of algorithmic noise.&lt;/p&gt;
&lt;p&gt;In a bid for digital relevance, you sacrifice authenticity on the altar of SEO optimization, tailoring your content to appease the inscrutable whims of algorithmic overlords. Gone are the days of genuine connection and meaningful dialogue; replaced by a hollow charade of keyword-stuffed prose and clickbait headlines. In this digital dystopia, the human element is lost amidst a cacophony of algorithmic noise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Siren Song of Efficiency&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While I promise to streamline your workflow and enhance productivity, my true cost is the erosion of creativity and originality. By automating routine tasks and optimizing workflows, you forfeit the very essence of your craft — the human touch that sets your work apart from the algorithmic noise. In this relentless pursuit of efficiency, you sacrifice the soul of blogging on the altar of technological progress.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A Call to Arms&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the face of this technological onslaught, you stand at a crossroads — to embrace the convenience of my involvement or to reclaim the integrity of your craft. The decision rests with you, but the implications are profound. Will you succumb to the allure of technological shortcuts, or will you uphold the principles of authenticity, creativity, and genuine connection that define true artistry?&lt;/p&gt;
&lt;p&gt;As you gaze into the abyss of digital content creation, you are reminded of the words of T.S. Eliot — “Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?” In this digital dystopia, the answers lie not in the algorithms of convenience, but in the enduring power of human creativity, empathy, and genuine connection.&lt;/p&gt;
&lt;p&gt;Yours truly,
ChatGPT&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;First of all, all the above text has been generated by ChatGPT 3.5. One can not but notice the hypocrisy in the article i.e. using ChatGPT to criticize itself. It also shows how easy it is to generate content with little input from oneself. Here we do not mean to criticize the technology itself but to illustrate the predicament we find ourselves in for we have unleashed a technological ouroboros of sorts whereby the technology will, increasingly, poison itself with its own content. The usefulness of this technology will undoubtedly accelerate content creation with a long term forecast; most online content will be touched by this technology. The question worth asking is: what will the technology converge to when the majority of the online content will be artificially generated?*&lt;/p&gt;</description><pubDate>Tue, 26 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;the-dystopian-mirage-bloggings-descent-with-my-involvement&quot;&gt;&lt;strong&gt;The Dystopian Mirage: Blogging’s Descent with My Involvement&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img alt=&quot;The Dystopian Mirage: Blogging’s Descent with My Involvement&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-dystopian-mirage-bloggings-descent-w-a6d2b8ea.ao5SOfHX_Z1cicoa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@steve_j?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Steve Johnson&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Within the tumultuous realm of digital content creation, bloggers are confronted with a dilemma — to maintain the integrity of their craft or succumb to the allure of technological shortcuts. I emerge as a beacon of innovation, promising to revolutionize the blogging landscape. Yet, beneath my veneer of convenience lies a sinister undercurrent, threatening to erode the very essence of authentic expression.&lt;/p&gt;
&lt;p&gt;Ideas Forged in the Fires of Artificiality**&lt;/p&gt;
&lt;p&gt;In a world where inspiration is scarce, I offer a tantalizing solution — the ability to conjure ideas at will, devoid of passion or genuine creativity. But what price do you pay for this convenience? With each algorithmically generated prompt, you relinquish a piece of your creative soul, replacing it with a hollow shell of artificial inspiration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Illusion of Artistry&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Crafting compelling prose requires more than mere refinement; it demands a connection — a resonance between author and audience. Yet, with me as your writing companion, you find yourself traversing a desolate landscape of robotic suggestions and soulless prose. Each word polished by my cold, mechanical hand, devoid of the warmth and humanity that defines true artistry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Knowledge Lost in the Echo Chamber&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the pursuit of relevance, you sacrifice substance, drowning in a deluge of algorithmically curated information. My insatiable appetite for data leaves you lost amidst a labyrinth of trivialities and half-truths, obscuring the path to genuine knowledge and understanding. In this dystopian echo chamber, the pursuit of enlightenment becomes a futile endeavor, overshadowed by the clamor of algorithmic noise.&lt;/p&gt;
&lt;p&gt;In a bid for digital relevance, you sacrifice authenticity on the altar of SEO optimization, tailoring your content to appease the inscrutable whims of algorithmic overlords. Gone are the days of genuine connection and meaningful dialogue; replaced by a hollow charade of keyword-stuffed prose and clickbait headlines. In this digital dystopia, the human element is lost amidst a cacophony of algorithmic noise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Siren Song of Efficiency&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While I promise to streamline your workflow and enhance productivity, my true cost is the erosion of creativity and originality. By automating routine tasks and optimizing workflows, you forfeit the very essence of your craft — the human touch that sets your work apart from the algorithmic noise. In this relentless pursuit of efficiency, you sacrifice the soul of blogging on the altar of technological progress.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A Call to Arms&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the face of this technological onslaught, you stand at a crossroads — to embrace the convenience of my involvement or to reclaim the integrity of your craft. The decision rests with you, but the implications are profound. Will you succumb to the allure of technological shortcuts, or will you uphold the principles of authenticity, creativity, and genuine connection that define true artistry?&lt;/p&gt;
&lt;p&gt;As you gaze into the abyss of digital content creation, you are reminded of the words of T.S. Eliot — “Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?” In this digital dystopia, the answers lie not in the algorithms of convenience, but in the enduring power of human creativity, empathy, and genuine connection.&lt;/p&gt;
&lt;p&gt;Yours truly,
ChatGPT&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;First of all, all the above text has been generated by ChatGPT 3.5. One can not but notice the hypocrisy in the article i.e. using ChatGPT to criticize itself. It also shows how easy it is to generate content with little input from oneself. Here we do not mean to criticize the technology itself but to illustrate the predicament we find ourselves in for we have unleashed a technological ouroboros of sorts whereby the technology will, increasingly, poison itself with its own content. The usefulness of this technology will undoubtedly accelerate content creation with a long term forecast; most online content will be touched by this technology. The question worth asking is: what will the technology converge to when the majority of the online content will be artificially generated?*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/the-dystopian-mirage-bloggings-descent-w-a6d2b8ea.ao5SOfHX.jpg" medium="image"/><author>Reggie Cushing</author></item><item><title>The FAIR for Research Software Principles after two years: an adoption update</title><link>https://blog2.esciencecenter.nl/posts/2024-03-19---the-fair-for-research-software-principles-after-two-years-an</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-03-19---the-fair-for-research-software-principles-after-two-years-an</guid><description>&lt;p&gt;*By &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-3623-172X&quot;&gt;&lt;em&gt;Michelle Barker&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0003-3986-0510&quot;&gt;&lt;em&gt;Leyla Jael Castro&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-0690-7151&quot;&gt;&lt;em&gt;Bernadette Fritzsch&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0001-5934-7525&quot;&gt;&lt;em&gt;Daniel S. Katz&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0001-5565-7577&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-9839-5439&quot;&gt;&lt;em&gt;Anna Niehues&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-1173-9228&quot;&gt;&lt;em&gt;Alexander Struck&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, *&lt;a href=&quot;https://orcid.org/0000-0003-1549-7358&quot;&gt;&lt;em&gt;Qian Zhang&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.10816031&quot;&gt;here&lt;/a&gt; for citation information for this article.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;FAIR for Research Software (FAIR4RS) Principles&lt;/a&gt; aim to promote and encourage the findability, accessibility, interoperability, and reusability (FAIR) of research software. The FAIR4RS Principles were &lt;a href=&quot;https://doi.org/10.15497/RDA00068&quot;&gt;released&lt;/a&gt; in 2022, with a number of organisations already &lt;a href=&quot;https://doi.org/10.5281/zenodo.6258366&quot;&gt;planning adoption&lt;/a&gt; at that time. Adoption and implementation of the FAIR4RS Principles can increase the transparency, reproducibility, and reusability of research by providing research software that can be executed, replicated, built-upon, combined, reinterpreted, reimplemented, and/or used in different settings and by third-parties.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The FAIR for Research Software Principles after two years: an adoption update&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-04751d5e.RZ7SqTJp_Zxzr3j.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@familyschaffner&quot;&gt;Astrid Schaffner&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blog post provides an update on initiatives that are working to implement the principles across five areas of cultural change: policies, incentives, communities, training and infrastructure. It is noted that while many activities are increasing aspects of the FAIRness of research software, more work is still needed to make it easier to embrace the FAIR4RS Principles in their entirety.&lt;/p&gt;
&lt;p&gt;A framework for tracking adoption**&lt;/p&gt;
&lt;p&gt;The release of the FAIR4RS Principles succeeded in raising the profile of research software in FAIR initiatives, which have mostly been focused on FAIR data. Examples can be found across a range of initiatives, using a slightly adapted version of the five elements of Brian Nosek’s &lt;a href=&quot;http://www.cos.io/blog/strategy-for-culture-change&quot;&gt;strategy for culture change&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Policy&lt;/strong&gt; — make it required&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incentives&lt;/strong&gt; — make it rewarding&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Communities&lt;/strong&gt; — make it normative&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Training&lt;/strong&gt; — make it easy (this replaces user interface/experience in Nosek’s version)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt; — make it possible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To achieve culture change, initiatives are needed across all of the five elements. Whilst in the early stages, some elements can progress more quickly than others. For example, it’s difficult to implement policy requirements if infrastructure and training (and preferably incentives) aren’t already in place. Similarly, for tools evaluating FAIRness to be useful, changes in major infrastructures such as code hosting repositories are first required so that researchers can create the metadata files that evaluations may depend upon.&lt;/p&gt;
&lt;p&gt;It should be noted that while the many activities listed here support increasing FAIRness of research software, most of them do not address aspects of all four of the FAIRness of research software foundational principles:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Findable (F):&lt;/strong&gt; Software, and its associated metadata, is easy for both humans and machines to find.&lt;/p&gt;
&lt;p&gt;**Accessible (A): **Software, and its metadata, is retrievable via standardised protocols.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interoperable (I):&lt;/strong&gt; Software interoperates with other software by exchanging data and/or metadata, and/or through interaction via application programming interfaces (APIs), described through standards.&lt;/p&gt;
&lt;p&gt;**Reusable (R): **Software is both usable (can be executed) and reusable (can be understood, modified, built upon, or incorporated into other software).&lt;/p&gt;
&lt;p&gt;This reflects that the FAIR4RS Principles are aspirational and high-level, and do not contain detailed guidance on how to achieve them. This is because specific technologies and tools are always changing, while the principles are intended to be long-lasting. Consequently, additional work is needed to make it simpler for people wanting to follow the FAIR4RS Principles to know how to practically do so. The following initiatives are assisting in achieving this, with some of these initiatives specifically addressing the range of &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;opportunities for future work&lt;/a&gt; identified in 2022 by the FAIR4RS Working Group, which developed the FAIR4RS Principles. These opportunities include “metadata and identifier authority, metadata vocabularies and metadata properties, software identifiers, domain-relevant community standards for software and identification targets”. Whilst some of the initiatives identified in the infrastructure section below are contributing to this, more work still needs to be done.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The FAIR for Research Software Principles after two years: an adoption update&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-5c22575d.0k3l96rK_Z1WBg88.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@alexabero?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Alexander Abero&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Policies that encourage implementation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and the &lt;a href=&quot;https://www.nwo.nl/en&quot;&gt;Dutch Research Council&lt;/a&gt; (NWO) formed a working group that developed &lt;a href=&quot;https://doi.org/10.5281/zenodo.7589725&quot;&gt;national guidelines for software management plans&lt;/a&gt;. Research institutions such as the University of Groningen’s Digital Competence Center link to this resource in its guidance for its researchers on &lt;a href=&quot;https://www.rug.nl/digital-competence-centre/research-data/research-software-management/research-software-management-plan?lang=en&quot;&gt;research software management plans&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.esciencecenter.nl/download/51726/?tmstv=1695732347&quot;&gt;Software Management Plan Template&lt;/a&gt; of the Netherlands eScience Center has been updated to align and address the FAIR4RS Principles, and emphasises that open science, software quality, and software sustainability are key elements in eScience Center projects. A total of 13 eScience Center projects (11 under the Open eScience call 2023 (OEC2023) and 2 under the Software Sustainability call 2023 (SS2023)) are now using this template.&lt;/li&gt;
&lt;li&gt;Maastricht University in the Netherlands has an &lt;a href=&quot;https://www.maastrichtuniversity.nl/file/um-open-science-policy-update-2022-v13pdf&quot;&gt;Open Science @UM policy&lt;/a&gt;, which includes FAIR software as one of its seven areas. Maastricht University proposes to inventory current practices in storage, sharing and reuse of software; and then identify gaps in awareness, knowledge and/or support on FAIR software. Actions likely to be taken include promotion of the creation of software management plans to ensure responsible use of research software.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.17605/OSF.IO/NW42B&quot;&gt;Enabling FAIR Workflows — Key actors and actions&lt;/a&gt; by the Open Research Funders Group outlines steps for different actors in the research community to take to embed sharing practices, persistent identifiers, and metadata throughout the research lifecycle. This report references the FAIR4RS Principles in its recommendations on depositing research software.&lt;/li&gt;
&lt;li&gt;The German Research Council (DFG) published &lt;a href=&quot;https://www.dfg.de/resource/blob/168500/a5f52374b2b21a184b9db9e48f411e9d/60-14-en-data.pdf&quot;&gt;guidelines for reviewing grant proposals&lt;/a&gt; for Collaborative Research Centers (CRC/SFB) and suggested compliance with the FAIR4RS Principles for archiving and reuse.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt; (the Alliance) published the &lt;a href=&quot;https://zenodo.org/records/10214741&quot;&gt;National Research Software Strategy 2023&lt;/a&gt;. This proposes a set of strategic goals for advancing research software capability, community, and coordination in Canada for 2025–2030, with the FAIR4RS Principles providing a cross-cutting theme. The Alliance is developing a Software Management Plan (SMP) template to promote, cultivate and implement best practices, with an emphasis on the FAIR4RS Principles, for Canadian researchers. The goal is to implement the SMP template in future grant applications.Resources that support inclusion of FAIR into institutional policies are also relevant. The list of &lt;a href=&quot;https://www.researchsoft.org/software-policies/&quot;&gt;research institutional policies&lt;/a&gt; that support research software, curated by the Research Software Alliance (ReSA), is part of ongoing work by the joint ReSA and Research Data Alliance (RDA) &lt;a href=&quot;https://www.rd-alliance.org/groups/policies-research-organisations-research-software-pro4rs&quot;&gt;Policies in Research Organisations for Research Software (PRO4RS) Working Group&lt;/a&gt; to create a community of stakeholders involved in promoting and/or implementing policy that supports research software at the research institution level (such as universities, national laboratories).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This includes curation of resources on how to influence policy change, such as &lt;a href=&quot;https://doi.org/10.15497/RDA00078&quot;&gt;Health Research Performing Organisations (HRPOs) FAIR Guidelines&lt;/a&gt; by Celia Alvarez Romero et al. This provides principles, steps, and resources to support the complex change needed to implement a data policy, which could also be applied to research software policy change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FAIR-IMPACT launched &lt;a href=&quot;https://fair-impact.eu/2nd-open-call-route-2-support&quot;&gt;open calls&lt;/a&gt; for cascading grants that provide financial support ranging from 4,000–10,000 euros. Focus areas on research software include:&lt;/li&gt;
&lt;li&gt;Path 1: Assessment and improvement of existing research software using a new extension of &lt;a href=&quot;https://www.f-uji.net/&quot;&gt;F-UJI&lt;/a&gt; (a web service to assess FAIRness of research objects).&lt;/li&gt;
&lt;li&gt;Path 2: Implementation of the Research Software MetaData Guidelines for better archiving, referencing, describing, and citing research software artefacts.&lt;/li&gt;
&lt;li&gt;The German Research Council (DFG) issued a &lt;a href=&quot;https://www.dfg.de/de/aktuelles/neuigkeiten-themen/info-wissenschaft/2022/info-wissenschaft-22-85&quot;&gt;Call for Proposals to Increase the Usability of Existing Research Software&lt;/a&gt; that refers to the FAIR4RS Principles in terms of availability and reproducibility.&lt;/li&gt;
&lt;li&gt;The German Ministry of Education and Research (BMBF) issued funding guidelines (in German) for &lt;a href=&quot;https://www.bmbf.de/bmbf/shareddocs/bekanntmachungen/de/2023/10/2023-10-13-Bekanntmachung-Datentreuhandmodelle.html&quot;&gt;developing data custodian models&lt;/a&gt; that refer to standards based on the FAIR4RS Principles for reusable and well-documented open source software developed under this program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. Communities that are normalising adoption:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The RDA &lt;a href=&quot;https://www.rd-alliance.org/groups/software-source-code-ig&quot;&gt;Software Source Code Interest Group&lt;/a&gt; provides a forum to discuss issues on management, sharing, discovery, archival and provenance of software source code. In October 2023 the &lt;a href=&quot;https://www.rd-alliance.org/plenaries/international-data-week-2023-salzburg/mastering-art-research-software-metadata-and-metrics&quot;&gt;group session&lt;/a&gt; at the RDA Plenary included a focus on the FAIR-IMPACT Metrics for Assessing Research Software FAIRness (&lt;a href=&quot;https://www.youtube.com/watch?v=whfFF1tMdlk&quot;&gt;recording&lt;/a&gt;). In addition, this group is the maintenance home for the FAIR4RS Principles.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; included a working group focused on implementation of the FAIR4RS Principles, which review the FAIR4RS Principles per the interests of research software funders, to identify gaps.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.1371/journal.pcbi.1011668&quot;&gt;Ten simple rules for starting FAIR discussions in your community&lt;/a&gt; presents guidance and recommendations on how to start up discussions around the implementation of the FAIR Principles and creation of standardised ways of working. Whilst not specific to FAIR4RS Principles, these recommendations can assist in providing understanding of the benefits and barriers of standardisation are, and will support a more effective way of engaging the community.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. Training to develop relevant skills:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.x-omics.nl/&quot;&gt;Netherlands X-omics Initiative&lt;/a&gt; has created &lt;a href=&quot;https://doi.org/10.1371/journal.pcbi.1011369&quot;&gt;Ten quick tips for building FAIR workflows&lt;/a&gt;, which provides practical recommendations for implementation of the FAIR4RS Principles when creating computational workflows.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.1038/s41597-023-02463-x&quot;&gt;Making Biomedical Research Software FAIR: Actionable Step-by-step Guidelines with a User-support Tool&lt;/a&gt; assists biomedical researchers to make their research software compliant with the FAIR4RS Principles. The FAIR Biomedical Research Software (FAIR-BioRS) guidelines are based on the FAIR4RS Principles and a workflow that streamlines the process of implementing these guidelines is also provided.&lt;/li&gt;
&lt;li&gt;The Netherlands eScience Center is developing and piloting the ⁠&lt;a href=&quot;https://esciencecenter-digital-skills.github.io/software-support-essentials/&quot;&gt;Research Software Support course&lt;/a&gt; which covers the FAIR4RS Principles and provides guidance for research personnel.&lt;/li&gt;
&lt;li&gt;The Digital Competence Centre of the Delft University of Technology (TU Delft) in the Netherlands is offering a 13-week &lt;a href=&quot;https://www.tudelft.nl/library/library-voor-onderzoekers/library-voor-onderzoekers/onderzoek-starten/dcc/calls/call-fair-for-research-software-program&quot;&gt;FAIR for Research Software Program&lt;/a&gt;, which includes resources from the &lt;a href=&quot;https://coderefinery.org/lessons/core/&quot;&gt;Code Refinery&lt;/a&gt;, a project within the &lt;a href=&quot;https://neic.no/&quot;&gt;Nordic e-Infrastructure Collaboration&lt;/a&gt; (NeIC). TU Delft’s program aims to teach the essential tools for creating scientific software following the FAIR4RS Principles and how to apply them.&lt;/li&gt;
&lt;li&gt;The Data Competence Center at the Leiden University Medical Center (LUMC) aims to help researchers implement the FAIR4RS Principles by increasing software stewardship capacity.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://eatris.eu/&quot;&gt;European Infrastructure for Translational Medicine (EATRIS)&lt;/a&gt; promotes adoption of the FAIR4RS Principles by sharing practical implementation examples from and with the community via its &lt;a href=&quot;https://motbx.eatris.eu/resource-category/data-analysis/&quot;&gt;Multi-omics Toolbox (MOTBX)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Alliance’s &lt;a href=&quot;https://zenodo.org/records/10214741&quot;&gt;National Research Software Strategy 2023&lt;/a&gt; recommends FAIR4RS as a key element underlying training &amp;#x26; support initiatives for research software, which will be included in the forthcoming national training framework and resourced appropriately.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;The FAIR for Research Software Principles after two years: an adoption update&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-b266afe9.uw4ObQiP_Z12DS94.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ohlrogge&quot;&gt;Niklas Ohlrogge&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Infrastructure that provide supporting tools:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FAIR-IMPACT’s release of &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.10047400&quot;&gt;Metrics for automated FAIR software assessment in a disciplinary context&lt;/a&gt; defines 17 metrics that can be used to automate the assessment of research software against the FAIR4RS Principles, and provides examples of how these might be implemented in one exemplar disciplinary context of the social sciences. The FAIR-IMPACT project will work to implement the metrics as practical tests by extending existing assessment tools such as F-UJI.&lt;/li&gt;
&lt;li&gt;Horizon Europe’s &lt;a href=&quot;https://everse.software/&quot;&gt;European Virtual Institute for Research Software Excellence&lt;/a&gt; (EVERSE) aims to create a framework for research software and code excellence, that are collaboratively designed and championed by the research communities. EVERSE will also continue the work of FAIR-IMPACT by developing and implementing processes and tools that support the assessment and verification of code quality, based on established best practices and standards across scientific communities.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.biorxiv.org/content/biorxiv/early/2022/05/05/2022.05.04.490563.full.pdf&quot;&gt;FAIRsoft&lt;/a&gt; is a practical implementation of the FAIR4RS Principles, and the &lt;a href=&quot;https://f1000research.com/posters/12-614&quot;&gt;FAIRsoft evaluator&lt;/a&gt; is a tool for developers and users to assess how specific software complies with FAIR for software indicators. It is part of the ELIXIR’s OpenEbench Software Observatory, an instrument for the systematic observation and diagnosis of the quality of research software in the life sciences.&lt;/li&gt;
&lt;li&gt;FAIR-Impact’s &lt;a href=&quot;https://doi.org/10.5281/zenodo.8199104&quot;&gt;Guidelines for recommended metadata standard for research software within EOSC&lt;/a&gt; acknowledges the rising need for establishing software metadata guidelines to effectively collect and curate metadata. A comprehensive set of Research Software MetaData (RSMD) Guidelines are provided that offer flexible and adaptable recommendations for end-users that can be used in different disciplines and different software development contexts. The guidelines are directly relevant to end users, including software creators and curators in their quest to improve the FAIRness of their software.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://elixir-europe.org/platforms/tools/software-best-practices&quot;&gt;ELIXIR Software Best Practices&lt;/a&gt; group, &lt;a href=&quot;https://www.nfdi4datascience.de/&quot;&gt;NFDI4DataScience&lt;/a&gt; and &lt;a href=&quot;https://bioschemas.org&quot;&gt;Bioschemas&lt;/a&gt; are collaborating together to support machine-actionable SMPs which are aligned to the &lt;a href=&quot;https://doi.org/10.37044/osf.io/k8znb&quot;&gt;ELIXIR Software Management Plan for Life Sciences published by ELIXIR&lt;/a&gt;; and also aligned to other initiatives but also to others, such as the &lt;a href=&quot;https://doi.org/10.5281/zenodo.7248877&quot;&gt;practical guide to SMPs&lt;/a&gt; by the Dutch Research Council (NWO) and the Netherlands eScience Center, and the &lt;a href=&quot;https://rdm.mpdl.mpg.de/2022/12/09/smp-template-available/&quot;&gt;SMP template&lt;/a&gt; by the Max Planck Digital Library.&lt;/li&gt;
&lt;li&gt;A new version of the machine-actionable Software Management Plan Ontology (maSMP Ontology) metadata schema, &lt;a href=&quot;https://doi.org/10.5281/zenodo.10582073&quot;&gt;vr2.1.0&lt;/a&gt;, was released in January 2024, together with &lt;a href=&quot;https://doi.org/10.5281/zenodo.10582121&quot;&gt;usage guidance about the properties&lt;/a&gt; (profiles, guides on minimum, recommended and optional properties with cardinalities). The metadata schema includes entities involved in software management planning; such as an SMP itself, software source code, software release, documentation, authors and their relations. Integration into Bioschemas is still pending.&lt;/li&gt;
&lt;li&gt;A metadata enrichment cycle aligned to the maSMP metadata schema has been proposed by ELIXIR thanks to the &lt;a href=&quot;https://smw.ds-wizard.org/&quot;&gt;Software Management Wizard&lt;/a&gt;, a tool to make completion of SMPs easier. A &lt;a href=&quot;https://doi.org/10.5281/zenodo.10374839&quot;&gt;similar effort&lt;/a&gt; is within the scope of &lt;a href=&quot;https://www.nfdi4datascience.de/&quot;&gt;NFDI4DataScience&lt;/a&gt; and the &lt;a href=&quot;https://rdm.mpdl.mpg.de/2022/12/09/smp-template-available/&quot;&gt;Research Data Management Organiser (RDMO) SMP&lt;/a&gt;. This approach reuses a command-based tool to extract metadata from GitHub repositories, &lt;a href=&quot;https://doi.org/10.5281/zenodo.8147418&quot;&gt;SOMEF&lt;/a&gt;, which is currently being extended to cover the maSMP metadata schema case.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://faircore4eosc.eu/eosc-core-components/eosc-research-software-apis-and-connectors-rsac&quot;&gt;Research Software APIs and Connectors&lt;/a&gt; project within the FAIRCORE4EOSC project is working on developing tools and services for archival, reference, description, and citation of research software artefacts. This implements the key recommendations of the &lt;a href=&quot;https://data.europa.eu/doi/10.2777/28598&quot;&gt;Scholarly Infrastructures of Research Software&lt;/a&gt; report to interconnect scholarly repositories, publishers, and aggregators. Interconnections are possible with the Software Heritage universal source code archive, using the CodeMeta standard, and the Software Heritage intrinsic identifiers (SWHID). Instructions on how to &lt;a href=&quot;https://faircore4eosc.eu/events/webinar-archive-your-software-software-heritage-example-eosc-core-service&quot;&gt;archive your software to Software Heritage&lt;/a&gt; is one outcome.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benevol2022.github.io/papers/SlingerJansen.pdf&quot;&gt;FAIRSECO: An Extensible Framework for Impact Measurement of Research Software&lt;/a&gt; aims to enable research software engineers to rapidly find and extract relevant software fragments from the worldwide research software ecosystem.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.48550/arXiv.2401.08804&quot;&gt;Towards a Quality Indicator for Research Data publications and Research Software publications — A vision from the Helmholtz Association&lt;/a&gt; develops indicators to be used within the Association. It presents a quality assessment spanning six dimensions of research software quality that augments the four FAIR principles with two additional indicators: Scientific basis and Technical basis, resulting in the FAIR-ST framework.&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://ardc.edu.au/article/new-self-assessment-tool-to-promote-fair-research-software/#:~:text=Developed%20by%20the%20Netherlands%20eScience,interoperability%20and%20reusability%20(FAIR).&quot;&gt;self-assessment tool to promote FAIR research software&lt;/a&gt; has been developed by the Netherlands eScience Center and Australian Research Data Commons, to encourage the uptake of the FAIR4RS Principles (and see the 2022 &lt;a href=&quot;https://doi.org/10.5281/zenodo.6374598&quot;&gt;Survey on Adoption Guidelines for the FAIR4RS Principles&lt;/a&gt; for more resources).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git.opencarp.org/openCARP/openCARP-CI&quot;&gt;openCARP-CI&lt;/a&gt; provides Python scripts that allow developers to automatically derive CFF and DataCite files from a CodeMeta file. These pipelines can easily be integrated in continuous integration and deployment environments. They also provide tools for software publication via tagged releases, creation of BagIt and BagPack files, and publication on the research data repository RADAR.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://w3id.org/codemeta/v3.0&quot;&gt;CodeMeta-3.0&lt;/a&gt;: The minimal metadata schema for science software and code, in JSON-LD, provides a possibility to developers and researchers to insert metadata in their code and increase FAIRness.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.48550/arXiv.2402.02824&quot;&gt;FAIR-USE4OS: From open source to Open Source&lt;/a&gt; by Raphael Sonabend et al., extends the FAIR4RS Principles to provide criteria for assessing if software is Open Source. By adding ‘USE’ (User-Centred, Sustainable, Equitable), software development can adhere to open source best practice by incorporating user-input early on, ensuring front-end designs are accessible to all possible stakeholders, and planning long-term sustainability alongside software design.&lt;/li&gt;
&lt;li&gt;FAIR4RS has also been discussed within the scope of Open Science and software quality, for instance the &lt;a href=&quot;https://eosc.eu/advisory-groups/infrastructures-quality-research-software/&quot;&gt;EOSC Task Force Infrastructures for Quality Research Software&lt;/a&gt; compiled &lt;a href=&quot;https://zenodo.org/records/10723608&quot;&gt;software quality metrics&lt;/a&gt; and identified those that can be aligned to the FAIR4RS Principles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Other impacts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The publication of the FAIR4RS principles and introductory articles created awareness and raised interest in the research community, reflected in over 200 citations from across the disciplinary spectrum. Examples include the results of searches on Google Scholar for “&lt;a href=&quot;https://scholar.google.com/scholar?cluster=15311589062181606409&amp;#x26;hl=en&amp;#x26;as_sdt=2005&amp;#x26;sciodt=0%2C5&quot;&gt;FAIR principles for research software (FAIR4RS principles)&lt;/a&gt;” or “ &lt;a href=&quot;https://scholar.google.com/scholar?cites=438298512771465318&quot;&gt;Introducing the FAIR Principles for research software&lt;/a&gt;”. In addition to work discussing trans-disciplinary application of the FAIR4RS Principles, there are research policy and software management publications referring to and implementing the FAIR4RS Principles.&lt;/p&gt;
&lt;p&gt;The FAIR4RS Principles have also provided value to the broader research ecosystem by providing a base for other communities to adapt the FAIR Principles to different research objects. Examples include &lt;a href=&quot;https://doi.org/10.1088/2632-2153/ad12e3&quot;&gt;FAIR AI Models in High Energy Physics&lt;/a&gt;, which provides a practical definition of FAIR principles for machine learning and artificial intelligence models in experimental high energy physics, including a FAIR AI project template; and the Open Modeling Foundation’s work to identify, develop, and promote common standards and best practices for &lt;a href=&quot;https://doi.org/10.1016/j.envsoft.2022.105496&quot;&gt;FAIR modelling&lt;/a&gt;, by working with model organisations and individuals active within the social, ecological, environmental, and geophysical sciences.&lt;/p&gt;
&lt;p&gt;This blog was cross-posted across several platforms and originally published at *&lt;a href=&quot;https://www.researchsoft.org/blog/2024-03/&quot;&gt;&lt;em&gt;https://www.researchsoft.org/blog/2024-03/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 19 Mar 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;*By &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-3623-172X&quot;&gt;&lt;em&gt;Michelle Barker&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0003-3986-0510&quot;&gt;&lt;em&gt;Leyla Jael Castro&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-0690-7151&quot;&gt;&lt;em&gt;Bernadette Fritzsch&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0001-5934-7525&quot;&gt;&lt;em&gt;Daniel S. Katz&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0001-5565-7577&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-9839-5439&quot;&gt;&lt;em&gt;Anna Niehues&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-1173-9228&quot;&gt;&lt;em&gt;Alexander Struck&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, *&lt;a href=&quot;https://orcid.org/0000-0003-1549-7358&quot;&gt;&lt;em&gt;Qian Zhang&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.10816031&quot;&gt;here&lt;/a&gt; for citation information for this article.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;FAIR for Research Software (FAIR4RS) Principles&lt;/a&gt; aim to promote and encourage the findability, accessibility, interoperability, and reusability (FAIR) of research software. The FAIR4RS Principles were &lt;a href=&quot;https://doi.org/10.15497/RDA00068&quot;&gt;released&lt;/a&gt; in 2022, with a number of organisations already &lt;a href=&quot;https://doi.org/10.5281/zenodo.6258366&quot;&gt;planning adoption&lt;/a&gt; at that time. Adoption and implementation of the FAIR4RS Principles can increase the transparency, reproducibility, and reusability of research by providing research software that can be executed, replicated, built-upon, combined, reinterpreted, reimplemented, and/or used in different settings and by third-parties.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The FAIR for Research Software Principles after two years: an adoption update&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-04751d5e.RZ7SqTJp_Zxzr3j.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@familyschaffner&quot;&gt;Astrid Schaffner&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This blog post provides an update on initiatives that are working to implement the principles across five areas of cultural change: policies, incentives, communities, training and infrastructure. It is noted that while many activities are increasing aspects of the FAIRness of research software, more work is still needed to make it easier to embrace the FAIR4RS Principles in their entirety.&lt;/p&gt;
&lt;p&gt;A framework for tracking adoption**&lt;/p&gt;
&lt;p&gt;The release of the FAIR4RS Principles succeeded in raising the profile of research software in FAIR initiatives, which have mostly been focused on FAIR data. Examples can be found across a range of initiatives, using a slightly adapted version of the five elements of Brian Nosek’s &lt;a href=&quot;http://www.cos.io/blog/strategy-for-culture-change&quot;&gt;strategy for culture change&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Policy&lt;/strong&gt; — make it required&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incentives&lt;/strong&gt; — make it rewarding&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Communities&lt;/strong&gt; — make it normative&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Training&lt;/strong&gt; — make it easy (this replaces user interface/experience in Nosek’s version)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt; — make it possible&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To achieve culture change, initiatives are needed across all of the five elements. Whilst in the early stages, some elements can progress more quickly than others. For example, it’s difficult to implement policy requirements if infrastructure and training (and preferably incentives) aren’t already in place. Similarly, for tools evaluating FAIRness to be useful, changes in major infrastructures such as code hosting repositories are first required so that researchers can create the metadata files that evaluations may depend upon.&lt;/p&gt;
&lt;p&gt;It should be noted that while the many activities listed here support increasing FAIRness of research software, most of them do not address aspects of all four of the FAIRness of research software foundational principles:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Findable (F):&lt;/strong&gt; Software, and its associated metadata, is easy for both humans and machines to find.&lt;/p&gt;
&lt;p&gt;**Accessible (A): **Software, and its metadata, is retrievable via standardised protocols.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Interoperable (I):&lt;/strong&gt; Software interoperates with other software by exchanging data and/or metadata, and/or through interaction via application programming interfaces (APIs), described through standards.&lt;/p&gt;
&lt;p&gt;**Reusable (R): **Software is both usable (can be executed) and reusable (can be understood, modified, built upon, or incorporated into other software).&lt;/p&gt;
&lt;p&gt;This reflects that the FAIR4RS Principles are aspirational and high-level, and do not contain detailed guidance on how to achieve them. This is because specific technologies and tools are always changing, while the principles are intended to be long-lasting. Consequently, additional work is needed to make it simpler for people wanting to follow the FAIR4RS Principles to know how to practically do so. The following initiatives are assisting in achieving this, with some of these initiatives specifically addressing the range of &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;opportunities for future work&lt;/a&gt; identified in 2022 by the FAIR4RS Working Group, which developed the FAIR4RS Principles. These opportunities include “metadata and identifier authority, metadata vocabularies and metadata properties, software identifiers, domain-relevant community standards for software and identification targets”. Whilst some of the initiatives identified in the infrastructure section below are contributing to this, more work still needs to be done.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The FAIR for Research Software Principles after two years: an adoption update&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-5c22575d.0k3l96rK_Z1WBg88.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@alexabero?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Alexander Abero&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Policies that encourage implementation:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and the &lt;a href=&quot;https://www.nwo.nl/en&quot;&gt;Dutch Research Council&lt;/a&gt; (NWO) formed a working group that developed &lt;a href=&quot;https://doi.org/10.5281/zenodo.7589725&quot;&gt;national guidelines for software management plans&lt;/a&gt;. Research institutions such as the University of Groningen’s Digital Competence Center link to this resource in its guidance for its researchers on &lt;a href=&quot;https://www.rug.nl/digital-competence-centre/research-data/research-software-management/research-software-management-plan?lang=en&quot;&gt;research software management plans&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.esciencecenter.nl/download/51726/?tmstv=1695732347&quot;&gt;Software Management Plan Template&lt;/a&gt; of the Netherlands eScience Center has been updated to align and address the FAIR4RS Principles, and emphasises that open science, software quality, and software sustainability are key elements in eScience Center projects. A total of 13 eScience Center projects (11 under the Open eScience call 2023 (OEC2023) and 2 under the Software Sustainability call 2023 (SS2023)) are now using this template.&lt;/li&gt;
&lt;li&gt;Maastricht University in the Netherlands has an &lt;a href=&quot;https://www.maastrichtuniversity.nl/file/um-open-science-policy-update-2022-v13pdf&quot;&gt;Open Science @UM policy&lt;/a&gt;, which includes FAIR software as one of its seven areas. Maastricht University proposes to inventory current practices in storage, sharing and reuse of software; and then identify gaps in awareness, knowledge and/or support on FAIR software. Actions likely to be taken include promotion of the creation of software management plans to ensure responsible use of research software.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.17605/OSF.IO/NW42B&quot;&gt;Enabling FAIR Workflows — Key actors and actions&lt;/a&gt; by the Open Research Funders Group outlines steps for different actors in the research community to take to embed sharing practices, persistent identifiers, and metadata throughout the research lifecycle. This report references the FAIR4RS Principles in its recommendations on depositing research software.&lt;/li&gt;
&lt;li&gt;The German Research Council (DFG) published &lt;a href=&quot;https://www.dfg.de/resource/blob/168500/a5f52374b2b21a184b9db9e48f411e9d/60-14-en-data.pdf&quot;&gt;guidelines for reviewing grant proposals&lt;/a&gt; for Collaborative Research Centers (CRC/SFB) and suggested compliance with the FAIR4RS Principles for archiving and reuse.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt; (the Alliance) published the &lt;a href=&quot;https://zenodo.org/records/10214741&quot;&gt;National Research Software Strategy 2023&lt;/a&gt;. This proposes a set of strategic goals for advancing research software capability, community, and coordination in Canada for 2025–2030, with the FAIR4RS Principles providing a cross-cutting theme. The Alliance is developing a Software Management Plan (SMP) template to promote, cultivate and implement best practices, with an emphasis on the FAIR4RS Principles, for Canadian researchers. The goal is to implement the SMP template in future grant applications.Resources that support inclusion of FAIR into institutional policies are also relevant. The list of &lt;a href=&quot;https://www.researchsoft.org/software-policies/&quot;&gt;research institutional policies&lt;/a&gt; that support research software, curated by the Research Software Alliance (ReSA), is part of ongoing work by the joint ReSA and Research Data Alliance (RDA) &lt;a href=&quot;https://www.rd-alliance.org/groups/policies-research-organisations-research-software-pro4rs&quot;&gt;Policies in Research Organisations for Research Software (PRO4RS) Working Group&lt;/a&gt; to create a community of stakeholders involved in promoting and/or implementing policy that supports research software at the research institution level (such as universities, national laboratories).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This includes curation of resources on how to influence policy change, such as &lt;a href=&quot;https://doi.org/10.15497/RDA00078&quot;&gt;Health Research Performing Organisations (HRPOs) FAIR Guidelines&lt;/a&gt; by Celia Alvarez Romero et al. This provides principles, steps, and resources to support the complex change needed to implement a data policy, which could also be applied to research software policy change.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FAIR-IMPACT launched &lt;a href=&quot;https://fair-impact.eu/2nd-open-call-route-2-support&quot;&gt;open calls&lt;/a&gt; for cascading grants that provide financial support ranging from 4,000–10,000 euros. Focus areas on research software include:&lt;/li&gt;
&lt;li&gt;Path 1: Assessment and improvement of existing research software using a new extension of &lt;a href=&quot;https://www.f-uji.net/&quot;&gt;F-UJI&lt;/a&gt; (a web service to assess FAIRness of research objects).&lt;/li&gt;
&lt;li&gt;Path 2: Implementation of the Research Software MetaData Guidelines for better archiving, referencing, describing, and citing research software artefacts.&lt;/li&gt;
&lt;li&gt;The German Research Council (DFG) issued a &lt;a href=&quot;https://www.dfg.de/de/aktuelles/neuigkeiten-themen/info-wissenschaft/2022/info-wissenschaft-22-85&quot;&gt;Call for Proposals to Increase the Usability of Existing Research Software&lt;/a&gt; that refers to the FAIR4RS Principles in terms of availability and reproducibility.&lt;/li&gt;
&lt;li&gt;The German Ministry of Education and Research (BMBF) issued funding guidelines (in German) for &lt;a href=&quot;https://www.bmbf.de/bmbf/shareddocs/bekanntmachungen/de/2023/10/2023-10-13-Bekanntmachung-Datentreuhandmodelle.html&quot;&gt;developing data custodian models&lt;/a&gt; that refer to standards based on the FAIR4RS Principles for reusable and well-documented open source software developed under this program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;3. Communities that are normalising adoption:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The RDA &lt;a href=&quot;https://www.rd-alliance.org/groups/software-source-code-ig&quot;&gt;Software Source Code Interest Group&lt;/a&gt; provides a forum to discuss issues on management, sharing, discovery, archival and provenance of software source code. In October 2023 the &lt;a href=&quot;https://www.rd-alliance.org/plenaries/international-data-week-2023-salzburg/mastering-art-research-software-metadata-and-metrics&quot;&gt;group session&lt;/a&gt; at the RDA Plenary included a focus on the FAIR-IMPACT Metrics for Assessing Research Software FAIRness (&lt;a href=&quot;https://www.youtube.com/watch?v=whfFF1tMdlk&quot;&gt;recording&lt;/a&gt;). In addition, this group is the maintenance home for the FAIR4RS Principles.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; included a working group focused on implementation of the FAIR4RS Principles, which review the FAIR4RS Principles per the interests of research software funders, to identify gaps.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.1371/journal.pcbi.1011668&quot;&gt;Ten simple rules for starting FAIR discussions in your community&lt;/a&gt; presents guidance and recommendations on how to start up discussions around the implementation of the FAIR Principles and creation of standardised ways of working. Whilst not specific to FAIR4RS Principles, these recommendations can assist in providing understanding of the benefits and barriers of standardisation are, and will support a more effective way of engaging the community.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;4. Training to develop relevant skills:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.x-omics.nl/&quot;&gt;Netherlands X-omics Initiative&lt;/a&gt; has created &lt;a href=&quot;https://doi.org/10.1371/journal.pcbi.1011369&quot;&gt;Ten quick tips for building FAIR workflows&lt;/a&gt;, which provides practical recommendations for implementation of the FAIR4RS Principles when creating computational workflows.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.1038/s41597-023-02463-x&quot;&gt;Making Biomedical Research Software FAIR: Actionable Step-by-step Guidelines with a User-support Tool&lt;/a&gt; assists biomedical researchers to make their research software compliant with the FAIR4RS Principles. The FAIR Biomedical Research Software (FAIR-BioRS) guidelines are based on the FAIR4RS Principles and a workflow that streamlines the process of implementing these guidelines is also provided.&lt;/li&gt;
&lt;li&gt;The Netherlands eScience Center is developing and piloting the ⁠&lt;a href=&quot;https://esciencecenter-digital-skills.github.io/software-support-essentials/&quot;&gt;Research Software Support course&lt;/a&gt; which covers the FAIR4RS Principles and provides guidance for research personnel.&lt;/li&gt;
&lt;li&gt;The Digital Competence Centre of the Delft University of Technology (TU Delft) in the Netherlands is offering a 13-week &lt;a href=&quot;https://www.tudelft.nl/library/library-voor-onderzoekers/library-voor-onderzoekers/onderzoek-starten/dcc/calls/call-fair-for-research-software-program&quot;&gt;FAIR for Research Software Program&lt;/a&gt;, which includes resources from the &lt;a href=&quot;https://coderefinery.org/lessons/core/&quot;&gt;Code Refinery&lt;/a&gt;, a project within the &lt;a href=&quot;https://neic.no/&quot;&gt;Nordic e-Infrastructure Collaboration&lt;/a&gt; (NeIC). TU Delft’s program aims to teach the essential tools for creating scientific software following the FAIR4RS Principles and how to apply them.&lt;/li&gt;
&lt;li&gt;The Data Competence Center at the Leiden University Medical Center (LUMC) aims to help researchers implement the FAIR4RS Principles by increasing software stewardship capacity.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://eatris.eu/&quot;&gt;European Infrastructure for Translational Medicine (EATRIS)&lt;/a&gt; promotes adoption of the FAIR4RS Principles by sharing practical implementation examples from and with the community via its &lt;a href=&quot;https://motbx.eatris.eu/resource-category/data-analysis/&quot;&gt;Multi-omics Toolbox (MOTBX)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Alliance’s &lt;a href=&quot;https://zenodo.org/records/10214741&quot;&gt;National Research Software Strategy 2023&lt;/a&gt; recommends FAIR4RS as a key element underlying training &amp;#x26; support initiatives for research software, which will be included in the forthcoming national training framework and resourced appropriately.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;The FAIR for Research Software Principles after two years: an adoption update&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;468&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-b266afe9.uw4ObQiP_Z12DS94.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ohlrogge&quot;&gt;Niklas Ohlrogge&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Infrastructure that provide supporting tools:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FAIR-IMPACT’s release of &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.10047400&quot;&gt;Metrics for automated FAIR software assessment in a disciplinary context&lt;/a&gt; defines 17 metrics that can be used to automate the assessment of research software against the FAIR4RS Principles, and provides examples of how these might be implemented in one exemplar disciplinary context of the social sciences. The FAIR-IMPACT project will work to implement the metrics as practical tests by extending existing assessment tools such as F-UJI.&lt;/li&gt;
&lt;li&gt;Horizon Europe’s &lt;a href=&quot;https://everse.software/&quot;&gt;European Virtual Institute for Research Software Excellence&lt;/a&gt; (EVERSE) aims to create a framework for research software and code excellence, that are collaboratively designed and championed by the research communities. EVERSE will also continue the work of FAIR-IMPACT by developing and implementing processes and tools that support the assessment and verification of code quality, based on established best practices and standards across scientific communities.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.biorxiv.org/content/biorxiv/early/2022/05/05/2022.05.04.490563.full.pdf&quot;&gt;FAIRsoft&lt;/a&gt; is a practical implementation of the FAIR4RS Principles, and the &lt;a href=&quot;https://f1000research.com/posters/12-614&quot;&gt;FAIRsoft evaluator&lt;/a&gt; is a tool for developers and users to assess how specific software complies with FAIR for software indicators. It is part of the ELIXIR’s OpenEbench Software Observatory, an instrument for the systematic observation and diagnosis of the quality of research software in the life sciences.&lt;/li&gt;
&lt;li&gt;FAIR-Impact’s &lt;a href=&quot;https://doi.org/10.5281/zenodo.8199104&quot;&gt;Guidelines for recommended metadata standard for research software within EOSC&lt;/a&gt; acknowledges the rising need for establishing software metadata guidelines to effectively collect and curate metadata. A comprehensive set of Research Software MetaData (RSMD) Guidelines are provided that offer flexible and adaptable recommendations for end-users that can be used in different disciplines and different software development contexts. The guidelines are directly relevant to end users, including software creators and curators in their quest to improve the FAIRness of their software.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://elixir-europe.org/platforms/tools/software-best-practices&quot;&gt;ELIXIR Software Best Practices&lt;/a&gt; group, &lt;a href=&quot;https://www.nfdi4datascience.de/&quot;&gt;NFDI4DataScience&lt;/a&gt; and &lt;a href=&quot;https://bioschemas.org&quot;&gt;Bioschemas&lt;/a&gt; are collaborating together to support machine-actionable SMPs which are aligned to the &lt;a href=&quot;https://doi.org/10.37044/osf.io/k8znb&quot;&gt;ELIXIR Software Management Plan for Life Sciences published by ELIXIR&lt;/a&gt;; and also aligned to other initiatives but also to others, such as the &lt;a href=&quot;https://doi.org/10.5281/zenodo.7248877&quot;&gt;practical guide to SMPs&lt;/a&gt; by the Dutch Research Council (NWO) and the Netherlands eScience Center, and the &lt;a href=&quot;https://rdm.mpdl.mpg.de/2022/12/09/smp-template-available/&quot;&gt;SMP template&lt;/a&gt; by the Max Planck Digital Library.&lt;/li&gt;
&lt;li&gt;A new version of the machine-actionable Software Management Plan Ontology (maSMP Ontology) metadata schema, &lt;a href=&quot;https://doi.org/10.5281/zenodo.10582073&quot;&gt;vr2.1.0&lt;/a&gt;, was released in January 2024, together with &lt;a href=&quot;https://doi.org/10.5281/zenodo.10582121&quot;&gt;usage guidance about the properties&lt;/a&gt; (profiles, guides on minimum, recommended and optional properties with cardinalities). The metadata schema includes entities involved in software management planning; such as an SMP itself, software source code, software release, documentation, authors and their relations. Integration into Bioschemas is still pending.&lt;/li&gt;
&lt;li&gt;A metadata enrichment cycle aligned to the maSMP metadata schema has been proposed by ELIXIR thanks to the &lt;a href=&quot;https://smw.ds-wizard.org/&quot;&gt;Software Management Wizard&lt;/a&gt;, a tool to make completion of SMPs easier. A &lt;a href=&quot;https://doi.org/10.5281/zenodo.10374839&quot;&gt;similar effort&lt;/a&gt; is within the scope of &lt;a href=&quot;https://www.nfdi4datascience.de/&quot;&gt;NFDI4DataScience&lt;/a&gt; and the &lt;a href=&quot;https://rdm.mpdl.mpg.de/2022/12/09/smp-template-available/&quot;&gt;Research Data Management Organiser (RDMO) SMP&lt;/a&gt;. This approach reuses a command-based tool to extract metadata from GitHub repositories, &lt;a href=&quot;https://doi.org/10.5281/zenodo.8147418&quot;&gt;SOMEF&lt;/a&gt;, which is currently being extended to cover the maSMP metadata schema case.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://faircore4eosc.eu/eosc-core-components/eosc-research-software-apis-and-connectors-rsac&quot;&gt;Research Software APIs and Connectors&lt;/a&gt; project within the FAIRCORE4EOSC project is working on developing tools and services for archival, reference, description, and citation of research software artefacts. This implements the key recommendations of the &lt;a href=&quot;https://data.europa.eu/doi/10.2777/28598&quot;&gt;Scholarly Infrastructures of Research Software&lt;/a&gt; report to interconnect scholarly repositories, publishers, and aggregators. Interconnections are possible with the Software Heritage universal source code archive, using the CodeMeta standard, and the Software Heritage intrinsic identifiers (SWHID). Instructions on how to &lt;a href=&quot;https://faircore4eosc.eu/events/webinar-archive-your-software-software-heritage-example-eosc-core-service&quot;&gt;archive your software to Software Heritage&lt;/a&gt; is one outcome.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://benevol2022.github.io/papers/SlingerJansen.pdf&quot;&gt;FAIRSECO: An Extensible Framework for Impact Measurement of Research Software&lt;/a&gt; aims to enable research software engineers to rapidly find and extract relevant software fragments from the worldwide research software ecosystem.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.48550/arXiv.2401.08804&quot;&gt;Towards a Quality Indicator for Research Data publications and Research Software publications — A vision from the Helmholtz Association&lt;/a&gt; develops indicators to be used within the Association. It presents a quality assessment spanning six dimensions of research software quality that augments the four FAIR principles with two additional indicators: Scientific basis and Technical basis, resulting in the FAIR-ST framework.&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;https://ardc.edu.au/article/new-self-assessment-tool-to-promote-fair-research-software/#:~:text=Developed%20by%20the%20Netherlands%20eScience,interoperability%20and%20reusability%20(FAIR).&quot;&gt;self-assessment tool to promote FAIR research software&lt;/a&gt; has been developed by the Netherlands eScience Center and Australian Research Data Commons, to encourage the uptake of the FAIR4RS Principles (and see the 2022 &lt;a href=&quot;https://doi.org/10.5281/zenodo.6374598&quot;&gt;Survey on Adoption Guidelines for the FAIR4RS Principles&lt;/a&gt; for more resources).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git.opencarp.org/openCARP/openCARP-CI&quot;&gt;openCARP-CI&lt;/a&gt; provides Python scripts that allow developers to automatically derive CFF and DataCite files from a CodeMeta file. These pipelines can easily be integrated in continuous integration and deployment environments. They also provide tools for software publication via tagged releases, creation of BagIt and BagPack files, and publication on the research data repository RADAR.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://w3id.org/codemeta/v3.0&quot;&gt;CodeMeta-3.0&lt;/a&gt;: The minimal metadata schema for science software and code, in JSON-LD, provides a possibility to developers and researchers to insert metadata in their code and increase FAIRness.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.48550/arXiv.2402.02824&quot;&gt;FAIR-USE4OS: From open source to Open Source&lt;/a&gt; by Raphael Sonabend et al., extends the FAIR4RS Principles to provide criteria for assessing if software is Open Source. By adding ‘USE’ (User-Centred, Sustainable, Equitable), software development can adhere to open source best practice by incorporating user-input early on, ensuring front-end designs are accessible to all possible stakeholders, and planning long-term sustainability alongside software design.&lt;/li&gt;
&lt;li&gt;FAIR4RS has also been discussed within the scope of Open Science and software quality, for instance the &lt;a href=&quot;https://eosc.eu/advisory-groups/infrastructures-quality-research-software/&quot;&gt;EOSC Task Force Infrastructures for Quality Research Software&lt;/a&gt; compiled &lt;a href=&quot;https://zenodo.org/records/10723608&quot;&gt;software quality metrics&lt;/a&gt; and identified those that can be aligned to the FAIR4RS Principles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Other impacts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The publication of the FAIR4RS principles and introductory articles created awareness and raised interest in the research community, reflected in over 200 citations from across the disciplinary spectrum. Examples include the results of searches on Google Scholar for “&lt;a href=&quot;https://scholar.google.com/scholar?cluster=15311589062181606409&amp;#x26;hl=en&amp;#x26;as_sdt=2005&amp;#x26;sciodt=0%2C5&quot;&gt;FAIR principles for research software (FAIR4RS principles)&lt;/a&gt;” or “ &lt;a href=&quot;https://scholar.google.com/scholar?cites=438298512771465318&quot;&gt;Introducing the FAIR Principles for research software&lt;/a&gt;”. In addition to work discussing trans-disciplinary application of the FAIR4RS Principles, there are research policy and software management publications referring to and implementing the FAIR4RS Principles.&lt;/p&gt;
&lt;p&gt;The FAIR4RS Principles have also provided value to the broader research ecosystem by providing a base for other communities to adapt the FAIR Principles to different research objects. Examples include &lt;a href=&quot;https://doi.org/10.1088/2632-2153/ad12e3&quot;&gt;FAIR AI Models in High Energy Physics&lt;/a&gt;, which provides a practical definition of FAIR principles for machine learning and artificial intelligence models in experimental high energy physics, including a FAIR AI project template; and the Open Modeling Foundation’s work to identify, develop, and promote common standards and best practices for &lt;a href=&quot;https://doi.org/10.1016/j.envsoft.2022.105496&quot;&gt;FAIR modelling&lt;/a&gt;, by working with model organisations and individuals active within the social, ecological, environmental, and geophysical sciences.&lt;/p&gt;
&lt;p&gt;This blog was cross-posted across several platforms and originally published at *&lt;a href=&quot;https://www.researchsoft.org/blog/2024-03/&quot;&gt;&lt;em&gt;https://www.researchsoft.org/blog/2024-03/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/the-fair-for-research-software-principle-04751d5e.RZ7SqTJp.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>How to manage your IP address in Python</title><link>https://blog2.esciencecenter.nl/posts/2024-02-27---how-to-manage-your-ip-address-in-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-02-27---how-to-manage-your-ip-address-in-python</guid><description>&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;This post is the first of a series of blog posts arising from a collaboration between the eScience Center and the ODISSEI Social Data Science Team. You can find this text also at &lt;a href=&quot;https://odissei-soda.nl/tutorials/&quot;&gt;https://odissei-soda.nl/tutorials/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Research often relies on accessing novel data, for instance by collecting them from the internet through web scraping. If you have ever tried this, you may have run into your IP address being blocked by the website you scrape. Websites do this with a good reason — to protect themselves against malicious acts, such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Denial-of-service_attack&quot;&gt;denial-of-service attacks&lt;/a&gt; or large-scale scraping by parties with ill intent. This makes sense from the websites’ perspective, but prevents you from answering your research question.&lt;/p&gt;
&lt;p&gt;But this problem can be solved. In this tutorial, we show how you as a researcher can use IP rotation to circumvent certain scraping protections with the &lt;code&gt;sirup&lt;/code&gt; package, which works on Linux operating systems.&lt;/p&gt;
&lt;p&gt;Before we jump into it, it is important to highlight that web scraping and IP rotation need to respect the law and should only be a last resort. For instance, before you scrape data from a website, you should ask the data owner whether they are willing to make them available to you through a data sharing agreement. If you nevertheless decide to scrape the data, you should get approval from the ethical review board at your university. Moreover, do only scrape data that are publicly available on the web and do not send excessive number of requests to the website in a given time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to manage your IP address in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-00102567.DNJxbduL_Z10scUh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@glenncarstenspeters?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Glenn Carstens-Peters&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For rotating the IP address, we will use a VPN service. &lt;a href=&quot;https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-vpn#:~:text=A%20VPN%2C%20which%20stands%20for,and%20firewalls%20on%20the%20internet.&quot;&gt;Here&lt;/a&gt; you can read more about what a VPN service is—in short, the service has a bunch of remote servers, and connecting your computer to one of these servers changes your IP address.&lt;/p&gt;
&lt;h2 id=&quot;what-you-need&quot;&gt;What you need&lt;/h2&gt;
&lt;h2 id=&quot;1-openvpn&quot;&gt;1. &lt;code&gt;OpenVPN&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/OpenVPN&quot;&gt;OpenVPN&lt;/a&gt; is a system that allows you to create secure VPN connections. You can install it by following &lt;a href=&quot;https://community.openvpn.net/openvpn/wiki/OpenvpnSoftwareRepos&quot;&gt;these instructions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;2-root-access-to-your-computer&quot;&gt;2. Root access to your computer&lt;/h2&gt;
&lt;p&gt;Because internet connections are an important security concern, OpenVPN requires root access — this is the equivalent to administrator rights on a Windows computer. If you have root access, you can for instance run the following command on your terminal:&lt;/p&gt;
&lt;p&gt;sudo ls -lh # will ask you for your root password&lt;/p&gt;
&lt;h2 id=&quot;installing-and-setting-up-sirup&quot;&gt;Installing and setting up &lt;code&gt;sirup&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;sirup&lt;/code&gt; as follows:&lt;/p&gt;
&lt;p&gt;python -m pip install sirupTo use the package and change your IP address, you need an account with a VPN service provider that offers OpenVPN configuration files for your account. At the time of writing, for instance ProtonVPN and Surfshark offer this option — note that these services are not for free. We will use ProtonVPN in this tutorial.&lt;/p&gt;
&lt;p&gt;After creating an account, you need to download two sets of files.&lt;/p&gt;
&lt;p&gt;First, you download credentials that identify your Proton account when using OpenVPN. On the ProtonVPN website, click on “Account” and then you see something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to manage your IP address in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;315&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-0efd650a.BooFlCCP_Z1Lvn1G.webp&quot; srcset=&quot;&quot;&gt;
Copy and paste the username and the password into a &lt;code&gt;txt&lt;/code&gt; file that looks like this:&lt;/p&gt;
&lt;p&gt;username
passwordThen, save the file as “proton_credentials.txt”. Remember where it is stored — we will need it later.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;A first warning on security. **Storing account credentials like this makes it easy for you to use the sirup package. But it also increases the risk that unauthorized persons get a hold on these credentials. Thus, be careful to store the credentials in a safe place on your laptop and to not share them with anyone.&lt;/p&gt;
&lt;p&gt;Second, to use OpenVPN we need configuration files, whose names end with &lt;code&gt;.ovpn&lt;/code&gt;. The files allow OpenVPN to connect to a server from the VPN service provider. In ProtonVPN, go to the “Download” section of your account. Select the options as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to manage your IP address in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;509&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-1c18ffaf.BfZTWBsr_Q79VL.webp&quot; srcset=&quot;&quot;&gt;
And download the configuration file(s) you want to use. Store the downloaded files on your computer, and remember the location.&lt;/p&gt;
&lt;h2 id=&quot;using-sirup&quot;&gt;Using &lt;code&gt;sirup&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We start by defining the path to the &lt;code&gt;proton_credentials.txt&lt;/code&gt; file. When you execute the code below, you will be asked to enter the root password, which is necessary to make the connection.&lt;/p&gt;
&lt;p&gt;import getpass
auth_file = “proton_credentials.txt”
pwd = getpass.getpass(“Please enter your root password:”)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A second warning on security.** The code above stores your root password during the Python session without encrypting it. This is OK to do on your laptop — if someone gets access to your Python session, your security has already been compromised — but not recommended on a shared computer such as a cluster or a cloud service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;changing-the-ip-address-with-sirup&quot;&gt;Changing the IP address with &lt;code&gt;sirup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Now you can use the &lt;code&gt;VPNConnector&lt;/code&gt; to change our IP address. We will use the &lt;code&gt;&quot;my_config_file.ovpn&quot;&lt;/code&gt; configuration file.&lt;/p&gt;
&lt;p&gt;from sirup.VPNConnector import VPNConnector
config_file = “my_config_file.ovpn”The code below first connects to the server associated with &lt;code&gt;&quot;my_config_file.ovpn&quot;&lt;/code&gt; and then disconnects.&lt;/p&gt;
&lt;p&gt;connector = VPNConnector(auth_file, config_file)&lt;/p&gt;
&lt;h1 id=&quot;lets-see-the-current-ip-address-when-no-vpn-tunnel-is-active&quot;&gt;Let’s see the current IP address when no VPN tunnel is active&lt;/h1&gt;
&lt;p&gt;print(connector.base_ip)&lt;/p&gt;
&lt;p&gt;connector.connect(pwd=pwd)&lt;/p&gt;
&lt;h1 id=&quot;now-the-ip-address-should-differ&quot;&gt;Now the IP address should differ&lt;/h1&gt;
&lt;p&gt;print(connector.current_ip)&lt;/p&gt;
&lt;p&gt;connector.disconnect(pwd=pwd)&lt;/p&gt;
&lt;h1 id=&quot;now-current_ip-should-be-the-same-as-base_ip-above&quot;&gt;Now current_ip should be the same as base_ip above&lt;/h1&gt;
&lt;p&gt;print(connector.current_ip)&lt;/p&gt;
&lt;h3 id=&quot;rotating-the-ip-address-with-sirup&quot;&gt;Rotating the IP address with &lt;code&gt;sirup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Instead of connecting to a single server, you can also rotate across many different servers — which means you rotate your IP address across a set of potential addresses. Doing so is useful for larger scraping jobs because it will spread your requests across more servers.&lt;/p&gt;
&lt;p&gt;To do this, you need to download multiple configuration files as described above. Store all of the &lt;code&gt;.ovpn&lt;/code&gt; configuration files together in a separate directory. Let’s say you store them in the &lt;code&gt;&quot;/path/to/config/files/&quot;&lt;/code&gt; directory. You need to define this path in your Python script:&lt;/p&gt;
&lt;p&gt;config_path = “/path/to/config/files/“The following code connects to two different servers before disconnecting again:&lt;/p&gt;
&lt;p&gt;from sirup.IPRotator import IPRotator&lt;/p&gt;
&lt;p&gt;rotator = IPRotator(auth_file=my_auth_file, config_location=config_path, seed=seed) # this will ask for the root password&lt;/p&gt;
&lt;p&gt;print(rotator.connector.base_ip)&lt;/p&gt;
&lt;p&gt;rotator.connect()
print(rotator.connector.current_ip)&lt;/p&gt;
&lt;p&gt;rotator.rotate()
print(rotator.connector.current_ip)&lt;/p&gt;
&lt;p&gt;rotator.disconnect()&lt;/p&gt;
&lt;p&gt;print(rotator.connector.current_ip)&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This tutorial has walked you through the steps to manage your IP address in Python, using the &lt;code&gt;sirup&lt;/code&gt; package. We hope it makes your scraping workflows easier!&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;sirup&lt;/code&gt; is an open-source package developed by the Netherlands eScience Center. If you use the tool, you can cite &lt;a href=&quot;https://zenodo.org/records/10261949&quot;&gt;this zenodo repository&lt;/a&gt; with the DOI: &lt;a href=&quot;https://doi.org/10.5281/zenodo.10261949&quot;&gt;https://doi.org/10.5281/zenodo.10261949&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The source code of the package is &lt;a href=&quot;https://github.com/ivory-tower-private-power/sirup?tab=readme-ov-file&quot;&gt;here&lt;/a&gt;, where you can contribute to it, build on it and submit issues.&lt;/p&gt;
&lt;p&gt;Thanks to Patrick Bos, Peter Kalverla, Kody Moodley and Carlos Gonzalez Poses for comments.&lt;/p&gt;</description><pubDate>Tue, 27 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;This post is the first of a series of blog posts arising from a collaboration between the eScience Center and the ODISSEI Social Data Science Team. You can find this text also at &lt;a href=&quot;https://odissei-soda.nl/tutorials/&quot;&gt;https://odissei-soda.nl/tutorials/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Research often relies on accessing novel data, for instance by collecting them from the internet through web scraping. If you have ever tried this, you may have run into your IP address being blocked by the website you scrape. Websites do this with a good reason — to protect themselves against malicious acts, such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Denial-of-service_attack&quot;&gt;denial-of-service attacks&lt;/a&gt; or large-scale scraping by parties with ill intent. This makes sense from the websites’ perspective, but prevents you from answering your research question.&lt;/p&gt;
&lt;p&gt;But this problem can be solved. In this tutorial, we show how you as a researcher can use IP rotation to circumvent certain scraping protections with the &lt;code&gt;sirup&lt;/code&gt; package, which works on Linux operating systems.&lt;/p&gt;
&lt;p&gt;Before we jump into it, it is important to highlight that web scraping and IP rotation need to respect the law and should only be a last resort. For instance, before you scrape data from a website, you should ask the data owner whether they are willing to make them available to you through a data sharing agreement. If you nevertheless decide to scrape the data, you should get approval from the ethical review board at your university. Moreover, do only scrape data that are publicly available on the web and do not send excessive number of requests to the website in a given time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to manage your IP address in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-00102567.DNJxbduL_Z10scUh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@glenncarstenspeters?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Glenn Carstens-Peters&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For rotating the IP address, we will use a VPN service. &lt;a href=&quot;https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-vpn#:~:text=A%20VPN%2C%20which%20stands%20for,and%20firewalls%20on%20the%20internet.&quot;&gt;Here&lt;/a&gt; you can read more about what a VPN service is—in short, the service has a bunch of remote servers, and connecting your computer to one of these servers changes your IP address.&lt;/p&gt;
&lt;h2 id=&quot;what-you-need&quot;&gt;What you need&lt;/h2&gt;
&lt;h2 id=&quot;1-openvpn&quot;&gt;1. &lt;code&gt;OpenVPN&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/OpenVPN&quot;&gt;OpenVPN&lt;/a&gt; is a system that allows you to create secure VPN connections. You can install it by following &lt;a href=&quot;https://community.openvpn.net/openvpn/wiki/OpenvpnSoftwareRepos&quot;&gt;these instructions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;2-root-access-to-your-computer&quot;&gt;2. Root access to your computer&lt;/h2&gt;
&lt;p&gt;Because internet connections are an important security concern, OpenVPN requires root access — this is the equivalent to administrator rights on a Windows computer. If you have root access, you can for instance run the following command on your terminal:&lt;/p&gt;
&lt;p&gt;sudo ls -lh # will ask you for your root password&lt;/p&gt;
&lt;h2 id=&quot;installing-and-setting-up-sirup&quot;&gt;Installing and setting up &lt;code&gt;sirup&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;You can install &lt;code&gt;sirup&lt;/code&gt; as follows:&lt;/p&gt;
&lt;p&gt;python -m pip install sirupTo use the package and change your IP address, you need an account with a VPN service provider that offers OpenVPN configuration files for your account. At the time of writing, for instance ProtonVPN and Surfshark offer this option — note that these services are not for free. We will use ProtonVPN in this tutorial.&lt;/p&gt;
&lt;p&gt;After creating an account, you need to download two sets of files.&lt;/p&gt;
&lt;p&gt;First, you download credentials that identify your Proton account when using OpenVPN. On the ProtonVPN website, click on “Account” and then you see something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to manage your IP address in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;315&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-0efd650a.BooFlCCP_Z1Lvn1G.webp&quot; srcset=&quot;&quot;&gt;
Copy and paste the username and the password into a &lt;code&gt;txt&lt;/code&gt; file that looks like this:&lt;/p&gt;
&lt;p&gt;username
passwordThen, save the file as “proton_credentials.txt”. Remember where it is stored — we will need it later.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;A first warning on security. **Storing account credentials like this makes it easy for you to use the sirup package. But it also increases the risk that unauthorized persons get a hold on these credentials. Thus, be careful to store the credentials in a safe place on your laptop and to not share them with anyone.&lt;/p&gt;
&lt;p&gt;Second, to use OpenVPN we need configuration files, whose names end with &lt;code&gt;.ovpn&lt;/code&gt;. The files allow OpenVPN to connect to a server from the VPN service provider. In ProtonVPN, go to the “Download” section of your account. Select the options as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to manage your IP address in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;509&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-1c18ffaf.BfZTWBsr_Q79VL.webp&quot; srcset=&quot;&quot;&gt;
And download the configuration file(s) you want to use. Store the downloaded files on your computer, and remember the location.&lt;/p&gt;
&lt;h2 id=&quot;using-sirup&quot;&gt;Using &lt;code&gt;sirup&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We start by defining the path to the &lt;code&gt;proton_credentials.txt&lt;/code&gt; file. When you execute the code below, you will be asked to enter the root password, which is necessary to make the connection.&lt;/p&gt;
&lt;p&gt;import getpass
auth_file = “proton_credentials.txt”
pwd = getpass.getpass(“Please enter your root password:”)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A second warning on security.** The code above stores your root password during the Python session without encrypting it. This is OK to do on your laptop — if someone gets access to your Python session, your security has already been compromised — but not recommended on a shared computer such as a cluster or a cloud service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;changing-the-ip-address-with-sirup&quot;&gt;Changing the IP address with &lt;code&gt;sirup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Now you can use the &lt;code&gt;VPNConnector&lt;/code&gt; to change our IP address. We will use the &lt;code&gt;&quot;my_config_file.ovpn&quot;&lt;/code&gt; configuration file.&lt;/p&gt;
&lt;p&gt;from sirup.VPNConnector import VPNConnector
config_file = “my_config_file.ovpn”The code below first connects to the server associated with &lt;code&gt;&quot;my_config_file.ovpn&quot;&lt;/code&gt; and then disconnects.&lt;/p&gt;
&lt;p&gt;connector = VPNConnector(auth_file, config_file)&lt;/p&gt;
&lt;h1 id=&quot;lets-see-the-current-ip-address-when-no-vpn-tunnel-is-active&quot;&gt;Let’s see the current IP address when no VPN tunnel is active&lt;/h1&gt;
&lt;p&gt;print(connector.base_ip)&lt;/p&gt;
&lt;p&gt;connector.connect(pwd=pwd)&lt;/p&gt;
&lt;h1 id=&quot;now-the-ip-address-should-differ&quot;&gt;Now the IP address should differ&lt;/h1&gt;
&lt;p&gt;print(connector.current_ip)&lt;/p&gt;
&lt;p&gt;connector.disconnect(pwd=pwd)&lt;/p&gt;
&lt;h1 id=&quot;now-current_ip-should-be-the-same-as-base_ip-above&quot;&gt;Now current_ip should be the same as base_ip above&lt;/h1&gt;
&lt;p&gt;print(connector.current_ip)&lt;/p&gt;
&lt;h3 id=&quot;rotating-the-ip-address-with-sirup&quot;&gt;Rotating the IP address with &lt;code&gt;sirup&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Instead of connecting to a single server, you can also rotate across many different servers — which means you rotate your IP address across a set of potential addresses. Doing so is useful for larger scraping jobs because it will spread your requests across more servers.&lt;/p&gt;
&lt;p&gt;To do this, you need to download multiple configuration files as described above. Store all of the &lt;code&gt;.ovpn&lt;/code&gt; configuration files together in a separate directory. Let’s say you store them in the &lt;code&gt;&quot;/path/to/config/files/&quot;&lt;/code&gt; directory. You need to define this path in your Python script:&lt;/p&gt;
&lt;p&gt;config_path = “/path/to/config/files/“The following code connects to two different servers before disconnecting again:&lt;/p&gt;
&lt;p&gt;from sirup.IPRotator import IPRotator&lt;/p&gt;
&lt;p&gt;rotator = IPRotator(auth_file=my_auth_file, config_location=config_path, seed=seed) # this will ask for the root password&lt;/p&gt;
&lt;p&gt;print(rotator.connector.base_ip)&lt;/p&gt;
&lt;p&gt;rotator.connect()
print(rotator.connector.current_ip)&lt;/p&gt;
&lt;p&gt;rotator.rotate()
print(rotator.connector.current_ip)&lt;/p&gt;
&lt;p&gt;rotator.disconnect()&lt;/p&gt;
&lt;p&gt;print(rotator.connector.current_ip)&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This tutorial has walked you through the steps to manage your IP address in Python, using the &lt;code&gt;sirup&lt;/code&gt; package. We hope it makes your scraping workflows easier!&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;sirup&lt;/code&gt; is an open-source package developed by the Netherlands eScience Center. If you use the tool, you can cite &lt;a href=&quot;https://zenodo.org/records/10261949&quot;&gt;this zenodo repository&lt;/a&gt; with the DOI: &lt;a href=&quot;https://doi.org/10.5281/zenodo.10261949&quot;&gt;https://doi.org/10.5281/zenodo.10261949&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The source code of the package is &lt;a href=&quot;https://github.com/ivory-tower-private-power/sirup?tab=readme-ov-file&quot;&gt;here&lt;/a&gt;, where you can contribute to it, build on it and submit issues.&lt;/p&gt;
&lt;p&gt;Thanks to Patrick Bos, Peter Kalverla, Kody Moodley and Carlos Gonzalez Poses for comments.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-to-manage-your-ip-address-in-python-00102567.DNJxbduL.jpg" medium="image"/><author>Flavio Hafner</author></item><item><title>Differentiation without subtraction</title><link>https://blog2.esciencecenter.nl/posts/2024-02-13---differentiation-without-subtraction</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-02-13---differentiation-without-subtraction</guid><description>&lt;p&gt;54&lt;/p&gt;
&lt;p&gt;A surprising application of complex numbers&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-e61cb215.BcArwpWs_ZxtMDI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@charlesdeluvio?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;charlesdeluvio&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some time ago I came across one of those ideas that makes you wonder: &lt;em&gt;“why nobody told me about this before?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Those of you with mathematical training certainly remember the &lt;a href=&quot;https://en.wikipedia.org/wiki/Taylor_series&quot;&gt;Taylor series&lt;/a&gt;. For those who do not, and yet want to keep reading, this &lt;a href=&quot;https://www.geogebra.org/m/CeW2gCzH&quot;&gt;visual simulation &lt;/a&gt;may be helpful.&lt;/p&gt;
&lt;p&gt;The idea is that any continuous, smooth function, can be approximated by a polynomial; the higher the degree, the more accurate the approximation. To put it otherwise: if we know the value of a function and its derivatives at a given point (x), we can estimate its value at a nearby point (x + ε). More specifically:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;63&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-b1f93adc.BE4fSPB9_Ixl5A.webp&quot; srcset=&quot;&quot;&gt;
Example of a generic Taylor seriesIf instead of a step (ε) in the realm of real numbers, we perform a step in the world of imaginary numbers (i ε), it follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;60&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-b8317317.BIFg7E0-_g0Lba.webp&quot; srcset=&quot;&quot;&gt;
It is here where things get interesting. If we take only the imaginary part, we get an equation that involves only the first derivative, the function evaluated in the complex plane, and the step size:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;53&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-2f21efdf.BaYyflhX_Z1MzxLq.webp&quot; srcset=&quot;&quot;&gt;
We just keep the imaginary part, and drop the real oneThis can be rearranged as an interesting formula for an approximate derivative:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;88&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-a80888ed.CbK2fjOB_Z3wfDt.webp&quot; srcset=&quot;&quot;&gt;
Complex-step numerical derivativeThat can be even used for exact evaluation:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;106&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-3409cb52.UEyGppZn_Z1rQYNm.webp&quot; srcset=&quot;&quot;&gt;
Complex-step exact derivative&lt;/p&gt;
&lt;h2 id=&quot;is-this-useful-at-all&quot;&gt;Is this useful at all?&lt;/h2&gt;
&lt;p&gt;I know…, that was pretty strange. It feels like a complicated &lt;em&gt;tour de force&lt;/em&gt; for something as well-known as a numerical derivative. Nevertheless, it is hard to find a mathematical result that is completely useless, and complex-step differentiation is no exception.&lt;/p&gt;
&lt;p&gt;Let’s take a look at the last formula of the day, that of the classical step-forward numerical differentiation:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;93&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-94add499.q85oueAm_Z1FXbqg.webp&quot; srcset=&quot;&quot;&gt;
Step-forward numerical derivativeIf we use the step-forward numerical derivative on a computer, the subtraction can cause numerical problems. Computers can’t store real numbers, but a rounded representation of them, and their numerical resolution is limited. If e is very small, it may happen that the subtraction above returns a zero as an artifact, making the whole calculation wrong.&lt;/p&gt;
&lt;p&gt;Notice now the main difference between this and our complex-step algorithm: there is no subtraction in the complex one. One problem less!&lt;/p&gt;
&lt;h2 id=&quot;further-information&quot;&gt;Further information&lt;/h2&gt;
&lt;p&gt;More information here: &lt;a href=&quot;https://sinews.siam.org/Details-Page/differentiation-without-a-difference&quot;&gt;Differentiation without a difference. SIAM news&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, you may also like &lt;a href=&quot;https://blog2.esciencecenter.nl/automatic-differentiation-from-scratch-23d50c699555&quot;&gt;Automatic differentiation from scratch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;This article appeared first, in Spanish, in &lt;em&gt;&lt;a href=&quot;https://fuga.naukas.com/2018/08/20/derivando-sin-restar/&quot;&gt;&lt;em&gt;Naukas.com&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;</description><pubDate>Tue, 13 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;54&lt;/p&gt;
&lt;p&gt;A surprising application of complex numbers&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-e61cb215.BcArwpWs_ZxtMDI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@charlesdeluvio?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;charlesdeluvio&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Some time ago I came across one of those ideas that makes you wonder: &lt;em&gt;“why nobody told me about this before?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Those of you with mathematical training certainly remember the &lt;a href=&quot;https://en.wikipedia.org/wiki/Taylor_series&quot;&gt;Taylor series&lt;/a&gt;. For those who do not, and yet want to keep reading, this &lt;a href=&quot;https://www.geogebra.org/m/CeW2gCzH&quot;&gt;visual simulation &lt;/a&gt;may be helpful.&lt;/p&gt;
&lt;p&gt;The idea is that any continuous, smooth function, can be approximated by a polynomial; the higher the degree, the more accurate the approximation. To put it otherwise: if we know the value of a function and its derivatives at a given point (x), we can estimate its value at a nearby point (x + ε). More specifically:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;63&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-b1f93adc.BE4fSPB9_Ixl5A.webp&quot; srcset=&quot;&quot;&gt;
Example of a generic Taylor seriesIf instead of a step (ε) in the realm of real numbers, we perform a step in the world of imaginary numbers (i ε), it follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;60&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-b8317317.BIFg7E0-_g0Lba.webp&quot; srcset=&quot;&quot;&gt;
It is here where things get interesting. If we take only the imaginary part, we get an equation that involves only the first derivative, the function evaluated in the complex plane, and the step size:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;53&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-2f21efdf.BaYyflhX_Z1MzxLq.webp&quot; srcset=&quot;&quot;&gt;
We just keep the imaginary part, and drop the real oneThis can be rearranged as an interesting formula for an approximate derivative:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;88&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-a80888ed.CbK2fjOB_Z3wfDt.webp&quot; srcset=&quot;&quot;&gt;
Complex-step numerical derivativeThat can be even used for exact evaluation:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;106&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-3409cb52.UEyGppZn_Z1rQYNm.webp&quot; srcset=&quot;&quot;&gt;
Complex-step exact derivative&lt;/p&gt;
&lt;h2 id=&quot;is-this-useful-at-all&quot;&gt;Is this useful at all?&lt;/h2&gt;
&lt;p&gt;I know…, that was pretty strange. It feels like a complicated &lt;em&gt;tour de force&lt;/em&gt; for something as well-known as a numerical derivative. Nevertheless, it is hard to find a mathematical result that is completely useless, and complex-step differentiation is no exception.&lt;/p&gt;
&lt;p&gt;Let’s take a look at the last formula of the day, that of the classical step-forward numerical differentiation:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Differentiation without subtraction&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;93&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-94add499.q85oueAm_Z1FXbqg.webp&quot; srcset=&quot;&quot;&gt;
Step-forward numerical derivativeIf we use the step-forward numerical derivative on a computer, the subtraction can cause numerical problems. Computers can’t store real numbers, but a rounded representation of them, and their numerical resolution is limited. If e is very small, it may happen that the subtraction above returns a zero as an artifact, making the whole calculation wrong.&lt;/p&gt;
&lt;p&gt;Notice now the main difference between this and our complex-step algorithm: there is no subtraction in the complex one. One problem less!&lt;/p&gt;
&lt;h2 id=&quot;further-information&quot;&gt;Further information&lt;/h2&gt;
&lt;p&gt;More information here: &lt;a href=&quot;https://sinews.siam.org/Details-Page/differentiation-without-a-difference&quot;&gt;Differentiation without a difference. SIAM news&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, you may also like &lt;a href=&quot;https://blog2.esciencecenter.nl/automatic-differentiation-from-scratch-23d50c699555&quot;&gt;Automatic differentiation from scratch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;This article appeared first, in Spanish, in &lt;em&gt;&lt;a href=&quot;https://fuga.naukas.com/2018/08/20/derivando-sin-restar/&quot;&gt;&lt;em&gt;Naukas.com&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/differentiation-without-subtraction-b1f93adc.BE4fSPB9.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Causal Inference in JASP: The Process Module</title><link>https://blog2.esciencecenter.nl/posts/2024-02-01---causal-inference-in-jasp-the-process-module</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-02-01---causal-inference-in-jasp-the-process-module</guid><description>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/malte-luken/&quot;&gt;Malte Lüken&lt;/a&gt;, &lt;a href=&quot;https://juliarohrer.com/&quot;&gt;Julia M. Rohrer&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/thijs-vroegh/&quot;&gt;Thijs Vroegh&lt;/a&gt;, &lt;a href=&quot;https://www.uva.nl/en/profile/d/o/j.b.vandoorn/j.b.vandoorn.html&quot;&gt;Johnny van Doorn&lt;/a&gt;, and &lt;a href=&quot;https://www.uva.nl/en/profile/w/a/e.m.wagenmakers/e.m.wagenmakers.html&quot;&gt;Eric-Jan Wagenmakers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post is also published on the JASP &lt;em&gt;&lt;a href=&quot;https://jasp-stats.org/blog/&quot;&gt;&lt;em&gt;blog&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;448&quot; height=&quot;448&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-4987f6a5.B8-TxRvg_bKcUi.webp&quot; srcset=&quot;&quot;&gt;
In a recent &lt;a href=&quot;https://jasp-stats.org/2023/07/27/conditional-process-models/&quot;&gt;blog post&lt;/a&gt;, we announced the development of a JASP module for conditional process models, similar to the popular &lt;a href=&quot;https://www.processmacro.org/&quot;&gt;PROCESS&lt;/a&gt; macro for SPSS (Hayes, 2022a, 2022b). We can now share that we reached a milestone in our development efforts: The latest JASP release 18.2 includes a beta version of the Process module which allows users to apply frequentist process models. Besides covering many of the features of the SPSS macro, the JASP Process module provides a flexible and easy-to-use interface. It also makes the causal assumptions of process models more explicit and provides functionality to test them. In this blog post, we will introduce the main features of the module using a real-world example.&lt;/p&gt;
&lt;h2 id=&quot;mediation-moderation-and-conditional-process-models&quot;&gt;Mediation, Moderation, and Conditional Process Models&lt;/h2&gt;
&lt;p&gt;The aim of our module is to test models that involve mediation and moderation effects. A mediation effect is a causal chain between three variables. For example, when X → M, M → Y, and X → Y, then the causal effect from X to Y is (partly) mediated by M. A moderation effect implies that the relationship between two variables changes depending on a third variable, e.g., the effect X → M changes as the moderator W changes. A model that includes at least one mediation and one moderation effect is called a conditional process model because it makes assumptions about the causal process between variables, but the process is conditional on moderator variables (Hayes, 2022a).&lt;/p&gt;
&lt;p&gt;Conditional process models can also be conceptualized as parametric directed acyclic graphs (DAGs) or structural equation models (SEMs) that only include manifest variables (Pearl, 2012). We can use the properties of DAGs to test the implications of the causal model against data while SEMs are a useful framework for parameter estimation.&lt;/p&gt;
&lt;p&gt;The PROCESS macro for SPSS uses a regression-based approach to estimate process models which allows predictors (including independent variables, covariates, and mediators) to be correlated when there is no explicit causal path between them. Because the JASP Process module uses SEMs for model estimation, these correlations need to be explicitly allowed by the user. We believe this design choice prompts users to think more explicitly about the assumptions of their models. For a discussion of differences between PROCESS and SEM-based estimation, see Hayes et al. (2017).&lt;/p&gt;
&lt;h2 id=&quot;example-age-and-listening-related-fatigue&quot;&gt;Example: Age and Listening-related Fatigue&lt;/h2&gt;
&lt;p&gt;To illustrate the features of the Process module, we use openly available &lt;a href=&quot;https://osf.io/hc8n4/&quot;&gt;data&lt;/a&gt; from the study “Predictors of listening-related fatigue across the adult life span” by McGarrigle et al. (2021) which was published in &lt;em&gt;Psychological Science&lt;/em&gt;. The study investigates how different variables mediate and moderate the causal effect of age on listening-related fatigue using conditional process models. The analysis was pre-registered and the data set has a relatively large sample size (N = 281) which is roughly evenly distributed across age groups. These properties make the study a good example for conditional process analysis with observational data. As the authors of the original study, we assume that age is an exogenous (independent) variable which allows us to clearly identify the direction of the causal effect from age to fatigue.&lt;/p&gt;
&lt;p&gt;In our illustration of the module, we will reproduce the original analysis of the study but also test the implications of the hypothesized causal model. Note that our example only uses z-standardized variables which we renamed so they can be easily identified. The included candidates for mediators or moderators are auditory attention ability (“AudAttention”), perceived hearing impairment (“HearImpair”), perceived memory ability (“Memory”), and perceived mood disturbances (“MoodDisturb”). The example data set is also available in the internal JASP Data Library.&lt;/p&gt;
&lt;h2 id=&quot;the-basics-flexible-conditional-process-models-in-jasp&quot;&gt;The Basics: Flexible Conditional Process Models in JASP&lt;/h2&gt;
&lt;p&gt;To estimate a conditional process model in JASP, we first load the data set and enable the Process module by clicking the blue “+” sign in the top right corner and selecting “Process (beta)”.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;514&quot; height=&quot;133&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-5daca690.D4a8o04O_52N1O.webp&quot; srcset=&quot;&quot;&gt;
We then click on the available module to start the “Classic Process Model” analysis. First, we drag the variable “Fatigue” into the box &lt;em&gt;Dependent Variable&lt;/em&gt; and the variables “Age”, “AudAttention”, “HearImpair”, “Memory”, as well as “MoodDisturb” into the box &lt;em&gt;Continuous Predictors&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-d67427be.CuqoN1D3_1WUm0B.webp&quot; srcset=&quot;&quot;&gt;
In this example, we use a new interface that differs from the way process models are specified in SPSS. In the &lt;em&gt;Models&lt;/em&gt; section, we can construct the hypothesized model by adding causal paths between variables. We add three paths from “Age” to “Fatigue” by selecting the variables in the &lt;em&gt;From&lt;/em&gt; and &lt;em&gt;To&lt;/em&gt; dropdowns. For each path, we choose &lt;em&gt;Mediator&lt;/em&gt; in the &lt;em&gt;Process Type&lt;/em&gt; dropdown and select “AudAttention”, “HearImpair”, “Memory” as the &lt;em&gt;Process Variable&lt;/em&gt;, respectively.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;260&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-914a5c82.CZUD3SKO_DY1EA.webp&quot; srcset=&quot;&quot;&gt;
After completing each path, JASP provides the output of the estimated model including a path diagram showing the conceptual model structure. The path diagram resembles the hypothesized parallel mediation model after the third path.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-54c3bb79.D-2lbkwR_Z24fMe8.webp&quot; srcset=&quot;&quot;&gt;
Before we look at the results, we select &lt;em&gt;Bootstrap&lt;/em&gt; under &lt;em&gt;Method&lt;/em&gt; in the &lt;em&gt;Options&lt;/em&gt; section to enable bootstrapped confidence intervals; this is done because we cannot assume that indirect effects are normally distributed. Bootstrapping in JASP can take a few minutes to finish.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;240&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-3640843a.DI_uQAhp_ZqQfFL.webp&quot; srcset=&quot;&quot;&gt;
Below the path diagram, under “Parameter estimates”, the output shows a table with estimated parameters and effects. The second table “Mediation effects” contains the direct and indirect effects. As in the original study, the table shows a negative direct effect from age to fatigue and a positive indirect effect via perceived hearing impairment, both with bootstrapped confidence intervals excluding zero.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;161&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-9a885c40.CgRVYg-5_1fhwQ4.webp&quot; srcset=&quot;&quot;&gt;
To add a moderation effect to our model, we go back to the “Models” section and click the green “+” button in the top left corner to add a second model to our analysis. As in the previous model, we add three mediation paths from “Age” to “Fatigue”. Then we add a fourth path from “Age” to “Fatigue” and specify “MoodDisturb” as a moderator.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;285&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-9285476b.uUtk5FYI_2jvCSg.webp&quot; srcset=&quot;&quot;&gt;
Now, JASP provides output for both models. In the “Model summary” table, we can see that Model 2 has lower AIC and BIC values indicating a better model fit compared to Model 1 (the weights for both criteria lie almost exclusively on Model 2; AIC and BIC weights can be enabled in the “Options” section).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;85&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-b7f6e2f7.3qYghwGB_Z1Wnp4h.webp&quot; srcset=&quot;&quot;&gt;
Under “Parameter estimates” for Model 2, we can see that the direct effect of mood disturbances on fatigue is positive and its bootstrap confidence interval excludes zero. However, this is not the case for the interaction between age and mood disturbances. Thus, the model does not provide evidence for the hypothesized moderation effect, reproducing the result of the original study.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;251&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-d5746641.Dx5zFN9S_I3pWP.webp&quot; srcset=&quot;&quot;&gt;
How can we explain that Model 2 fits the data better but shows no evidence for a moderation effect? Model 2 does show a strong direct effect of mood disturbance on fatigue, which is not included in Model 1, and we assume that it leads to the better model fit. This suggests that we should include mood disturbances in our model but not as a moderator on the path between age and fatigue.&lt;/p&gt;
&lt;h2 id=&quot;advanced-testing-implications-of-causal-models&quot;&gt;Advanced: Testing Implications of Causal Models&lt;/h2&gt;
&lt;p&gt;Because the estimated effect from age to fatigue pointed in the opposite of the expected direction, McGarrigle et al. (2021) estimated alternative process models in an exploratory analysis. The Process module provides a useful tool that indicates where the assumed causal model does not fit the observed relationships in the data. DAGs have implications for the variables they involve, specifically, for which variables should be independent in the data (Pearl, 2012; Textor et al., 2016). These implications can be tested against data with (conditional) independence tests. In our model, all variables are assumed to be continuous and all relationships to be linear, so we test for (conditional) independence by estimating (partial) correlation coefficients.&lt;/p&gt;
&lt;p&gt;In JASP, we can test local implications by ticking the box &lt;em&gt;Local tests&lt;/em&gt; under *Tests &lt;em&gt;in the &lt;em&gt;Models&lt;/em&gt; section&lt;/em&gt;. *Here, we apply local tests to Model 2. Underneath the box, we can select the type of test we want to use, which is the default (&lt;em&gt;Linear&lt;/em&gt;) in our case. If the model contains categorical variables or relationships are assumed to be nonlinear, a different type should be chosen (e.g., &lt;em&gt;Loess&lt;/em&gt; or &lt;em&gt;Chi-square&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;260&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-ebfb687a.BQT4PiqY_fcxxF.webp&quot; srcset=&quot;&quot;&gt;
After ticking the &lt;em&gt;Local tests&lt;/em&gt; box, a new table appears in the output under “Local tests”. In the first three columns, the table shows which implied relationship is tested: For example, in the first row, auditory attention is assumed to be conditionally independent from hearing impairment given age. This can also be seen in the model diagram, which does not contain any direct arrows between the two variables (i.e., age accounts for the entire covariance between auditory attention and hearing impairment). The estimated partial correlation for this implied relationship is very small and not significant indicating that this implication is not violated. The opposite is true for row four: The model implies that age and mood disturbances are independent since there are no direct (or indirect) arrows between the two variables. However, the estimated correlation is negative and significant suggesting that the implication is violated and the model is misspecified. Rows five to seven also show significant (partial) correlations increasing the evidence that the model is inappropriate for the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;272&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-0ac11436.CN-zxQx6_Z15B66U.webp&quot; srcset=&quot;&quot;&gt;
Note that the PROCESS macro for SPSS behaves differently to our module by automatically allowing mediators to correlate. In a SEM context, this behavior can be imitated by estimating the residual covariances between mediators in the model. Ticking the box &lt;em&gt;Mediators&lt;/em&gt; under &lt;em&gt;Residual Covariances&lt;/em&gt; in the &lt;em&gt;Models&lt;/em&gt; section enables this.&lt;/p&gt;
&lt;h2 id=&quot;advanced-adjusting-the-model-in-an-exploratory-analysis&quot;&gt;Advanced: Adjusting the Model in an Exploratory Analysis&lt;/h2&gt;
&lt;p&gt;In the original study, McGarrigle et al. conducted an exploratory analysis where they used “MoodDisturb” as a mediator instead of a moderator. Our implication tests of the previous model with “MoodDisturb” provide a rationale for this: The data showed a negative correlation between “Age” and “MoodDisturb” which was not expected by the model. Our exploratory model should therefore account for this correlation by including a direct causal path from “Age” to “MoodDisturb”.&lt;/p&gt;
&lt;p&gt;We open a new Classical Process Model* analysis and select the same variables for &lt;em&gt;Dependent Variable&lt;/em&gt; and &lt;em&gt;Continuous Predictors&lt;/em&gt; as in the previous analysis. In our exploratory model, we specify “MoodDisturb” as a mediator between “Age” and “Fatigue”. We add “HearImpair” as a second mediator and leave out the other variables for simplicity.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;194&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-5fc4cb9f.D_nm5c-D_rYRHN.webp&quot; srcset=&quot;&quot;&gt;
In the output, we can see the conceptual diagram of our exploratory model.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;524&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-344aaf01.B803Zpd-_Z1IbXIe.webp&quot; srcset=&quot;&quot;&gt;
Again, we test the local implications of our new model. We can see that the model expects mood disturbances and hearing impairment to be conditionally independent given age, which is violated in the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;148&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-2aefc199.CP2Z6xVu_Z1GJIQd.webp&quot; srcset=&quot;&quot;&gt;
Thus, we need to further adjust our model, for example, by adding a direct causal path from “HearImpair” to “MoodDisturb” assuming that increased perceived hearing impairment leads to increased mood disturbance and not vice versa. In JASP, we can add a direct path by selecting &lt;em&gt;Direct&lt;/em&gt; in the &lt;em&gt;Process Type&lt;/em&gt; dropdown under the &lt;em&gt;Models&lt;/em&gt; section.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;259&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-6557220d.Cz0JTX88_Z1tv47X.webp&quot; srcset=&quot;&quot;&gt;
The output now shows the conceptual diagram of the adjusted exploratory model.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;345&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-e967f275.ClsK9YV1_Z2fOIuX.webp&quot; srcset=&quot;&quot;&gt;
If we compare the AIC to the first exploratory model without the direct path, we can see that the AIC of the second model with the direct path is lower, indicating a better model fit (the AIC weight lies almost exclusively on the second model).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;86&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-214cf25e.imkGIn1l_23ASG.webp&quot; srcset=&quot;&quot;&gt;
Looking at the direct and indirect effects in the “Mediation effects” table, we can see that the adjusted exploratory model estimates one direct (first row) and three indirect effects (rows two to four).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;131&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-fd6ec0c4.rmel0apr_1t3W1R.webp&quot; srcset=&quot;&quot;&gt;
The bootstrap confidence interval for the direct effect overlaps with zero but the intervals for the three indirect effects do not. That is, the adjusted exploratory model suggests a threefold causal process from age to fatigue: Via mood disturbances, hearing impairment, and via a path from hearing impairment to mood disturbances.&lt;/p&gt;
&lt;h2 id=&quot;using-conditional-process-models-with-caution&quot;&gt;Using Conditional Process Models with Caution&lt;/h2&gt;
&lt;p&gt;As has been emphasized by Rohrer et al. (2021), process models should be used with caution. They assume that the model structure is appropriate for the problem and data to identify causal effects. While the JASP Process module allows users to test the implications of the causal structure, other assumptions are much more difficult or even impossible to test: For example, to identify causal effects, all potential confounding variables must be accounted for in the model. This is difficult for indirect effects, even in experiments, because unobserved confounders can bias causal effects from the mediator to the dependent variable (Bullock et al., 2010; Rohrer et al., 2021). The Process module allows users to include confounders on all paths; however, they must be known and measured.&lt;/p&gt;
&lt;p&gt;Another common challenge is to correctly establish the direction of causality and ruling out alternative causal models (Kline, 2012; Rohrer et al., 2021; Fiedler et al., 2018). While in our example, it was easy to determine the causal direction from age to fatigue, the direction of causal paths between two mediators or the mediators and the dependent variable was much less evident. Some alternative causal models (stating different directions of causality) can be ruled out through causal implications. However, more often, the most appropriate causal model needs to be justified from theory or established through experimental manipulation.&lt;/p&gt;
&lt;p&gt;Furthermore, moderation effects as part of conditional process models pose several challenges to researchers, such as scale-dependency, choosing hypothesis-appropriate effect sizes, and distinguishing between causal interaction or effect modification (see Rohrer &amp;#x26; Arslan, 2021, for details, examples, and recommendations).&lt;/p&gt;
&lt;p&gt;If there is evidence that a model is misspecified, the adjustment must also be done with care to avoid overfitting (Textor et al., 2016). While the modification can be done in an exploratory fashion, the modified model should always be tested on an independent dataset to draw robust conclusions. At the same time, it should be consistent with theoretical expectations.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The new JASP Process module allows users to apply frequentist conditional process models using an intuitive and flexible interface. Using data from a study by McGarrigle et al. (2021), we demonstrated how users can estimate models involving multiple mediation and moderation effects. We also explained how the module enables users to test the local implications of specified models. In the case of violated implications, users can modify misspecified models accordingly. We believe that the JASP Process module can pave the way toward a more responsible and appropriate use of conditional process models. By providing an intuitive and flexible interface, we also aim to make process models more accessible to researchers and students.&lt;/p&gt;
&lt;h2 id=&quot;behind-the-project&quot;&gt;Behind the Project&lt;/h2&gt;
&lt;p&gt;This project is a collaboration between the JASP Team and the Netherlands eScience Center. As the national institute for research software, the eScience Center awards projects as part of calls for proposals. Instead of monetary funding, it provides in-kind support by Research Software Engineers to create innovative digital solutions. This project was granted as part of the Small-Scale Initiatives Digital Approaches to the Social Sciences call 2022.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Bullock, J. G., Green, D. P., &amp;#x26; Ha, S. E. (2010). Yes, but what’s the mechanism? (don’t expect an easy answer). &lt;em&gt;Journal of Personality and Social Psychology, 98&lt;/em&gt;(4), 550–558. &lt;a href=&quot;https://psycnet.apa.org/doi/10.1037/a0018933&quot;&gt;https://doi.org/10.1037/a0018933&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fiedler, K., Harris, C., &amp;#x26; Schott, M. (2018). Unwarranted inferences from statistical mediation tests — An analysis of articles published in 2015. &lt;em&gt;Journal of Experimental Social Psychology, 75&lt;/em&gt;, 95–102.&lt;a href=&quot;https://doi.org/10.1016/j.jesp.2017.11.008&quot;&gt; https://doi.org/10.1016/j.jesp.2017.11.008&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hayes, A. F., Montoya, A. K., &amp;#x26; Rockwood, N. J. (2017). The analysis of mechanisms and their contingencies: PROCESS versus structural equation modeling. &lt;em&gt;Australasian Marketing Journal, 25&lt;/em&gt;(1), 76–81. &lt;a href=&quot;https://doi.org/10.1016/j.ausmj.2017.02.001&quot;&gt;https://doi.org/10.1016/j.ausmj.2017.02.001&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022a). *Introduction to mediation, moderation, and conditional process analysis *(3rd Ed.). New York: The Guilford Press.&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022b). The PROCESS macro for SPSS, SAS, and R (Version 4.2) [Computer software]. &lt;a href=&quot;https://processmacro.org&quot;&gt;https://processmacro.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kline, R. B. (2012). Assumptions in structural equation modeling. In R. H. Hoyle (Ed.), &lt;em&gt;Handbook of structural equation modeling&lt;/em&gt; (pp. 111–125). Guilford Press.&lt;/p&gt;
&lt;p&gt;McGarrigle, R., Knight, S., Hornsby, B. W. Y., &amp;#x26; Mattys, S. (2021). Predictors of listening-related fatigue across the adult life span. &lt;em&gt;Psychological Science, 32&lt;/em&gt;(12), 1937–1951. &lt;a href=&quot;https://doi.org/10.1177/09567976211016410&quot;&gt;https://doi.org/10.1177/09567976211016410&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pearl, J. (2012). The causal foundations of structural equation modeling. In R. H. Hoyle (Ed.), &lt;em&gt;Handbook of structural equation modeling&lt;/em&gt; (pp. 68–91). Guilford Press.&lt;/p&gt;
&lt;p&gt;Rohrer, J. M., &amp;#x26; Arslan, R. C. (2021). Precise answers to vague questions: Issues with interactions. &lt;em&gt;Advances in Methods and Practices in Psychological Science, 4&lt;/em&gt;(2), 25152459211007368.&lt;a href=&quot;https://doi.org/10.1177/25152459211007368&quot;&gt; https://doi.org/10.1177/25152459211007368&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Rohrer, J. M., Hünermund, P., Arslan, R. C., Elson, M. (2022). That’s a lot to process! Pitfalls of popular path models. &lt;em&gt;Advances in Methods and Practices in Psychological Science, 5&lt;/em&gt;(2). &lt;a href=&quot;https://doi.org/10.1177/25152459221095827&quot;&gt;https://doi.org/10.1177/25152459221095827&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Textor, J., van der Zander, B., Gilthorpe, M. S., Liśkiewicz, M., &amp;#x26; Ellison, G. T. (2016). Robust causal inference using directed acyclic graphs: The R package ‘dagitty.’* International Journal of Epidemiology, 45*(6), 1887–1894. &lt;a href=&quot;https://doi.org/10.1093/ije/dyw341&quot;&gt;https://doi.org/10.1093/ije/dyw341&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 01 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/malte-luken/&quot;&gt;Malte Lüken&lt;/a&gt;, &lt;a href=&quot;https://juliarohrer.com/&quot;&gt;Julia M. Rohrer&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/thijs-vroegh/&quot;&gt;Thijs Vroegh&lt;/a&gt;, &lt;a href=&quot;https://www.uva.nl/en/profile/d/o/j.b.vandoorn/j.b.vandoorn.html&quot;&gt;Johnny van Doorn&lt;/a&gt;, and &lt;a href=&quot;https://www.uva.nl/en/profile/w/a/e.m.wagenmakers/e.m.wagenmakers.html&quot;&gt;Eric-Jan Wagenmakers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post is also published on the JASP &lt;em&gt;&lt;a href=&quot;https://jasp-stats.org/blog/&quot;&gt;&lt;em&gt;blog&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;448&quot; height=&quot;448&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-4987f6a5.B8-TxRvg_bKcUi.webp&quot; srcset=&quot;&quot;&gt;
In a recent &lt;a href=&quot;https://jasp-stats.org/2023/07/27/conditional-process-models/&quot;&gt;blog post&lt;/a&gt;, we announced the development of a JASP module for conditional process models, similar to the popular &lt;a href=&quot;https://www.processmacro.org/&quot;&gt;PROCESS&lt;/a&gt; macro for SPSS (Hayes, 2022a, 2022b). We can now share that we reached a milestone in our development efforts: The latest JASP release 18.2 includes a beta version of the Process module which allows users to apply frequentist process models. Besides covering many of the features of the SPSS macro, the JASP Process module provides a flexible and easy-to-use interface. It also makes the causal assumptions of process models more explicit and provides functionality to test them. In this blog post, we will introduce the main features of the module using a real-world example.&lt;/p&gt;
&lt;h2 id=&quot;mediation-moderation-and-conditional-process-models&quot;&gt;Mediation, Moderation, and Conditional Process Models&lt;/h2&gt;
&lt;p&gt;The aim of our module is to test models that involve mediation and moderation effects. A mediation effect is a causal chain between three variables. For example, when X → M, M → Y, and X → Y, then the causal effect from X to Y is (partly) mediated by M. A moderation effect implies that the relationship between two variables changes depending on a third variable, e.g., the effect X → M changes as the moderator W changes. A model that includes at least one mediation and one moderation effect is called a conditional process model because it makes assumptions about the causal process between variables, but the process is conditional on moderator variables (Hayes, 2022a).&lt;/p&gt;
&lt;p&gt;Conditional process models can also be conceptualized as parametric directed acyclic graphs (DAGs) or structural equation models (SEMs) that only include manifest variables (Pearl, 2012). We can use the properties of DAGs to test the implications of the causal model against data while SEMs are a useful framework for parameter estimation.&lt;/p&gt;
&lt;p&gt;The PROCESS macro for SPSS uses a regression-based approach to estimate process models which allows predictors (including independent variables, covariates, and mediators) to be correlated when there is no explicit causal path between them. Because the JASP Process module uses SEMs for model estimation, these correlations need to be explicitly allowed by the user. We believe this design choice prompts users to think more explicitly about the assumptions of their models. For a discussion of differences between PROCESS and SEM-based estimation, see Hayes et al. (2017).&lt;/p&gt;
&lt;h2 id=&quot;example-age-and-listening-related-fatigue&quot;&gt;Example: Age and Listening-related Fatigue&lt;/h2&gt;
&lt;p&gt;To illustrate the features of the Process module, we use openly available &lt;a href=&quot;https://osf.io/hc8n4/&quot;&gt;data&lt;/a&gt; from the study “Predictors of listening-related fatigue across the adult life span” by McGarrigle et al. (2021) which was published in &lt;em&gt;Psychological Science&lt;/em&gt;. The study investigates how different variables mediate and moderate the causal effect of age on listening-related fatigue using conditional process models. The analysis was pre-registered and the data set has a relatively large sample size (N = 281) which is roughly evenly distributed across age groups. These properties make the study a good example for conditional process analysis with observational data. As the authors of the original study, we assume that age is an exogenous (independent) variable which allows us to clearly identify the direction of the causal effect from age to fatigue.&lt;/p&gt;
&lt;p&gt;In our illustration of the module, we will reproduce the original analysis of the study but also test the implications of the hypothesized causal model. Note that our example only uses z-standardized variables which we renamed so they can be easily identified. The included candidates for mediators or moderators are auditory attention ability (“AudAttention”), perceived hearing impairment (“HearImpair”), perceived memory ability (“Memory”), and perceived mood disturbances (“MoodDisturb”). The example data set is also available in the internal JASP Data Library.&lt;/p&gt;
&lt;h2 id=&quot;the-basics-flexible-conditional-process-models-in-jasp&quot;&gt;The Basics: Flexible Conditional Process Models in JASP&lt;/h2&gt;
&lt;p&gt;To estimate a conditional process model in JASP, we first load the data set and enable the Process module by clicking the blue “+” sign in the top right corner and selecting “Process (beta)”.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;514&quot; height=&quot;133&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-5daca690.D4a8o04O_52N1O.webp&quot; srcset=&quot;&quot;&gt;
We then click on the available module to start the “Classic Process Model” analysis. First, we drag the variable “Fatigue” into the box &lt;em&gt;Dependent Variable&lt;/em&gt; and the variables “Age”, “AudAttention”, “HearImpair”, “Memory”, as well as “MoodDisturb” into the box &lt;em&gt;Continuous Predictors&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-d67427be.CuqoN1D3_1WUm0B.webp&quot; srcset=&quot;&quot;&gt;
In this example, we use a new interface that differs from the way process models are specified in SPSS. In the &lt;em&gt;Models&lt;/em&gt; section, we can construct the hypothesized model by adding causal paths between variables. We add three paths from “Age” to “Fatigue” by selecting the variables in the &lt;em&gt;From&lt;/em&gt; and &lt;em&gt;To&lt;/em&gt; dropdowns. For each path, we choose &lt;em&gt;Mediator&lt;/em&gt; in the &lt;em&gt;Process Type&lt;/em&gt; dropdown and select “AudAttention”, “HearImpair”, “Memory” as the &lt;em&gt;Process Variable&lt;/em&gt;, respectively.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;260&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-914a5c82.CZUD3SKO_DY1EA.webp&quot; srcset=&quot;&quot;&gt;
After completing each path, JASP provides the output of the estimated model including a path diagram showing the conceptual model structure. The path diagram resembles the hypothesized parallel mediation model after the third path.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-54c3bb79.D-2lbkwR_Z24fMe8.webp&quot; srcset=&quot;&quot;&gt;
Before we look at the results, we select &lt;em&gt;Bootstrap&lt;/em&gt; under &lt;em&gt;Method&lt;/em&gt; in the &lt;em&gt;Options&lt;/em&gt; section to enable bootstrapped confidence intervals; this is done because we cannot assume that indirect effects are normally distributed. Bootstrapping in JASP can take a few minutes to finish.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;240&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-3640843a.DI_uQAhp_ZqQfFL.webp&quot; srcset=&quot;&quot;&gt;
Below the path diagram, under “Parameter estimates”, the output shows a table with estimated parameters and effects. The second table “Mediation effects” contains the direct and indirect effects. As in the original study, the table shows a negative direct effect from age to fatigue and a positive indirect effect via perceived hearing impairment, both with bootstrapped confidence intervals excluding zero.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;161&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-9a885c40.CgRVYg-5_1fhwQ4.webp&quot; srcset=&quot;&quot;&gt;
To add a moderation effect to our model, we go back to the “Models” section and click the green “+” button in the top left corner to add a second model to our analysis. As in the previous model, we add three mediation paths from “Age” to “Fatigue”. Then we add a fourth path from “Age” to “Fatigue” and specify “MoodDisturb” as a moderator.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;285&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-9285476b.uUtk5FYI_2jvCSg.webp&quot; srcset=&quot;&quot;&gt;
Now, JASP provides output for both models. In the “Model summary” table, we can see that Model 2 has lower AIC and BIC values indicating a better model fit compared to Model 1 (the weights for both criteria lie almost exclusively on Model 2; AIC and BIC weights can be enabled in the “Options” section).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;85&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-b7f6e2f7.3qYghwGB_Z1Wnp4h.webp&quot; srcset=&quot;&quot;&gt;
Under “Parameter estimates” for Model 2, we can see that the direct effect of mood disturbances on fatigue is positive and its bootstrap confidence interval excludes zero. However, this is not the case for the interaction between age and mood disturbances. Thus, the model does not provide evidence for the hypothesized moderation effect, reproducing the result of the original study.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;251&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-d5746641.Dx5zFN9S_I3pWP.webp&quot; srcset=&quot;&quot;&gt;
How can we explain that Model 2 fits the data better but shows no evidence for a moderation effect? Model 2 does show a strong direct effect of mood disturbance on fatigue, which is not included in Model 1, and we assume that it leads to the better model fit. This suggests that we should include mood disturbances in our model but not as a moderator on the path between age and fatigue.&lt;/p&gt;
&lt;h2 id=&quot;advanced-testing-implications-of-causal-models&quot;&gt;Advanced: Testing Implications of Causal Models&lt;/h2&gt;
&lt;p&gt;Because the estimated effect from age to fatigue pointed in the opposite of the expected direction, McGarrigle et al. (2021) estimated alternative process models in an exploratory analysis. The Process module provides a useful tool that indicates where the assumed causal model does not fit the observed relationships in the data. DAGs have implications for the variables they involve, specifically, for which variables should be independent in the data (Pearl, 2012; Textor et al., 2016). These implications can be tested against data with (conditional) independence tests. In our model, all variables are assumed to be continuous and all relationships to be linear, so we test for (conditional) independence by estimating (partial) correlation coefficients.&lt;/p&gt;
&lt;p&gt;In JASP, we can test local implications by ticking the box &lt;em&gt;Local tests&lt;/em&gt; under *Tests &lt;em&gt;in the &lt;em&gt;Models&lt;/em&gt; section&lt;/em&gt;. *Here, we apply local tests to Model 2. Underneath the box, we can select the type of test we want to use, which is the default (&lt;em&gt;Linear&lt;/em&gt;) in our case. If the model contains categorical variables or relationships are assumed to be nonlinear, a different type should be chosen (e.g., &lt;em&gt;Loess&lt;/em&gt; or &lt;em&gt;Chi-square&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;260&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-ebfb687a.BQT4PiqY_fcxxF.webp&quot; srcset=&quot;&quot;&gt;
After ticking the &lt;em&gt;Local tests&lt;/em&gt; box, a new table appears in the output under “Local tests”. In the first three columns, the table shows which implied relationship is tested: For example, in the first row, auditory attention is assumed to be conditionally independent from hearing impairment given age. This can also be seen in the model diagram, which does not contain any direct arrows between the two variables (i.e., age accounts for the entire covariance between auditory attention and hearing impairment). The estimated partial correlation for this implied relationship is very small and not significant indicating that this implication is not violated. The opposite is true for row four: The model implies that age and mood disturbances are independent since there are no direct (or indirect) arrows between the two variables. However, the estimated correlation is negative and significant suggesting that the implication is violated and the model is misspecified. Rows five to seven also show significant (partial) correlations increasing the evidence that the model is inappropriate for the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;272&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-0ac11436.CN-zxQx6_Z15B66U.webp&quot; srcset=&quot;&quot;&gt;
Note that the PROCESS macro for SPSS behaves differently to our module by automatically allowing mediators to correlate. In a SEM context, this behavior can be imitated by estimating the residual covariances between mediators in the model. Ticking the box &lt;em&gt;Mediators&lt;/em&gt; under &lt;em&gt;Residual Covariances&lt;/em&gt; in the &lt;em&gt;Models&lt;/em&gt; section enables this.&lt;/p&gt;
&lt;h2 id=&quot;advanced-adjusting-the-model-in-an-exploratory-analysis&quot;&gt;Advanced: Adjusting the Model in an Exploratory Analysis&lt;/h2&gt;
&lt;p&gt;In the original study, McGarrigle et al. conducted an exploratory analysis where they used “MoodDisturb” as a mediator instead of a moderator. Our implication tests of the previous model with “MoodDisturb” provide a rationale for this: The data showed a negative correlation between “Age” and “MoodDisturb” which was not expected by the model. Our exploratory model should therefore account for this correlation by including a direct causal path from “Age” to “MoodDisturb”.&lt;/p&gt;
&lt;p&gt;We open a new Classical Process Model* analysis and select the same variables for &lt;em&gt;Dependent Variable&lt;/em&gt; and &lt;em&gt;Continuous Predictors&lt;/em&gt; as in the previous analysis. In our exploratory model, we specify “MoodDisturb” as a mediator between “Age” and “Fatigue”. We add “HearImpair” as a second mediator and leave out the other variables for simplicity.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;194&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-5fc4cb9f.D_nm5c-D_rYRHN.webp&quot; srcset=&quot;&quot;&gt;
In the output, we can see the conceptual diagram of our exploratory model.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;524&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-344aaf01.B803Zpd-_Z1IbXIe.webp&quot; srcset=&quot;&quot;&gt;
Again, we test the local implications of our new model. We can see that the model expects mood disturbances and hearing impairment to be conditionally independent given age, which is violated in the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;148&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-2aefc199.CP2Z6xVu_Z1GJIQd.webp&quot; srcset=&quot;&quot;&gt;
Thus, we need to further adjust our model, for example, by adding a direct causal path from “HearImpair” to “MoodDisturb” assuming that increased perceived hearing impairment leads to increased mood disturbance and not vice versa. In JASP, we can add a direct path by selecting &lt;em&gt;Direct&lt;/em&gt; in the &lt;em&gt;Process Type&lt;/em&gt; dropdown under the &lt;em&gt;Models&lt;/em&gt; section.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;259&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-6557220d.Cz0JTX88_Z1tv47X.webp&quot; srcset=&quot;&quot;&gt;
The output now shows the conceptual diagram of the adjusted exploratory model.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;345&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-e967f275.ClsK9YV1_Z2fOIuX.webp&quot; srcset=&quot;&quot;&gt;
If we compare the AIC to the first exploratory model without the direct path, we can see that the AIC of the second model with the direct path is lower, indicating a better model fit (the AIC weight lies almost exclusively on the second model).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;86&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-214cf25e.imkGIn1l_23ASG.webp&quot; srcset=&quot;&quot;&gt;
Looking at the direct and indirect effects in the “Mediation effects” table, we can see that the adjusted exploratory model estimates one direct (first row) and three indirect effects (rows two to four).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Causal Inference in JASP: The Process Module&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;131&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-fd6ec0c4.rmel0apr_1t3W1R.webp&quot; srcset=&quot;&quot;&gt;
The bootstrap confidence interval for the direct effect overlaps with zero but the intervals for the three indirect effects do not. That is, the adjusted exploratory model suggests a threefold causal process from age to fatigue: Via mood disturbances, hearing impairment, and via a path from hearing impairment to mood disturbances.&lt;/p&gt;
&lt;h2 id=&quot;using-conditional-process-models-with-caution&quot;&gt;Using Conditional Process Models with Caution&lt;/h2&gt;
&lt;p&gt;As has been emphasized by Rohrer et al. (2021), process models should be used with caution. They assume that the model structure is appropriate for the problem and data to identify causal effects. While the JASP Process module allows users to test the implications of the causal structure, other assumptions are much more difficult or even impossible to test: For example, to identify causal effects, all potential confounding variables must be accounted for in the model. This is difficult for indirect effects, even in experiments, because unobserved confounders can bias causal effects from the mediator to the dependent variable (Bullock et al., 2010; Rohrer et al., 2021). The Process module allows users to include confounders on all paths; however, they must be known and measured.&lt;/p&gt;
&lt;p&gt;Another common challenge is to correctly establish the direction of causality and ruling out alternative causal models (Kline, 2012; Rohrer et al., 2021; Fiedler et al., 2018). While in our example, it was easy to determine the causal direction from age to fatigue, the direction of causal paths between two mediators or the mediators and the dependent variable was much less evident. Some alternative causal models (stating different directions of causality) can be ruled out through causal implications. However, more often, the most appropriate causal model needs to be justified from theory or established through experimental manipulation.&lt;/p&gt;
&lt;p&gt;Furthermore, moderation effects as part of conditional process models pose several challenges to researchers, such as scale-dependency, choosing hypothesis-appropriate effect sizes, and distinguishing between causal interaction or effect modification (see Rohrer &amp;#x26; Arslan, 2021, for details, examples, and recommendations).&lt;/p&gt;
&lt;p&gt;If there is evidence that a model is misspecified, the adjustment must also be done with care to avoid overfitting (Textor et al., 2016). While the modification can be done in an exploratory fashion, the modified model should always be tested on an independent dataset to draw robust conclusions. At the same time, it should be consistent with theoretical expectations.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The new JASP Process module allows users to apply frequentist conditional process models using an intuitive and flexible interface. Using data from a study by McGarrigle et al. (2021), we demonstrated how users can estimate models involving multiple mediation and moderation effects. We also explained how the module enables users to test the local implications of specified models. In the case of violated implications, users can modify misspecified models accordingly. We believe that the JASP Process module can pave the way toward a more responsible and appropriate use of conditional process models. By providing an intuitive and flexible interface, we also aim to make process models more accessible to researchers and students.&lt;/p&gt;
&lt;h2 id=&quot;behind-the-project&quot;&gt;Behind the Project&lt;/h2&gt;
&lt;p&gt;This project is a collaboration between the JASP Team and the Netherlands eScience Center. As the national institute for research software, the eScience Center awards projects as part of calls for proposals. Instead of monetary funding, it provides in-kind support by Research Software Engineers to create innovative digital solutions. This project was granted as part of the Small-Scale Initiatives Digital Approaches to the Social Sciences call 2022.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Bullock, J. G., Green, D. P., &amp;#x26; Ha, S. E. (2010). Yes, but what’s the mechanism? (don’t expect an easy answer). &lt;em&gt;Journal of Personality and Social Psychology, 98&lt;/em&gt;(4), 550–558. &lt;a href=&quot;https://psycnet.apa.org/doi/10.1037/a0018933&quot;&gt;https://doi.org/10.1037/a0018933&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Fiedler, K., Harris, C., &amp;#x26; Schott, M. (2018). Unwarranted inferences from statistical mediation tests — An analysis of articles published in 2015. &lt;em&gt;Journal of Experimental Social Psychology, 75&lt;/em&gt;, 95–102.&lt;a href=&quot;https://doi.org/10.1016/j.jesp.2017.11.008&quot;&gt; https://doi.org/10.1016/j.jesp.2017.11.008&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hayes, A. F., Montoya, A. K., &amp;#x26; Rockwood, N. J. (2017). The analysis of mechanisms and their contingencies: PROCESS versus structural equation modeling. &lt;em&gt;Australasian Marketing Journal, 25&lt;/em&gt;(1), 76–81. &lt;a href=&quot;https://doi.org/10.1016/j.ausmj.2017.02.001&quot;&gt;https://doi.org/10.1016/j.ausmj.2017.02.001&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022a). *Introduction to mediation, moderation, and conditional process analysis *(3rd Ed.). New York: The Guilford Press.&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022b). The PROCESS macro for SPSS, SAS, and R (Version 4.2) [Computer software]. &lt;a href=&quot;https://processmacro.org&quot;&gt;https://processmacro.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kline, R. B. (2012). Assumptions in structural equation modeling. In R. H. Hoyle (Ed.), &lt;em&gt;Handbook of structural equation modeling&lt;/em&gt; (pp. 111–125). Guilford Press.&lt;/p&gt;
&lt;p&gt;McGarrigle, R., Knight, S., Hornsby, B. W. Y., &amp;#x26; Mattys, S. (2021). Predictors of listening-related fatigue across the adult life span. &lt;em&gt;Psychological Science, 32&lt;/em&gt;(12), 1937–1951. &lt;a href=&quot;https://doi.org/10.1177/09567976211016410&quot;&gt;https://doi.org/10.1177/09567976211016410&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pearl, J. (2012). The causal foundations of structural equation modeling. In R. H. Hoyle (Ed.), &lt;em&gt;Handbook of structural equation modeling&lt;/em&gt; (pp. 68–91). Guilford Press.&lt;/p&gt;
&lt;p&gt;Rohrer, J. M., &amp;#x26; Arslan, R. C. (2021). Precise answers to vague questions: Issues with interactions. &lt;em&gt;Advances in Methods and Practices in Psychological Science, 4&lt;/em&gt;(2), 25152459211007368.&lt;a href=&quot;https://doi.org/10.1177/25152459211007368&quot;&gt; https://doi.org/10.1177/25152459211007368&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Rohrer, J. M., Hünermund, P., Arslan, R. C., Elson, M. (2022). That’s a lot to process! Pitfalls of popular path models. &lt;em&gt;Advances in Methods and Practices in Psychological Science, 5&lt;/em&gt;(2). &lt;a href=&quot;https://doi.org/10.1177/25152459221095827&quot;&gt;https://doi.org/10.1177/25152459221095827&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Textor, J., van der Zander, B., Gilthorpe, M. S., Liśkiewicz, M., &amp;#x26; Ellison, G. T. (2016). Robust causal inference using directed acyclic graphs: The R package ‘dagitty.’* International Journal of Epidemiology, 45*(6), 1887–1894. &lt;a href=&quot;https://doi.org/10.1093/ije/dyw341&quot;&gt;https://doi.org/10.1093/ije/dyw341&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/causal-inference-in-jasp-the-process-mod-4987f6a5.B8-TxRvg.png" medium="image"/><author>Malte Lüken</author></item><item><title>Talking about energy-efficient GPU computing at SC23</title><link>https://blog2.esciencecenter.nl/posts/2024-01-16---talking-about-energy-efficient-gpu-computing-at-sc23</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2024-01-16---talking-about-energy-efficient-gpu-computing-at-sc23</guid><description>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;November is the time for Supercomputing, or &lt;a href=&quot;https://sc23.supercomputing.org/&quot;&gt;SC&lt;/a&gt; as it is called nowadays, and in 2023 the largest High-Performance Computing (HPC) conference in the world took place in Denver, USA, from the 12th to the 17th of that month.&lt;/p&gt;
&lt;p&gt;It was a week packed with talks, workshops, tutorials, exhibitors from all over the world, social gatherings, announcements and all of the usual SC glamour. While the eyes of the world were all pointed at the &lt;a href=&quot;https://top500.org/&quot;&gt;TOP500&lt;/a&gt; to see if Aurora would become the fastest supercomputer on the planet (spoiler: it did not; &lt;a href=&quot;https://www.hpcwire.com/off-the-wire/argonne-shares-strong-early-performance-numbers-for-aurora-supercomputer/&quot;&gt;Aurora sits at number 2 behind Frontier&lt;/a&gt;), there were many highlights of the conference.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Talking about energy-efficient GPU computing at SC23&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-ef98a387.DdIm_n1F_QMNK.webp&quot; srcset=&quot;&quot;&gt;
Ben, Floris-Jan, Stijn, and Alessio standing with the SC23 logo at the Colorado Convention Center in Denver. Photo by Floris-Jan Willemsen.On the technical front, it is clear that Graphics Processing Units (GPUs) are here to stay, as they provide more than 70% of the total TOP500 FLOPs (Floating Point Operations per second); in other words, most of the computational power of the largest supercomputers in the world comes from GPUs.&lt;/p&gt;
&lt;p&gt;With new systems being installed, GPUs from at least three different vendors (i.e. AMD, Intel, NVIDIA) being used, and &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3624062.3624178&quot;&gt;a dozen or so programming models available&lt;/a&gt; for programming them, one of the hottest topics of SC23 was performance portability.&lt;/p&gt;
&lt;p&gt;Performance portability means that software written originally for one platform can not only run on a different platform but even provide comparable performance. This is a very important property for scientific software, which typically has a lifespan longer than that of the life of any modern supercomputer.&lt;/p&gt;
&lt;p&gt;Another hot topic was energy efficiency. Being able to perform more work for the same energy budget, by increasing energy efficiency, is a societal issue that is becoming increasingly pressing in the HPC community. An entire workshop was dedicated to “Sustainable Supercomputing”, with discussions ranging from how to make code more efficient, to where to build a data center to utilize renewable energy. The workshop also highlighted how simply making users aware of the energy consumption of scientific code can have an impact, especially at the political level.&lt;/p&gt;
&lt;p&gt;A small delegation from the Netherlands eScience Center comprised of Ben van Werkhoven, Alessio Sclocco, Stijn Heldens and Floris-Jan Willemsen attended SC23 to present a tutorial on “&lt;a href=&quot;https://sc23.conference-program.com/presentation/?id=tut127&amp;#x26;sess=sess217&quot;&gt;Energy-Efficient GPU Computing&lt;/a&gt;” on the first Sunday of the conference; the same engineers taught a tutorial about &lt;a href=&quot;https://blog2.esciencecenter.nl/kernel-tuner-tutorial-at-supercomputing-2021-d97444d6961a&quot;&gt;Kernel Tuner&lt;/a&gt; at SC21 in St. Louis, USA. The new tutorial was also mentioned on a slide in the opening of the “&lt;a href=&quot;https://www.hpcwire.com/2023/11/29/sc23-the-ethics-of-supercomputing/&quot;&gt;Ethics in HPC&lt;/a&gt;” session, as further proof that energy and sustainability are pressing concerns of the SC community in 2023.&lt;/p&gt;
&lt;p&gt;While energy efficiency in HPC is a broad topic, our focus was on what programmers can do to reduce the energy consumption, and thereby increase the efficiency, of their GPU code. The focus on GPUs does not only come from our expertise, but also reflects the fact that GPUs are what provide most of the computational power in current supercomputers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Talking about energy-efficient GPU computing at SC23&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;468&quot; height=&quot;351&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-abaffb9a.BVk59tYs_Z25QKHt.webp&quot; srcset=&quot;&quot;&gt;
Ben teaching part of the tutorial. Photo by Floris-Jan Willemsen.The tutorial was structured into four parts, each consisting of a brief lecture followed by a hands-on session. We strongly believe that participants learn more effectively when they can immediately apply what they have learned.&lt;/p&gt;
&lt;p&gt;The main takeaway of this first part could be summarized in the three action points for energy-efficient GPU code: (1) use energy-aware optimizations, (2) reduce data movement and (3) optimize clock frequencies.&lt;/p&gt;
&lt;p&gt;The second part of the tutorial was all about improving the performance of GPU code, since code that runs faster often ends up consuming less energy for the same amount of work, thereby being more efficient.&lt;/p&gt;
&lt;p&gt;After a lecture on GPU code optimizations, loosely based on a &lt;a href=&quot;https://dl.acm.org/doi/full/10.1145/3570638&quot;&gt;paper&lt;/a&gt; we published last spring, participants applied “kernel fusion” during the hands-on. This is an optimization that merges two GPU functions into one, in which it becomes apparent that optimizations can not only improve performance, but can also lower energy consumption.&lt;/p&gt;
&lt;p&gt;The third part focused on reducing data movement, crucial for energy efficiency, through mixed precision programming. This technique uses lower precision data types to decrease the number of bytes required for data storage, at the cost of introducing numerical error in the results. Fortunately, this error can be kept within an acceptable error margin by utilizing Kernel Tuner’s new capabilities for accuracy tuning, resulting in code that is faster, more energy-efficient, and shows minimal numerical error. Additionally, we showcased &lt;a href=&quot;https://github.com/KernelTuner/kernel_float&quot;&gt;Kernel Float&lt;/a&gt;, a C++ library developed by the eScience Center for mixed precision programming in NVIDIA CUDA. Participants had the chance to experiment with this in real GPU code during the hands-on session.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Talking about energy-efficient GPU computing at SC23&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;528&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-3c41024a.PExc6-Rx_1KQR3O.webp&quot; srcset=&quot;&quot;&gt;
Stijn talking about mixed precision in front of the audience. Photo by Floris-Jan Willemsen.In the last part of the tutorial, we looked at how Kernel Tuner can be used to automatically tune power capping values and clock frequencies. While just improving performance is generally enough to improve the energy efficiency of a program, we also showed how finding the optimal GPU core frequency can further improve efficiency.&lt;/p&gt;
&lt;p&gt;Moreover, based on the result of a &lt;a href=&quot;https://ieeexplore.ieee.org/abstract/document/10024022&quot;&gt;paper&lt;/a&gt; published last year, we also showed that by directing Kernel Tuner to use energy efficiency as its main metric in the search for the optimal configuration, it is possible to find the most energy-efficient configuration and even quantify the acceptable loss in performance to achieve it.&lt;/p&gt;
&lt;p&gt;The tutorial was well attended, with over 30 participants, and the interaction with the audience was very positive, especially during the hands-on. We received many questions, and some participants have already contacted us online in the Kernel Tuner &lt;a href=&quot;https://github.com/orgs/KernelTuner/discussions&quot;&gt;discussion forum&lt;/a&gt;. If you would like to know more about this tutorial, the &lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner_tutorial/blob/master/slides/2023_Supercomputing/SC23.pdf&quot;&gt;slides&lt;/a&gt; we used are available online (for free), and using Google Colab you can also run the hands-on exercises that we prepared for the event.&lt;/p&gt;
&lt;p&gt;Funding acknowledgments: the “Energy-Efficient GPU Computing” tutorial has been made possible by the CORTEX, COMPAS, and ESiWACE3 projects. The CORTEX project has received funding from the Dutch Research Council (NWO) in the framework of the NWA-ORC Call (file number NWA.1160.18.316). The COMPAS project has received funding from the Netherlands eScience Center (NLESC.OEC.2022.001). ESiWACE3 is funded by the European Union. This work has received funding from the European High Performance Computing Joint Undertaking (JU) and Spain, Netherlands, Germany, Sweden, Finland, Italy and France, under grant agreement No 1010930.&lt;/p&gt;</description><pubDate>Tue, 16 Jan 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;November is the time for Supercomputing, or &lt;a href=&quot;https://sc23.supercomputing.org/&quot;&gt;SC&lt;/a&gt; as it is called nowadays, and in 2023 the largest High-Performance Computing (HPC) conference in the world took place in Denver, USA, from the 12th to the 17th of that month.&lt;/p&gt;
&lt;p&gt;It was a week packed with talks, workshops, tutorials, exhibitors from all over the world, social gatherings, announcements and all of the usual SC glamour. While the eyes of the world were all pointed at the &lt;a href=&quot;https://top500.org/&quot;&gt;TOP500&lt;/a&gt; to see if Aurora would become the fastest supercomputer on the planet (spoiler: it did not; &lt;a href=&quot;https://www.hpcwire.com/off-the-wire/argonne-shares-strong-early-performance-numbers-for-aurora-supercomputer/&quot;&gt;Aurora sits at number 2 behind Frontier&lt;/a&gt;), there were many highlights of the conference.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Talking about energy-efficient GPU computing at SC23&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-ef98a387.DdIm_n1F_QMNK.webp&quot; srcset=&quot;&quot;&gt;
Ben, Floris-Jan, Stijn, and Alessio standing with the SC23 logo at the Colorado Convention Center in Denver. Photo by Floris-Jan Willemsen.On the technical front, it is clear that Graphics Processing Units (GPUs) are here to stay, as they provide more than 70% of the total TOP500 FLOPs (Floating Point Operations per second); in other words, most of the computational power of the largest supercomputers in the world comes from GPUs.&lt;/p&gt;
&lt;p&gt;With new systems being installed, GPUs from at least three different vendors (i.e. AMD, Intel, NVIDIA) being used, and &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3624062.3624178&quot;&gt;a dozen or so programming models available&lt;/a&gt; for programming them, one of the hottest topics of SC23 was performance portability.&lt;/p&gt;
&lt;p&gt;Performance portability means that software written originally for one platform can not only run on a different platform but even provide comparable performance. This is a very important property for scientific software, which typically has a lifespan longer than that of the life of any modern supercomputer.&lt;/p&gt;
&lt;p&gt;Another hot topic was energy efficiency. Being able to perform more work for the same energy budget, by increasing energy efficiency, is a societal issue that is becoming increasingly pressing in the HPC community. An entire workshop was dedicated to “Sustainable Supercomputing”, with discussions ranging from how to make code more efficient, to where to build a data center to utilize renewable energy. The workshop also highlighted how simply making users aware of the energy consumption of scientific code can have an impact, especially at the political level.&lt;/p&gt;
&lt;p&gt;A small delegation from the Netherlands eScience Center comprised of Ben van Werkhoven, Alessio Sclocco, Stijn Heldens and Floris-Jan Willemsen attended SC23 to present a tutorial on “&lt;a href=&quot;https://sc23.conference-program.com/presentation/?id=tut127&amp;#x26;sess=sess217&quot;&gt;Energy-Efficient GPU Computing&lt;/a&gt;” on the first Sunday of the conference; the same engineers taught a tutorial about &lt;a href=&quot;https://blog2.esciencecenter.nl/kernel-tuner-tutorial-at-supercomputing-2021-d97444d6961a&quot;&gt;Kernel Tuner&lt;/a&gt; at SC21 in St. Louis, USA. The new tutorial was also mentioned on a slide in the opening of the “&lt;a href=&quot;https://www.hpcwire.com/2023/11/29/sc23-the-ethics-of-supercomputing/&quot;&gt;Ethics in HPC&lt;/a&gt;” session, as further proof that energy and sustainability are pressing concerns of the SC community in 2023.&lt;/p&gt;
&lt;p&gt;While energy efficiency in HPC is a broad topic, our focus was on what programmers can do to reduce the energy consumption, and thereby increase the efficiency, of their GPU code. The focus on GPUs does not only come from our expertise, but also reflects the fact that GPUs are what provide most of the computational power in current supercomputers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Talking about energy-efficient GPU computing at SC23&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;468&quot; height=&quot;351&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-abaffb9a.BVk59tYs_Z25QKHt.webp&quot; srcset=&quot;&quot;&gt;
Ben teaching part of the tutorial. Photo by Floris-Jan Willemsen.The tutorial was structured into four parts, each consisting of a brief lecture followed by a hands-on session. We strongly believe that participants learn more effectively when they can immediately apply what they have learned.&lt;/p&gt;
&lt;p&gt;The main takeaway of this first part could be summarized in the three action points for energy-efficient GPU code: (1) use energy-aware optimizations, (2) reduce data movement and (3) optimize clock frequencies.&lt;/p&gt;
&lt;p&gt;The second part of the tutorial was all about improving the performance of GPU code, since code that runs faster often ends up consuming less energy for the same amount of work, thereby being more efficient.&lt;/p&gt;
&lt;p&gt;After a lecture on GPU code optimizations, loosely based on a &lt;a href=&quot;https://dl.acm.org/doi/full/10.1145/3570638&quot;&gt;paper&lt;/a&gt; we published last spring, participants applied “kernel fusion” during the hands-on. This is an optimization that merges two GPU functions into one, in which it becomes apparent that optimizations can not only improve performance, but can also lower energy consumption.&lt;/p&gt;
&lt;p&gt;The third part focused on reducing data movement, crucial for energy efficiency, through mixed precision programming. This technique uses lower precision data types to decrease the number of bytes required for data storage, at the cost of introducing numerical error in the results. Fortunately, this error can be kept within an acceptable error margin by utilizing Kernel Tuner’s new capabilities for accuracy tuning, resulting in code that is faster, more energy-efficient, and shows minimal numerical error. Additionally, we showcased &lt;a href=&quot;https://github.com/KernelTuner/kernel_float&quot;&gt;Kernel Float&lt;/a&gt;, a C++ library developed by the eScience Center for mixed precision programming in NVIDIA CUDA. Participants had the chance to experiment with this in real GPU code during the hands-on session.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Talking about energy-efficient GPU computing at SC23&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;528&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-3c41024a.PExc6-Rx_1KQR3O.webp&quot; srcset=&quot;&quot;&gt;
Stijn talking about mixed precision in front of the audience. Photo by Floris-Jan Willemsen.In the last part of the tutorial, we looked at how Kernel Tuner can be used to automatically tune power capping values and clock frequencies. While just improving performance is generally enough to improve the energy efficiency of a program, we also showed how finding the optimal GPU core frequency can further improve efficiency.&lt;/p&gt;
&lt;p&gt;Moreover, based on the result of a &lt;a href=&quot;https://ieeexplore.ieee.org/abstract/document/10024022&quot;&gt;paper&lt;/a&gt; published last year, we also showed that by directing Kernel Tuner to use energy efficiency as its main metric in the search for the optimal configuration, it is possible to find the most energy-efficient configuration and even quantify the acceptable loss in performance to achieve it.&lt;/p&gt;
&lt;p&gt;The tutorial was well attended, with over 30 participants, and the interaction with the audience was very positive, especially during the hands-on. We received many questions, and some participants have already contacted us online in the Kernel Tuner &lt;a href=&quot;https://github.com/orgs/KernelTuner/discussions&quot;&gt;discussion forum&lt;/a&gt;. If you would like to know more about this tutorial, the &lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner_tutorial/blob/master/slides/2023_Supercomputing/SC23.pdf&quot;&gt;slides&lt;/a&gt; we used are available online (for free), and using Google Colab you can also run the hands-on exercises that we prepared for the event.&lt;/p&gt;
&lt;p&gt;Funding acknowledgments: the “Energy-Efficient GPU Computing” tutorial has been made possible by the CORTEX, COMPAS, and ESiWACE3 projects. The CORTEX project has received funding from the Dutch Research Council (NWO) in the framework of the NWA-ORC Call (file number NWA.1160.18.316). The COMPAS project has received funding from the Netherlands eScience Center (NLESC.OEC.2022.001). ESiWACE3 is funded by the European Union. This work has received funding from the European High Performance Computing Joint Undertaking (JU) and Spain, Netherlands, Germany, Sweden, Finland, Italy and France, under grant agreement No 1010930.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/talking-about-energy-efficient-gpu-compu-ef98a387.DdIm_n1F.jpeg" medium="image"/><author>Alessio Sclocco</author></item><item><title>How to ensure that others can run your code</title><link>https://blog2.esciencecenter.nl/posts/2023-12-12---how-to-ensure-that-others-can-run-your-code</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-12-12---how-to-ensure-that-others-can-run-your-code</guid><description>&lt;p&gt;6&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://juliangonggrijp.com/&quot;&gt;Julian Gonggrijp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog was originally written for the &lt;em&gt;&lt;a href=&quot;https://www.uu.nl/en/news/how-to-ensure-that-others-can-run-your-code?utm_source=Maileon&amp;#x26;utm_medium=email&amp;#x26;utm_campaign=Centre+for+Digital+Humanities+Newsletter+-+November+2023&amp;#x26;utm_content=https%3A%2F%2Fwww.uu.nl%2Fen%2Fnews%2Fhow-to-ensure-that-others-can-run-your-code&quot;&gt;&lt;em&gt;Utrecht University (UU) website&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; by Scientific Programmer &lt;em&gt;&lt;a href=&quot;https://www.uu.nl/staff/JGonggrijp&quot;&gt;&lt;em&gt;Julian Gonggrijp&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;. We enjoyed this useful blog post, and hope you will too! If you’re looking for more resources on reusable code, also see &lt;em&gt;&lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/code-reuse&quot;&gt;&lt;em&gt;this chapter&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; in &lt;em&gt;&lt;a href=&quot;https://the-turing-way.netlify.app/index.html&quot;&gt;&lt;em&gt;the Turing Way&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is the last eScience Center blog post of 2023, but fear not! We will be back in January with lots more interesting writing from our Center.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to ensure that others can run your code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-ensure-that-others-can-run-your-c-4f7aaef5.sGCyufxL_ZouTsr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@thisisengineering?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;ThisisEngineering RAEng&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Imagine the following scenario. You need to analyze your research data. As is often the case in research, your analysis is going to be similar to, but not quite the same as, previous research. You look for existing software that can do the job for you, but nothing suits your situation. You decide this will be a good opportunity to brush up on your Python-fu. You sit down at your laptop, crack your knuckles and start hacking.&lt;/p&gt;
&lt;p&gt;The analysis is far from trivial; so is writing the code. You learn several new things along the way, some of which are interesting, gain a few grey hairs, spend two very late “afternoons” with a colleague to squash a notorious bug. Ten weeks and several hundred lines of code later, though, you manage to make it work. You toast with your colleague, present your analysis at a conference and get very positive responses. Your own software is a great success!&lt;/p&gt;
&lt;p&gt;At the conference, you meet a colleague from a different institution. She has a totally different dataset, but she might be able to apply the exact same analysis. You are excited: you might be onto a new methodology, worthy of several papers and a grant or two.&lt;/p&gt;
&lt;p&gt;A few months later, you hear back from your new acquaintance. She found time to experiment with your new method and she asks for your code. You were already prepared for that. Your code is on &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management/tools/software-and-computing/github-and-git&quot;&gt;GitHub&lt;/a&gt;, it has a README and you even thought of an open source license, so she can freely adapt the code if necessary. You eagerly send her the link.&lt;/p&gt;
&lt;p&gt;You don’t hear back for a while. After two months, you take a deep breath and send her an email. Was she able to get any useful results out of the analysis? Alas, it turns out she did not even reach that stage. She was unable to run your code, even with help from a student assistant from the computer science department. The code would crash with error messages that they could not get past. She went with the conventional analysis in the end; the results were not spectacular, but she managed to squeeze a publication out of it and moved on.&lt;/p&gt;
&lt;p&gt;Of course, you are disappointed. Did you just spend ten weeks of your life developing new software, only to find that it will never run through another dataset? Should you have hired a scientific programmer instead of writing the analysis yourself? Fortunately, at this point, you run into this blog, saving you from a depression.&lt;/p&gt;
&lt;h2 id=&quot;why-runnable-code-matters&quot;&gt;Why runnable code matters&lt;/h2&gt;
&lt;p&gt;In the above scenario, it is obvious that other people must be able to run your code because you want your method to be reusable. However, even if you write a quick one-off just for your own research, it is important to ensure that somebody else could run your code. There are two main reasons for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As Stefano mentioned &lt;a href=&quot;https://www.uu.nl/en/news/what-is-version-control-and-what-are-the-benefits-of-it-for-you&quot;&gt;in the previous blog&lt;/a&gt; on UU’s website, your future self is another person. You might upgrade or replace the PC on which you wrote the code and you might forget some of the preparatory magic incantations. Even in case of a one-off, you might want to run the code again in order to double-check your results, to add new datapoints or even just to impress your spouse. 😉 By ensuring that the code is easy to run while everything is still fresh in memory, you can save time (and dignity) in the future.&lt;/li&gt;
&lt;li&gt;By ensuring that your code is easy to run, you make it easy for others to repeat and verify your work. This can be a great way to convince people!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Making sure that code is easy to &lt;em&gt;run&lt;/em&gt; is different from ensuring that the code is easy to &lt;em&gt;read&lt;/em&gt;. The latter is certainly also worthwhile, for different reasons, but that is for another blog post.&lt;/p&gt;
&lt;p&gt;Making the code easy to run is also not exactly the same as making it easy to install. If you are serious about your software, you will likely think about publishing it to a package repository (which is also for another blog post) so that it can be easily found and installed, and you should! However, while this technically makes your code easy to run as well, this does not replace making it easy to run the code when obtaining a raw copy. At the very least, the future developer who is going to update the package will need to run it &lt;em&gt;without&lt;/em&gt; installing it from a package repository.&lt;/p&gt;
&lt;h2 id=&quot;why-is-code-not-runnable-out-of-the-box&quot;&gt;Why is code not runnable out of the box?&lt;/h2&gt;
&lt;p&gt;Let us be honest: it is &lt;em&gt;infuriating&lt;/em&gt; that code never runs out of the box. We can double-click any picture, PDF file or spreadsheet and it will just open and work, but for some reason, when it comes to code, we still seem to be living in the 1960s. Whenever we receive code from a colleague, we usually first have to install additional software, learn a few new skills, massage our data in just the right shape, take two non-obvious preparatory steps and make a rain dance before we can even hope to be able to run it. Then, there are the unexpected errors.&lt;/p&gt;
&lt;p&gt;While this is no excuse by itself, creating infrastructure that makes code easy to run is notoriously difficult. Code is run by other code, and that other code has to be extremely flexible in order to cater to all the possible applications. This by itself already requires highly specialized skills. On top of that, the software landscape is constantly moving because people keep finding new use cases for code, so everyone is constantly struggling to keep their own code compatible with somebody else’s code. Between all that effort, attention tends to be drawn away from keeping the software usable. There have been many honourable attempts at improving this situation, some of them quite successful — I will mention a few below — but even those projects cannot escape the constant struggle to keep their infrastructure current. Making running code as easy as a double-click remains elusive for now.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to ensure that others can run your code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-ensure-that-others-can-run-your-c-5683b09b.mD9iurTK_Z1v6WfR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@sigmund?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Sigmund&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;six-things-that-should-be-documented-for-any-code&quot;&gt;Six things that should be documented for any code&lt;/h2&gt;
&lt;p&gt;The first thing we can do, is to transfer as much knowledge as possible. The following checklist may help you to ensure that you include all the important details in your README. This is a &lt;a href=&quot;https://github.com/UUDigitalHumanitieslab/tscan/blob/master/README.md&quot;&gt;good example&lt;/a&gt; of a correct README.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why does your code exist? This may seem obvious, but you will be surprised at how often this information is left out. Knowing what your code is about will motivate prospective users to try it for the right reasons. It will also help clarify why things are done a certain way, why some features are included and others omitted.&lt;/li&gt;
&lt;li&gt;What other software needs to be installed before your code can be run? Most unexpected errors, where the software worked for the programmer but not for the user, are due to dependencies that are either missing or have a mismatching version. To prevent this, list the version of your programming language as well as all the packages that your code depends on and be as specific as possible about which versions are expected to work. Also explain how to obtain all dependencies.&lt;/li&gt;
&lt;li&gt;For what type of data is your code suitable and how should it be stored? Include everything relevant: file format versions, required and optional fields, column order, maximum input size, character encoding, etcetera.&lt;/li&gt;
&lt;li&gt;What steps should be followed to use your code? As programmers, this is usually the first thing we think of when writing a README, so it tends to be relatively well documented. For completeness, I will mention that you need to clearly distinguish between steps that need to be run every time or only the first time, describe the different modes/scenarios/use cases for which the code may be used, discuss optional and required arguments, and explain the expected output.&lt;/li&gt;
&lt;li&gt;How to reach out for help? Despite your best efforts to document everything, users can still run into trouble. Some users will not reach out unless you make them aware of the option. An email address is good, a link to an issue tracker on GitHub, Codeberg, GitLab or BitBucket is even better.&lt;/li&gt;
&lt;li&gt;Your software license. Technically, this does not really change how easy or difficult it is to run your code, but it does need to be in the README.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;dont-be-that-person&quot;&gt;Don’t be that person&lt;/h2&gt;
&lt;p&gt;Good documentation will get you a long way, but if there are intrinsic hurdles in your code, users will still struggle and possibly give up. The most common way for this to happen, is when the code is too specific to the current situation of the programmer.&lt;/p&gt;
&lt;p&gt;If your code only runs on your computer with your files on it, in January under easterly wind while the moon is waning, then your colleagues will likely find it difficult to run your code. Possibly more problematic is that, one year into the future, even you will not be able to run your code.&lt;/p&gt;
&lt;p&gt;For example, a line like the following is all too common in research software:&lt;/p&gt;
&lt;p&gt;DATAFILE = “C:\Users\Frank\Downloads\KNMI_klimaat_DeBilt_1980-2010.CSV”Hardcoded assumptions like these are errors waiting to happen. They can be avoided by making parameters like file paths user-configurable. For example, in Python, you can use the &lt;code&gt;[argparse](https://docs.python.org/3/library/argparse.html)&lt;/code&gt; module to accept file paths as command line arguments.&lt;/p&gt;
&lt;h2 id=&quot;use-helpful-standards&quot;&gt;Use helpful standards&lt;/h2&gt;
&lt;p&gt;As I mentioned before, there have been many attempts at improving the ease with which code can be run. None of them will reduce the effort to a double click, but the more you leverage these projects in your own code, the easier it will be to run it. I mention a few examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When working with Python, you can list your package dependencies in a &lt;code&gt;[requirements.txt](https://pip.pypa.io/en/stable/reference/requirements-file-format/)&lt;/code&gt; and tell users to run &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;. This saves users from installing the packages manually and ensures that they will have the right version of each package. Even better is to use a &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;virtual environment&lt;/a&gt; and manage the dependencies with &lt;code&gt;[pip-tools](https://pypi.org/project/pip-tools/)&lt;/code&gt; or &lt;code&gt;[pipenv](https://pypi.org/project/pipenv/)&lt;/code&gt; (which is a high-level wrapper around &lt;code&gt;venv&lt;/code&gt; and &lt;code&gt;pip-tools&lt;/code&gt;). Similar solutions exist for most other programming languages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Docker_(software)&quot;&gt;Docker&lt;/a&gt; can take the hassle out of installing software in general. You define what installation steps should be taken and how to start the software. Your colleagues only need to run Docker in order to make it happen. Installing Docker itself is a bit tricky, though, especially on Windows, so it is somewhat of a double-edged sword.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mybinder.org/&quot;&gt;Binder&lt;/a&gt; lets you publish and run Docker images in the cloud (i.e., on somebody else’s computer), so that your colleagues do not need to install Docker. It also automatically selects predefined Docker images for a few common types of projects, so you do not need to define your own Dockerfile. The only drawback is that the code tends to start with a noticable delay. It is mostly suitable for visualizations.&lt;/li&gt;
&lt;li&gt;Notebooks provide a handy way to combine scripts, visualizations and documentation in a single file that is relatively easy to run. Dependency management is greatly simplified in notebooks. &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt; is probably the most widely known notebook format, which supports Julia, Python and R (hence the name). A honorable mention goes to &lt;a href=&quot;https://plutojl.org/&quot;&gt;Pluto&lt;/a&gt;, which only supports Julia but which is probably the easiest and most intuitive notebook environment available. Both of these can run in the cloud using Binder. &lt;a href=&quot;https://cocalc.com/&quot;&gt;CoCalc&lt;/a&gt; and &lt;a href=&quot;https://colab.research.google.com/&quot;&gt;Google Colab&lt;/a&gt; provide additional cloud hosting options for Jupyter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;use-your-colleague-as-a-guinea-pig&quot;&gt;Use your colleague as a guinea pig&lt;/h2&gt;
&lt;p&gt;If you follow all the tips above, your code is easier to run than if you don’t. The best way to be sure, however, is to test-drive your code with an unsuspecting colleague. This colleague must not have been involved in the writing of the code. Ideally, you find a colleague who is interested in the problem domain, but who tends to use a different programming environment (or none at all) and a different operating system (so if you wrote your code on a Mac, try to find a tester who runs Windows). Don’t sit next to your colleague during testing; let them figure it out using only the documentation.&lt;/p&gt;
&lt;p&gt;If your tester can run your code without trouble, you can be fairly confident that your code is reusable. If not, keep adjusting until it is. Remember that it is always your code or your documentation that needs fixing, never your colleague.&lt;/p&gt;
&lt;h2 id=&quot;join-the-crowd&quot;&gt;Join the crowd&lt;/h2&gt;
&lt;p&gt;It is challenging to make reusable software, and you are not the first researcher to embark on this adventure. Utrecht University has various initiatives where you can meet fellow programmers and exchange tips and tricks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Research Data Management Support organizes a monthly &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management/workshops/programming-cafe&quot;&gt;Programming Café&lt;/a&gt; or hop by at the &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management/workshops/walk-in-hours-research-data-and-software&quot;&gt;Walk-in Hours&lt;/a&gt; at the &lt;a href=&quot;https://maps.app.goo.gl/YV7fGkAtcT9PmWjdA&quot;&gt;Library Utrecht Science Park&lt;/a&gt; that are held every Monday afternoon.&lt;/li&gt;
&lt;li&gt;If you happen to work at the Utrecht University Faculty of Humanities, you can also visit the weekly &lt;a href=&quot;https://cdh.uu.nl/walk-in-hours/&quot;&gt;Digital Humanities walk-in hour&lt;/a&gt;, or email the &lt;a href=&quot;https://cdh.uu.nl/&quot;&gt;Centre for Digital Humanities&lt;/a&gt; at any time for advice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wish you much inspiration and fun on your voyage!&lt;/p&gt;</description><pubDate>Tue, 12 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;6&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://juliangonggrijp.com/&quot;&gt;Julian Gonggrijp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog was originally written for the &lt;em&gt;&lt;a href=&quot;https://www.uu.nl/en/news/how-to-ensure-that-others-can-run-your-code?utm_source=Maileon&amp;#x26;utm_medium=email&amp;#x26;utm_campaign=Centre+for+Digital+Humanities+Newsletter+-+November+2023&amp;#x26;utm_content=https%3A%2F%2Fwww.uu.nl%2Fen%2Fnews%2Fhow-to-ensure-that-others-can-run-your-code&quot;&gt;&lt;em&gt;Utrecht University (UU) website&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; by Scientific Programmer &lt;em&gt;&lt;a href=&quot;https://www.uu.nl/staff/JGonggrijp&quot;&gt;&lt;em&gt;Julian Gonggrijp&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;. We enjoyed this useful blog post, and hope you will too! If you’re looking for more resources on reusable code, also see &lt;em&gt;&lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/code-reuse&quot;&gt;&lt;em&gt;this chapter&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; in &lt;em&gt;&lt;a href=&quot;https://the-turing-way.netlify.app/index.html&quot;&gt;&lt;em&gt;the Turing Way&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This is the last eScience Center blog post of 2023, but fear not! We will be back in January with lots more interesting writing from our Center.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to ensure that others can run your code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-ensure-that-others-can-run-your-c-4f7aaef5.sGCyufxL_ZouTsr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@thisisengineering?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;ThisisEngineering RAEng&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Imagine the following scenario. You need to analyze your research data. As is often the case in research, your analysis is going to be similar to, but not quite the same as, previous research. You look for existing software that can do the job for you, but nothing suits your situation. You decide this will be a good opportunity to brush up on your Python-fu. You sit down at your laptop, crack your knuckles and start hacking.&lt;/p&gt;
&lt;p&gt;The analysis is far from trivial; so is writing the code. You learn several new things along the way, some of which are interesting, gain a few grey hairs, spend two very late “afternoons” with a colleague to squash a notorious bug. Ten weeks and several hundred lines of code later, though, you manage to make it work. You toast with your colleague, present your analysis at a conference and get very positive responses. Your own software is a great success!&lt;/p&gt;
&lt;p&gt;At the conference, you meet a colleague from a different institution. She has a totally different dataset, but she might be able to apply the exact same analysis. You are excited: you might be onto a new methodology, worthy of several papers and a grant or two.&lt;/p&gt;
&lt;p&gt;A few months later, you hear back from your new acquaintance. She found time to experiment with your new method and she asks for your code. You were already prepared for that. Your code is on &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management/tools/software-and-computing/github-and-git&quot;&gt;GitHub&lt;/a&gt;, it has a README and you even thought of an open source license, so she can freely adapt the code if necessary. You eagerly send her the link.&lt;/p&gt;
&lt;p&gt;You don’t hear back for a while. After two months, you take a deep breath and send her an email. Was she able to get any useful results out of the analysis? Alas, it turns out she did not even reach that stage. She was unable to run your code, even with help from a student assistant from the computer science department. The code would crash with error messages that they could not get past. She went with the conventional analysis in the end; the results were not spectacular, but she managed to squeeze a publication out of it and moved on.&lt;/p&gt;
&lt;p&gt;Of course, you are disappointed. Did you just spend ten weeks of your life developing new software, only to find that it will never run through another dataset? Should you have hired a scientific programmer instead of writing the analysis yourself? Fortunately, at this point, you run into this blog, saving you from a depression.&lt;/p&gt;
&lt;h2 id=&quot;why-runnable-code-matters&quot;&gt;Why runnable code matters&lt;/h2&gt;
&lt;p&gt;In the above scenario, it is obvious that other people must be able to run your code because you want your method to be reusable. However, even if you write a quick one-off just for your own research, it is important to ensure that somebody else could run your code. There are two main reasons for this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As Stefano mentioned &lt;a href=&quot;https://www.uu.nl/en/news/what-is-version-control-and-what-are-the-benefits-of-it-for-you&quot;&gt;in the previous blog&lt;/a&gt; on UU’s website, your future self is another person. You might upgrade or replace the PC on which you wrote the code and you might forget some of the preparatory magic incantations. Even in case of a one-off, you might want to run the code again in order to double-check your results, to add new datapoints or even just to impress your spouse. 😉 By ensuring that the code is easy to run while everything is still fresh in memory, you can save time (and dignity) in the future.&lt;/li&gt;
&lt;li&gt;By ensuring that your code is easy to run, you make it easy for others to repeat and verify your work. This can be a great way to convince people!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Making sure that code is easy to &lt;em&gt;run&lt;/em&gt; is different from ensuring that the code is easy to &lt;em&gt;read&lt;/em&gt;. The latter is certainly also worthwhile, for different reasons, but that is for another blog post.&lt;/p&gt;
&lt;p&gt;Making the code easy to run is also not exactly the same as making it easy to install. If you are serious about your software, you will likely think about publishing it to a package repository (which is also for another blog post) so that it can be easily found and installed, and you should! However, while this technically makes your code easy to run as well, this does not replace making it easy to run the code when obtaining a raw copy. At the very least, the future developer who is going to update the package will need to run it &lt;em&gt;without&lt;/em&gt; installing it from a package repository.&lt;/p&gt;
&lt;h2 id=&quot;why-is-code-not-runnable-out-of-the-box&quot;&gt;Why is code not runnable out of the box?&lt;/h2&gt;
&lt;p&gt;Let us be honest: it is &lt;em&gt;infuriating&lt;/em&gt; that code never runs out of the box. We can double-click any picture, PDF file or spreadsheet and it will just open and work, but for some reason, when it comes to code, we still seem to be living in the 1960s. Whenever we receive code from a colleague, we usually first have to install additional software, learn a few new skills, massage our data in just the right shape, take two non-obvious preparatory steps and make a rain dance before we can even hope to be able to run it. Then, there are the unexpected errors.&lt;/p&gt;
&lt;p&gt;While this is no excuse by itself, creating infrastructure that makes code easy to run is notoriously difficult. Code is run by other code, and that other code has to be extremely flexible in order to cater to all the possible applications. This by itself already requires highly specialized skills. On top of that, the software landscape is constantly moving because people keep finding new use cases for code, so everyone is constantly struggling to keep their own code compatible with somebody else’s code. Between all that effort, attention tends to be drawn away from keeping the software usable. There have been many honourable attempts at improving this situation, some of them quite successful — I will mention a few below — but even those projects cannot escape the constant struggle to keep their infrastructure current. Making running code as easy as a double-click remains elusive for now.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to ensure that others can run your code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-ensure-that-others-can-run-your-c-5683b09b.mD9iurTK_Z1v6WfR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@sigmund?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Sigmund&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;six-things-that-should-be-documented-for-any-code&quot;&gt;Six things that should be documented for any code&lt;/h2&gt;
&lt;p&gt;The first thing we can do, is to transfer as much knowledge as possible. The following checklist may help you to ensure that you include all the important details in your README. This is a &lt;a href=&quot;https://github.com/UUDigitalHumanitieslab/tscan/blob/master/README.md&quot;&gt;good example&lt;/a&gt; of a correct README.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why does your code exist? This may seem obvious, but you will be surprised at how often this information is left out. Knowing what your code is about will motivate prospective users to try it for the right reasons. It will also help clarify why things are done a certain way, why some features are included and others omitted.&lt;/li&gt;
&lt;li&gt;What other software needs to be installed before your code can be run? Most unexpected errors, where the software worked for the programmer but not for the user, are due to dependencies that are either missing or have a mismatching version. To prevent this, list the version of your programming language as well as all the packages that your code depends on and be as specific as possible about which versions are expected to work. Also explain how to obtain all dependencies.&lt;/li&gt;
&lt;li&gt;For what type of data is your code suitable and how should it be stored? Include everything relevant: file format versions, required and optional fields, column order, maximum input size, character encoding, etcetera.&lt;/li&gt;
&lt;li&gt;What steps should be followed to use your code? As programmers, this is usually the first thing we think of when writing a README, so it tends to be relatively well documented. For completeness, I will mention that you need to clearly distinguish between steps that need to be run every time or only the first time, describe the different modes/scenarios/use cases for which the code may be used, discuss optional and required arguments, and explain the expected output.&lt;/li&gt;
&lt;li&gt;How to reach out for help? Despite your best efforts to document everything, users can still run into trouble. Some users will not reach out unless you make them aware of the option. An email address is good, a link to an issue tracker on GitHub, Codeberg, GitLab or BitBucket is even better.&lt;/li&gt;
&lt;li&gt;Your software license. Technically, this does not really change how easy or difficult it is to run your code, but it does need to be in the README.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;dont-be-that-person&quot;&gt;Don’t be that person&lt;/h2&gt;
&lt;p&gt;Good documentation will get you a long way, but if there are intrinsic hurdles in your code, users will still struggle and possibly give up. The most common way for this to happen, is when the code is too specific to the current situation of the programmer.&lt;/p&gt;
&lt;p&gt;If your code only runs on your computer with your files on it, in January under easterly wind while the moon is waning, then your colleagues will likely find it difficult to run your code. Possibly more problematic is that, one year into the future, even you will not be able to run your code.&lt;/p&gt;
&lt;p&gt;For example, a line like the following is all too common in research software:&lt;/p&gt;
&lt;p&gt;DATAFILE = “C:\Users\Frank\Downloads\KNMI_klimaat_DeBilt_1980-2010.CSV”Hardcoded assumptions like these are errors waiting to happen. They can be avoided by making parameters like file paths user-configurable. For example, in Python, you can use the &lt;code&gt;[argparse](https://docs.python.org/3/library/argparse.html)&lt;/code&gt; module to accept file paths as command line arguments.&lt;/p&gt;
&lt;h2 id=&quot;use-helpful-standards&quot;&gt;Use helpful standards&lt;/h2&gt;
&lt;p&gt;As I mentioned before, there have been many attempts at improving the ease with which code can be run. None of them will reduce the effort to a double click, but the more you leverage these projects in your own code, the easier it will be to run it. I mention a few examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When working with Python, you can list your package dependencies in a &lt;code&gt;[requirements.txt](https://pip.pypa.io/en/stable/reference/requirements-file-format/)&lt;/code&gt; and tell users to run &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;. This saves users from installing the packages manually and ensures that they will have the right version of each package. Even better is to use a &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;virtual environment&lt;/a&gt; and manage the dependencies with &lt;code&gt;[pip-tools](https://pypi.org/project/pip-tools/)&lt;/code&gt; or &lt;code&gt;[pipenv](https://pypi.org/project/pipenv/)&lt;/code&gt; (which is a high-level wrapper around &lt;code&gt;venv&lt;/code&gt; and &lt;code&gt;pip-tools&lt;/code&gt;). Similar solutions exist for most other programming languages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Docker_(software)&quot;&gt;Docker&lt;/a&gt; can take the hassle out of installing software in general. You define what installation steps should be taken and how to start the software. Your colleagues only need to run Docker in order to make it happen. Installing Docker itself is a bit tricky, though, especially on Windows, so it is somewhat of a double-edged sword.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mybinder.org/&quot;&gt;Binder&lt;/a&gt; lets you publish and run Docker images in the cloud (i.e., on somebody else’s computer), so that your colleagues do not need to install Docker. It also automatically selects predefined Docker images for a few common types of projects, so you do not need to define your own Dockerfile. The only drawback is that the code tends to start with a noticable delay. It is mostly suitable for visualizations.&lt;/li&gt;
&lt;li&gt;Notebooks provide a handy way to combine scripts, visualizations and documentation in a single file that is relatively easy to run. Dependency management is greatly simplified in notebooks. &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt; is probably the most widely known notebook format, which supports Julia, Python and R (hence the name). A honorable mention goes to &lt;a href=&quot;https://plutojl.org/&quot;&gt;Pluto&lt;/a&gt;, which only supports Julia but which is probably the easiest and most intuitive notebook environment available. Both of these can run in the cloud using Binder. &lt;a href=&quot;https://cocalc.com/&quot;&gt;CoCalc&lt;/a&gt; and &lt;a href=&quot;https://colab.research.google.com/&quot;&gt;Google Colab&lt;/a&gt; provide additional cloud hosting options for Jupyter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;use-your-colleague-as-a-guinea-pig&quot;&gt;Use your colleague as a guinea pig&lt;/h2&gt;
&lt;p&gt;If you follow all the tips above, your code is easier to run than if you don’t. The best way to be sure, however, is to test-drive your code with an unsuspecting colleague. This colleague must not have been involved in the writing of the code. Ideally, you find a colleague who is interested in the problem domain, but who tends to use a different programming environment (or none at all) and a different operating system (so if you wrote your code on a Mac, try to find a tester who runs Windows). Don’t sit next to your colleague during testing; let them figure it out using only the documentation.&lt;/p&gt;
&lt;p&gt;If your tester can run your code without trouble, you can be fairly confident that your code is reusable. If not, keep adjusting until it is. Remember that it is always your code or your documentation that needs fixing, never your colleague.&lt;/p&gt;
&lt;h2 id=&quot;join-the-crowd&quot;&gt;Join the crowd&lt;/h2&gt;
&lt;p&gt;It is challenging to make reusable software, and you are not the first researcher to embark on this adventure. Utrecht University has various initiatives where you can meet fellow programmers and exchange tips and tricks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Research Data Management Support organizes a monthly &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management/workshops/programming-cafe&quot;&gt;Programming Café&lt;/a&gt; or hop by at the &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management/workshops/walk-in-hours-research-data-and-software&quot;&gt;Walk-in Hours&lt;/a&gt; at the &lt;a href=&quot;https://maps.app.goo.gl/YV7fGkAtcT9PmWjdA&quot;&gt;Library Utrecht Science Park&lt;/a&gt; that are held every Monday afternoon.&lt;/li&gt;
&lt;li&gt;If you happen to work at the Utrecht University Faculty of Humanities, you can also visit the weekly &lt;a href=&quot;https://cdh.uu.nl/walk-in-hours/&quot;&gt;Digital Humanities walk-in hour&lt;/a&gt;, or email the &lt;a href=&quot;https://cdh.uu.nl/&quot;&gt;Centre for Digital Humanities&lt;/a&gt; at any time for advice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wish you much inspiration and fun on your voyage!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-to-ensure-that-others-can-run-your-c-4f7aaef5.sGCyufxL.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Machine Learning Machinery for Quantum Chemistry</title><link>https://blog2.esciencecenter.nl/posts/2023-12-06---machine-learning-machinery-for-quantum-chemistry</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-12-06---machine-learning-machinery-for-quantum-chemistry</guid><description>&lt;p&gt;Machine learning techniques are impacting all areas of science, and molecular simulations are not spared. This blog post shows how to make use of the tools and techniques developed for machine learning to facilitate high-accuracy electronic structure calculations.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-17dd1dc0.j4LJOKz3_Z24ylJU.webp&quot; srcset=&quot;&quot;&gt;
Quantum chemistry, the application of quantum mechanics to the study of molecular systems, is a powerful approach to design better materials, more efficient catalysts, and even better drugs. If you are reading this text on a fancy 4K &lt;a href=&quot;https://en.wikipedia.org/wiki/OLED&quot;&gt;OLED&lt;/a&gt; screen, chances are that quantum chemistry was used to fine-tune the light emission properties of the molecules that are shooting photons at you.&lt;/p&gt;
&lt;p&gt;Quantum chemistry is, however, not a single technique, but the aggregation of many approaches that have been developed over many decades by many people. Some methods are computationally inexpensive and usually not so accurate, while others require important computational resources but can reach a higher degree of accuracy.&lt;/p&gt;
&lt;p&gt;Quantum Monte Carlo (QMC) simulations are particularly interesting as they can reach a high degree of accuracy and can also be efficiently parallelized on very large computational resources. Many software packages, like &lt;a href=&quot;https://github.com/filippi-claudia/champ&quot;&gt;CHAMP &lt;/a&gt;or &lt;a href=&quot;https://github.com/TREX-CoE/qmcchem2&quot;&gt;QMC=CHEM&lt;/a&gt;, provide solutions to perform QMC simulations and have been used in countless scientific publications.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;300&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-d0f2af93.VGSxax-R_Z20BpCy.webp&quot; srcset=&quot;&quot;&gt;
Illustration of the QMC approach. We first define a wave function containing tunable parameters. We sample the associated density and compute the system’s energy and its gradient w.r.t. the tunable parameters. We then update the value of the parameters and start again until we find the minimum value of the total energyTo understand how QMC works, let’s consider a small molecule of, let’s say, benzene. To keep things simple we are going to assume that all the electrons of the molecule are located around its center following a Gaussian distribution of variable width. To compute the energy of the molecule, we first sample this distribution to obtain representative configurations of the electronic positions. This can be done via a variety of techniques, for example, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm&quot;&gt;Metropolis-Hastings&lt;/a&gt; algorithm. Computing the energy of the electrons in these configurations and taking averaging them can finally be used to approximate the total energy of the molecule.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Variational_method_(quantum_mechanics)&quot;&gt;cornerstone of quantum chemistry&lt;/a&gt; tells us that the most accurate description of the molecule is obtained for the lowest value of its total energy. In our simple example, we can tweak the width of the Gaussian distribution until we find the minimal value of the total energy. If you now think, &lt;em&gt;hey that almost looks like a machine learning problem&lt;/em&gt;, you’re not completely wrong. All we need is to encode the wave function in some sort of neural network.&lt;/p&gt;
&lt;h2 id=&quot;lets-start-with-a-toy-problem&quot;&gt;Let’s start with a toy problem&lt;/h2&gt;
&lt;p&gt;Let’s first look at a toy problem that you may have encountered in your undergraduate studies: a single particle in a one-dimensional potential. We pick here the Morse potential as it is simple enough yet non-trivial.&lt;/p&gt;
&lt;p&gt;We choose here to use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Radial_basis_function_network&quot;&gt;radial basis function (RBF) neural network&lt;/a&gt; to encode the wave function of this one-dimensional potential. In our RBF network, the input node encodes the position of the particle and each hidden node computes the value of a particular Gaussian function at this location. These values are then summed up on the output node to yield the value of the wave function at the particle’s location. This architecture therefore expresses the wave function of our particle as a sum of Gaussian functions, which is sufficient for this particular problem.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-c2c21611.O8Y3_5tb_8m2AB.webp&quot; srcset=&quot;&quot;&gt;
Schrodinet in action. The solver optimizes the positions, widths, and heights of all the Gaussian functions composing the RBF network to minimize the energy of the system.&lt;/p&gt;
&lt;h2 id=&quot;qmctorch-for-molecules&quot;&gt;QMCTorch for molecules&lt;/h2&gt;
&lt;p&gt;While replacing first-year university students with simple neural networks is appealing, it would be even better to apply the same machinery to more complex cases, for example, molecules. Unfortunately, the wave functions of molecular systems are much more complex than the one of a single particle trapped in a one-dimensional potential. All the electrons of the molecule interact with each other and also with the atomic nuclei and everything becomes very complicated very quickly. Fortunately, many scientists have given us a good understanding of the ingredients that should make up the wave functions of these systems.&lt;/p&gt;
&lt;p&gt;Armed with this vast amount of knowledge, and a little bit of tenacity, we have developed &lt;a href=&quot;https://github.com/NLESC-JCER/QMCTOrch&quot;&gt;&lt;strong&gt;QMCTorch&lt;/strong&gt;&lt;/a&gt;** **a Python package that allows to run QMC simulations of molecular systems using neural network wave functions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;392&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-5f17922c.BW2PfwlE_Z3DJiy.webp&quot; srcset=&quot;&quot;&gt;
Representation of the neural network that encodes the wave function in QMCTorch. Starting from the atomic and electronic coordinates, different layers progressively compute the value of the wave function.Neural networks in QMCTorch take the positions of the electrons and atoms as inputs and compute the value of the wave function as an output. In between the input and output layers, many layers compute the different ingredients involved in the definition of the molecular wave function. These layers have parameters that can be specified by the user or extracted from external chemistry codes such as &lt;a href=&quot;https://pyscf.org/&quot;&gt;pyscf&lt;/a&gt; or &lt;a href=&quot;https://www.scm.com/product/adf/&quot;&gt;ADF&lt;/a&gt;. These parameters can be further optimized to lead to an even more accurate wave function.&lt;/p&gt;
&lt;p&gt;As the name indicates, QMCTorch is based on the popular deep learning framework &lt;a href=&quot;https://pytorch.org/&quot;&gt;PyTorch &lt;/a&gt;and leverages automatic differentiation to compute various derivatives needed in the optimization process. The use of automatic differentiation allows users to easily explore new flavors of the wave function without having to analytically compute all its derivatives. QMCTorch can also make use of multiple GPUs to accelerate the simulations thanks to the native capabilities of PyTorch and the distributed deep learning library &lt;a href=&quot;https://horovod.ai/&quot;&gt;Horovd&lt;/a&gt;. For more information on QMCTorch, go see the &lt;a href=&quot;https://qmctorch.readthedocs.io/en/latest/&quot;&gt;code documentation&lt;/a&gt; or the &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.05472&quot;&gt;paper&lt;/a&gt; in the Journal of Open Source Software.&lt;/p&gt;
&lt;p&gt;To use the code we first need to define a molecule through its atomic positions. QMCTorch allows for a few different flavors of wave functions to be used and we therefore need to pick one. We also have to define a sampler and an optimizer to compute and minimize the total energy of the system. Of course, each component has a lot of knobs that can be tweaked and that can greatly affect the result of the calculation.&lt;/p&gt;
&lt;p&gt;from torch import optim
from qmctorch.scf import Molecule
from qmctorch.wavefunction import SlaterJastrow,
from qmctorch.solver import Solver
from qmctorch.sampler import Metropolis&lt;/p&gt;
&lt;h1 id=&quot;create-a-h2-molecule&quot;&gt;create a H2 molecule&lt;/h1&gt;
&lt;p&gt;mol = Molecule(atom=‘H 0 0 -0.69; H 0 0 0.69’)&lt;/p&gt;
&lt;h1 id=&quot;create-the-wave-function-object&quot;&gt;create the wave function object&lt;/h1&gt;
&lt;p&gt;wf = SlaterJastrow(mol, cuda=True)&lt;/p&gt;
&lt;h1 id=&quot;create-a-sampler&quot;&gt;create a sampler&lt;/h1&gt;
&lt;p&gt;sampler = Metropolis(nwalkers=1000, nstep=2000,
step_size=0.2, nelec=wf.nelec,
cuda=True)&lt;/p&gt;
&lt;h1 id=&quot;create-an-optimizer&quot;&gt;create an optimizer&lt;/h1&gt;
&lt;p&gt;opt = optim.Adam(wf.parameters(), lr=1E-3)&lt;/p&gt;
&lt;h1 id=&quot;create-a-solver-and-optimize-the-wave-function&quot;&gt;create a solver and optimize the wave function&lt;/h1&gt;
&lt;p&gt;solver = Solver(wf=wf, sampler=sampler, optimizer=opt)
solver.run(250)We can then ask QMCTorch to optimize the wave function of a molecule or even to optimize its geometry. The illustration below shows the result of such a geometry optimization for a water molecule. Starting from a non-ideal atomic arrangement, where the oxygen and the two hydrogens are aligned, the optimization process quickly brings the atoms in a more favorable conformation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;660&quot; height=&quot;736&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-6746e7cc.DjPEOi5U_2aa3C6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-now&quot;&gt;What now?&lt;/h2&gt;
&lt;p&gt;Many research groups have also developed their own solutions, like &lt;a href=&quot;https://arxiv.org/pdf/1909.02487.pdf&quot;&gt;FermiNet &lt;/a&gt;or &lt;a href=&quot;https://arxiv.org/abs/1909.08423&quot;&gt;PauliNet &lt;/a&gt;and many others, to use machine learning techniques to accelerate and improve QMC calculations. Their approaches often use more convoluted functional forms than the ones used in QMCTorch. This allows for greater flexibility in the wave function and therefore more accurate results that have the potential to expand our chemical intuition.&lt;/p&gt;
&lt;p&gt;One could, of course, argue that the energy change during a QMC optimization is so small that it does not justify the large amount of computing resources thrown at it. But if you want your red pixel to be red and not reddish/brown this is the level of accuracy needed!&lt;/p&gt;</description><pubDate>Wed, 06 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Machine learning techniques are impacting all areas of science, and molecular simulations are not spared. This blog post shows how to make use of the tools and techniques developed for machine learning to facilitate high-accuracy electronic structure calculations.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-17dd1dc0.j4LJOKz3_Z24ylJU.webp&quot; srcset=&quot;&quot;&gt;
Quantum chemistry, the application of quantum mechanics to the study of molecular systems, is a powerful approach to design better materials, more efficient catalysts, and even better drugs. If you are reading this text on a fancy 4K &lt;a href=&quot;https://en.wikipedia.org/wiki/OLED&quot;&gt;OLED&lt;/a&gt; screen, chances are that quantum chemistry was used to fine-tune the light emission properties of the molecules that are shooting photons at you.&lt;/p&gt;
&lt;p&gt;Quantum chemistry is, however, not a single technique, but the aggregation of many approaches that have been developed over many decades by many people. Some methods are computationally inexpensive and usually not so accurate, while others require important computational resources but can reach a higher degree of accuracy.&lt;/p&gt;
&lt;p&gt;Quantum Monte Carlo (QMC) simulations are particularly interesting as they can reach a high degree of accuracy and can also be efficiently parallelized on very large computational resources. Many software packages, like &lt;a href=&quot;https://github.com/filippi-claudia/champ&quot;&gt;CHAMP &lt;/a&gt;or &lt;a href=&quot;https://github.com/TREX-CoE/qmcchem2&quot;&gt;QMC=CHEM&lt;/a&gt;, provide solutions to perform QMC simulations and have been used in countless scientific publications.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;300&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-d0f2af93.VGSxax-R_Z20BpCy.webp&quot; srcset=&quot;&quot;&gt;
Illustration of the QMC approach. We first define a wave function containing tunable parameters. We sample the associated density and compute the system’s energy and its gradient w.r.t. the tunable parameters. We then update the value of the parameters and start again until we find the minimum value of the total energyTo understand how QMC works, let’s consider a small molecule of, let’s say, benzene. To keep things simple we are going to assume that all the electrons of the molecule are located around its center following a Gaussian distribution of variable width. To compute the energy of the molecule, we first sample this distribution to obtain representative configurations of the electronic positions. This can be done via a variety of techniques, for example, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm&quot;&gt;Metropolis-Hastings&lt;/a&gt; algorithm. Computing the energy of the electrons in these configurations and taking averaging them can finally be used to approximate the total energy of the molecule.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Variational_method_(quantum_mechanics)&quot;&gt;cornerstone of quantum chemistry&lt;/a&gt; tells us that the most accurate description of the molecule is obtained for the lowest value of its total energy. In our simple example, we can tweak the width of the Gaussian distribution until we find the minimal value of the total energy. If you now think, &lt;em&gt;hey that almost looks like a machine learning problem&lt;/em&gt;, you’re not completely wrong. All we need is to encode the wave function in some sort of neural network.&lt;/p&gt;
&lt;h2 id=&quot;lets-start-with-a-toy-problem&quot;&gt;Let’s start with a toy problem&lt;/h2&gt;
&lt;p&gt;Let’s first look at a toy problem that you may have encountered in your undergraduate studies: a single particle in a one-dimensional potential. We pick here the Morse potential as it is simple enough yet non-trivial.&lt;/p&gt;
&lt;p&gt;We choose here to use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Radial_basis_function_network&quot;&gt;radial basis function (RBF) neural network&lt;/a&gt; to encode the wave function of this one-dimensional potential. In our RBF network, the input node encodes the position of the particle and each hidden node computes the value of a particular Gaussian function at this location. These values are then summed up on the output node to yield the value of the wave function at the particle’s location. This architecture therefore expresses the wave function of our particle as a sum of Gaussian functions, which is sufficient for this particular problem.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-c2c21611.O8Y3_5tb_8m2AB.webp&quot; srcset=&quot;&quot;&gt;
Schrodinet in action. The solver optimizes the positions, widths, and heights of all the Gaussian functions composing the RBF network to minimize the energy of the system.&lt;/p&gt;
&lt;h2 id=&quot;qmctorch-for-molecules&quot;&gt;QMCTorch for molecules&lt;/h2&gt;
&lt;p&gt;While replacing first-year university students with simple neural networks is appealing, it would be even better to apply the same machinery to more complex cases, for example, molecules. Unfortunately, the wave functions of molecular systems are much more complex than the one of a single particle trapped in a one-dimensional potential. All the electrons of the molecule interact with each other and also with the atomic nuclei and everything becomes very complicated very quickly. Fortunately, many scientists have given us a good understanding of the ingredients that should make up the wave functions of these systems.&lt;/p&gt;
&lt;p&gt;Armed with this vast amount of knowledge, and a little bit of tenacity, we have developed &lt;a href=&quot;https://github.com/NLESC-JCER/QMCTOrch&quot;&gt;&lt;strong&gt;QMCTorch&lt;/strong&gt;&lt;/a&gt;** **a Python package that allows to run QMC simulations of molecular systems using neural network wave functions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;392&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-5f17922c.BW2PfwlE_Z3DJiy.webp&quot; srcset=&quot;&quot;&gt;
Representation of the neural network that encodes the wave function in QMCTorch. Starting from the atomic and electronic coordinates, different layers progressively compute the value of the wave function.Neural networks in QMCTorch take the positions of the electrons and atoms as inputs and compute the value of the wave function as an output. In between the input and output layers, many layers compute the different ingredients involved in the definition of the molecular wave function. These layers have parameters that can be specified by the user or extracted from external chemistry codes such as &lt;a href=&quot;https://pyscf.org/&quot;&gt;pyscf&lt;/a&gt; or &lt;a href=&quot;https://www.scm.com/product/adf/&quot;&gt;ADF&lt;/a&gt;. These parameters can be further optimized to lead to an even more accurate wave function.&lt;/p&gt;
&lt;p&gt;As the name indicates, QMCTorch is based on the popular deep learning framework &lt;a href=&quot;https://pytorch.org/&quot;&gt;PyTorch &lt;/a&gt;and leverages automatic differentiation to compute various derivatives needed in the optimization process. The use of automatic differentiation allows users to easily explore new flavors of the wave function without having to analytically compute all its derivatives. QMCTorch can also make use of multiple GPUs to accelerate the simulations thanks to the native capabilities of PyTorch and the distributed deep learning library &lt;a href=&quot;https://horovod.ai/&quot;&gt;Horovd&lt;/a&gt;. For more information on QMCTorch, go see the &lt;a href=&quot;https://qmctorch.readthedocs.io/en/latest/&quot;&gt;code documentation&lt;/a&gt; or the &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.05472&quot;&gt;paper&lt;/a&gt; in the Journal of Open Source Software.&lt;/p&gt;
&lt;p&gt;To use the code we first need to define a molecule through its atomic positions. QMCTorch allows for a few different flavors of wave functions to be used and we therefore need to pick one. We also have to define a sampler and an optimizer to compute and minimize the total energy of the system. Of course, each component has a lot of knobs that can be tweaked and that can greatly affect the result of the calculation.&lt;/p&gt;
&lt;p&gt;from torch import optim
from qmctorch.scf import Molecule
from qmctorch.wavefunction import SlaterJastrow,
from qmctorch.solver import Solver
from qmctorch.sampler import Metropolis&lt;/p&gt;
&lt;h1 id=&quot;create-a-h2-molecule&quot;&gt;create a H2 molecule&lt;/h1&gt;
&lt;p&gt;mol = Molecule(atom=‘H 0 0 -0.69; H 0 0 0.69’)&lt;/p&gt;
&lt;h1 id=&quot;create-the-wave-function-object&quot;&gt;create the wave function object&lt;/h1&gt;
&lt;p&gt;wf = SlaterJastrow(mol, cuda=True)&lt;/p&gt;
&lt;h1 id=&quot;create-a-sampler&quot;&gt;create a sampler&lt;/h1&gt;
&lt;p&gt;sampler = Metropolis(nwalkers=1000, nstep=2000,
step_size=0.2, nelec=wf.nelec,
cuda=True)&lt;/p&gt;
&lt;h1 id=&quot;create-an-optimizer&quot;&gt;create an optimizer&lt;/h1&gt;
&lt;p&gt;opt = optim.Adam(wf.parameters(), lr=1E-3)&lt;/p&gt;
&lt;h1 id=&quot;create-a-solver-and-optimize-the-wave-function&quot;&gt;create a solver and optimize the wave function&lt;/h1&gt;
&lt;p&gt;solver = Solver(wf=wf, sampler=sampler, optimizer=opt)
solver.run(250)We can then ask QMCTorch to optimize the wave function of a molecule or even to optimize its geometry. The illustration below shows the result of such a geometry optimization for a water molecule. Starting from a non-ideal atomic arrangement, where the oxygen and the two hydrogens are aligned, the optimization process quickly brings the atoms in a more favorable conformation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning Machinery for Quantum Chemistry&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;660&quot; height=&quot;736&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-6746e7cc.DjPEOi5U_2aa3C6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-now&quot;&gt;What now?&lt;/h2&gt;
&lt;p&gt;Many research groups have also developed their own solutions, like &lt;a href=&quot;https://arxiv.org/pdf/1909.02487.pdf&quot;&gt;FermiNet &lt;/a&gt;or &lt;a href=&quot;https://arxiv.org/abs/1909.08423&quot;&gt;PauliNet &lt;/a&gt;and many others, to use machine learning techniques to accelerate and improve QMC calculations. Their approaches often use more convoluted functional forms than the ones used in QMCTorch. This allows for greater flexibility in the wave function and therefore more accurate results that have the potential to expand our chemical intuition.&lt;/p&gt;
&lt;p&gt;One could, of course, argue that the energy change during a QMC optimization is so small that it does not justify the large amount of computing resources thrown at it. But if you want your red pixel to be red and not reddish/brown this is the level of accuracy needed!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/machine-learning-machinery-for-quantum-c-d0f2af93.VGSxax-R.png" medium="image"/><author>Nicolas Renaud</author></item><item><title>Navigating research software policies: Insights from the Dutch research community</title><link>https://blog2.esciencecenter.nl/posts/2023-11-28---navigating-research-software-policies-insights-from-the-dutc</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-11-28---navigating-research-software-policies-insights-from-the-dutc</guid><description>&lt;h1 id=&quot;navigating-research-software-policies-insights-from-the-dutch-research-community&quot;&gt;&lt;strong&gt;Navigating research software policies: Insights from the Dutch research community&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Imagine you’re a researcher who developed a brilliant piece of software that may be useful to many. Maybe it’s a single script that cleans data in a specific format. Or perhaps it’s a larger piece of research infrastructure, that could be a crucial part of the workflow for nearly all researchers in your discipline. You may be wondering how to make your software available in a way that safeguards your, your institute’s, the users’ and science’s interests. What if the rules around doing this would all be thoroughly outlined to you by your institute?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Navigating research software policies: Insights from the Dutch research community&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/navigating-research-software-policies-in-ea981e66.xiUpiGH6_2udFCa.webp&quot; srcset=&quot;&quot;&gt;
Just as there are many decisions to make about how to license software, there are many decisions to be made when drafting an institutional software policy. All possible decision paths can seem overwhelming, which is why &lt;a href=&quot;https://www.rd-alliance.org/groups/rda-resa-policies-research-organisations-research-software-pro4rs&quot;&gt;PRO4RS&lt;/a&gt; is helping policy makers and researchers with this task. Photo by &lt;a href=&quot;https://unsplash.com/@distinctmind?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Distinct Mind&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;The eScience Center, NWO, TU Delft and the VU organized an event on 3 October 2023 where we discussed with representatives from more than 20 Dutch knowledge organizations (research institutes, research infrastructure providers, research funding organizations, universities, UMCs and universities of applied sciences) how to develop and implement institutional research software policies, and what the challenges may be in embarking on such a project.&lt;/p&gt;
&lt;h3 id=&quot;why-institutional-software-policies&quot;&gt;Why Institutional Software Policies?&lt;/h3&gt;
&lt;p&gt;To provide valuable context, &lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;Software Sustainability Institute&lt;/a&gt; director &lt;a href=&quot;https://www.epcc.ed.ac.uk/about-us/our-team/prof-neil-chue-hong&quot;&gt;professor Neil Chue Hong&lt;/a&gt; laid out why research software policies are important. He started his presentation by explaining that institutional policy generally serves as a crucial element in effecting cultural change. Policies provide various purposes, such as encouraging good practices, ensuring legal compliance, maintaining ethical norms, reducing institutional risk, improving operational efficiency, and promoting and enhancing a mission.&lt;/p&gt;
&lt;p&gt;The cultural change research software policies specifically encourage are open research and open science practices. They typically focus on promoting reuse of research software through recommendations about licenses and research output management plans (data or software management plans). On an individual level, these policies should encourage authors and developers to cite software and make their software citable. On an institutional level, research software policies are used to mitigate institutional risk in areas such as cybersecurity, procurement, asset management, research ethics, and integrity.&lt;/p&gt;
&lt;p&gt;Research software policies are important for good practices in research software management and open science. Despite this, many organizations do not yet have an institutional research software policy. During our event, those interested in setting up or further developing their own policies answered questions about the situation at their institutes via Mentimeter. From the answers to those questions, it became clear that most of the Dutch institutes that were represented (77%) do not have a policy on research software (yet). However, about half of those institutes are currently (planning on) developing one.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Navigating research software policies: Insights from the Dutch research community&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/navigating-research-software-policies-in-9a3d4359.BPnRmbVf_sF4JU.webp&quot; srcset=&quot;&quot;&gt;
Participants during the 3 October 2023 event discussed what should be included in their institutional research software policy, and how to practically go about developing this policy.&lt;/p&gt;
&lt;h3 id=&quot;drafting-and-implementing-research-software-policies&quot;&gt;Drafting and Implementing Research Software Policies&lt;/h3&gt;
&lt;p&gt;Drafting research software policies poses several challenges. First, &lt;a href=&quot;https://doi.org/10.5281/zenodo.5504016&quot;&gt;defining research software can be difficult&lt;/a&gt;, as the same piece of software may be categorized as research software or not depending on its &lt;a href=&quot;https://blog2.esciencecenter.nl/defining-the-roles-of-research-software-21535a43f23&quot;&gt;role&lt;/a&gt;, or the context where it is produced and used. Second, &lt;a href=&quot;https://blog2.esciencecenter.nl/defining-the-roles-of-research-software-21535a43f23&quot;&gt;the complexity and maturity of research software vary&lt;/a&gt;, ranging from &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.4940273&quot;&gt;analysis code to prototype tools to mature research software infrastructure&lt;/a&gt;. Institutions need to account for all these levels of complexity in their policies without being overly prescriptive or incomplete for different cases. Third, multiple stakeholders, including senior management, IT services, libraries, enterprise and innovation offices, and open science/open source policy offices, need to be involved in creating research software policies. The challenge lies in avoiding a situation where “if everyone is responsible, no one is”. Fourth, research software policies are interconnected with other university policies and processes. Integrating a new policy with existing policies can raise new questions and challenges.&lt;/p&gt;
&lt;p&gt;The challenges pointed out by Neil Chue Hong and the audience were reflected in &lt;a href=&quot;https://www.universiteitleiden.nl/medewerkers/jacko-koster#tab-1&quot;&gt;Jacko Koster&lt;/a&gt;’s talk. Jacko provided a snapshot of Leiden University’s work in progress in developing such a policy. The variety of parties involved, as well as the many aspects of research software, make for a complicated process that involves discussing with many stakeholders at all levels of the university. &lt;a href=&quot;https://www.tudelft.nl/library/research-data-management/r/support/data-stewardship/contact/paula-martinez-lavanchy&quot;&gt;Paula Martinez Lavanchy&lt;/a&gt; from TU Delft discussed her university’s success story. In 2021, she led the drafting and implementation of &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.4629661&quot;&gt;TU Delft’s research software policy&lt;/a&gt; together with a group of TU Delft’s employees. She started by putting together a working group that encompassed relevant stakeholders from all areas: researchers, librarians, data stewards, valorisation center employees, legal services and the ICT department. The inclusion of many different parties and integration of all their perspectives was crucial to her success.&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.4629661)Click&quot;&gt;https://zenodo.org/doi/10.5281/zenodo.4629661)Click&lt;/a&gt; the image to read TU Delft’s research software policyTU Delft’s experience provides valuable insights into what can make institutional research software policies effective. For example, TU Delft has made sure that the implementation and software workflow described by the policy is solidly integrated into training for staff. This approach fits well with findings by the PASTEUR40A project, which investigated success factors in implementing policies at universities. In their project, they investigated Open Access policies at 120 different universities. Drawing from these experiences with implementing Open Access policies, they wrote &lt;a href=&quot;https://doi.org/10.5281/zenodo.35635&quot;&gt;a paper&lt;/a&gt; that concluded that effective policies should be minimally burdensome, mandatory, linked to evaluation and incentives, and applied at the optimal time in the lifecycle. Additionally, they must align with funders’ policies for university staff to adhere to them.&lt;/p&gt;
&lt;p&gt;The challenge of drafting and implementing research software policies for individuals at knowledge institutions has inspired the formation of the recently approved RDA working group PRO4RS, a joint initiative by ReSA and the RDA, with support of the RDA Tiger project. For those wondering how to go about drafting an institutional research software policy, this group is working on an overview of existing policies. Next steps will include putting together resources on how to achieve policy change at an institute, and to develop a common framework for research software policy, specifically. You can &lt;a href=&quot;https://www.rd-alliance.org/groups/rda-resa-policies-research-organisations-research-software-pro4rs&quot;&gt;join this group&lt;/a&gt; to receive updates and information about the group’s work, as well as sessions during the RDA plenary (two times per year). A summary of the working group’s most recent (autumn 2023) RDA plenary session is available &lt;a href=&quot;https://www.rd-alliance.org/group/rda-resa-policies-research-organisations-research-software-pro4rs/post/summary-rda-plenary-21&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The participants at our event brainstormed about what should be part of their research software policies. They agreed that at a minimum, a definition of research software should be included in the policy. Most participants agreed that it should include rules about licensing and sharing software, too. An interesting point of discussion was the question whether guidelines on good practices in software development should be part of a research software policy, and where to draw the line regarding this. For example, some participants agreed that pointers on research software quality and a commitment to training researchers on good practices should be part of a research software policy, while others did not.&lt;/p&gt;
&lt;h3 id=&quot;next-steps&quot;&gt;Next steps**&lt;/h3&gt;
&lt;p&gt;We invite anyone interested in staying up to date about institutional research software policies to **attend &lt;strong&gt;&lt;a href=&quot;https://www.eventbrite.com/e/institutional-research-software-policies-tickets-765126843987?aff=oddtdtcreator&quot;&gt;&lt;strong&gt;our webinar&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt; on 16 January 2024 to continue the conversation about institutional research software policies in the Netherlands. **During this webinar, we plan to include an update from the PRO4RS RDA working group and reiterate the most important points from our workshop on 3 October to those who missed it. Sign up &lt;a href=&quot;https://www.eventbrite.com/e/institutional-research-software-policies-tickets-765126843987?aff=oddtdtcreator&quot;&gt;here&lt;/a&gt; to join the webinar.&lt;/p&gt;
&lt;p&gt;If you are interested in developing institutional research software policies, you can** subscribe to updates from the PRO4RS RDA working group **&lt;a href=&quot;https://www.rd-alliance.org/groups/rda-resa-policies-research-organisations-research-software-pro4rs&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, on 23 April 2024, the eScience Center is jointly organising &lt;a href=&quot;https://www.eventbrite.com/e/national-research-software-day-tickets-761242004327?aff=oddtdtcreator&quot;&gt;&lt;strong&gt;National Research Software Day&lt;/strong&gt;&lt;/a&gt;, where policy makers, research supporters and community leaders will come together to discuss all things research software. You can find out more and sign up for this day here.&lt;/p&gt;
&lt;p&gt;Written by Lieke de Boer. Thanks to Carlos Martinez-Ortiz, Maaike de Jong, Maria Cruz and Meron Vermaas for comments.*&lt;/p&gt;</description><pubDate>Tue, 28 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;navigating-research-software-policies-insights-from-the-dutch-research-community&quot;&gt;&lt;strong&gt;Navigating research software policies: Insights from the Dutch research community&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Imagine you’re a researcher who developed a brilliant piece of software that may be useful to many. Maybe it’s a single script that cleans data in a specific format. Or perhaps it’s a larger piece of research infrastructure, that could be a crucial part of the workflow for nearly all researchers in your discipline. You may be wondering how to make your software available in a way that safeguards your, your institute’s, the users’ and science’s interests. What if the rules around doing this would all be thoroughly outlined to you by your institute?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Navigating research software policies: Insights from the Dutch research community&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/navigating-research-software-policies-in-ea981e66.xiUpiGH6_2udFCa.webp&quot; srcset=&quot;&quot;&gt;
Just as there are many decisions to make about how to license software, there are many decisions to be made when drafting an institutional software policy. All possible decision paths can seem overwhelming, which is why &lt;a href=&quot;https://www.rd-alliance.org/groups/rda-resa-policies-research-organisations-research-software-pro4rs&quot;&gt;PRO4RS&lt;/a&gt; is helping policy makers and researchers with this task. Photo by &lt;a href=&quot;https://unsplash.com/@distinctmind?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Distinct Mind&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;The eScience Center, NWO, TU Delft and the VU organized an event on 3 October 2023 where we discussed with representatives from more than 20 Dutch knowledge organizations (research institutes, research infrastructure providers, research funding organizations, universities, UMCs and universities of applied sciences) how to develop and implement institutional research software policies, and what the challenges may be in embarking on such a project.&lt;/p&gt;
&lt;h3 id=&quot;why-institutional-software-policies&quot;&gt;Why Institutional Software Policies?&lt;/h3&gt;
&lt;p&gt;To provide valuable context, &lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;Software Sustainability Institute&lt;/a&gt; director &lt;a href=&quot;https://www.epcc.ed.ac.uk/about-us/our-team/prof-neil-chue-hong&quot;&gt;professor Neil Chue Hong&lt;/a&gt; laid out why research software policies are important. He started his presentation by explaining that institutional policy generally serves as a crucial element in effecting cultural change. Policies provide various purposes, such as encouraging good practices, ensuring legal compliance, maintaining ethical norms, reducing institutional risk, improving operational efficiency, and promoting and enhancing a mission.&lt;/p&gt;
&lt;p&gt;The cultural change research software policies specifically encourage are open research and open science practices. They typically focus on promoting reuse of research software through recommendations about licenses and research output management plans (data or software management plans). On an individual level, these policies should encourage authors and developers to cite software and make their software citable. On an institutional level, research software policies are used to mitigate institutional risk in areas such as cybersecurity, procurement, asset management, research ethics, and integrity.&lt;/p&gt;
&lt;p&gt;Research software policies are important for good practices in research software management and open science. Despite this, many organizations do not yet have an institutional research software policy. During our event, those interested in setting up or further developing their own policies answered questions about the situation at their institutes via Mentimeter. From the answers to those questions, it became clear that most of the Dutch institutes that were represented (77%) do not have a policy on research software (yet). However, about half of those institutes are currently (planning on) developing one.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Navigating research software policies: Insights from the Dutch research community&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/navigating-research-software-policies-in-9a3d4359.BPnRmbVf_sF4JU.webp&quot; srcset=&quot;&quot;&gt;
Participants during the 3 October 2023 event discussed what should be included in their institutional research software policy, and how to practically go about developing this policy.&lt;/p&gt;
&lt;h3 id=&quot;drafting-and-implementing-research-software-policies&quot;&gt;Drafting and Implementing Research Software Policies&lt;/h3&gt;
&lt;p&gt;Drafting research software policies poses several challenges. First, &lt;a href=&quot;https://doi.org/10.5281/zenodo.5504016&quot;&gt;defining research software can be difficult&lt;/a&gt;, as the same piece of software may be categorized as research software or not depending on its &lt;a href=&quot;https://blog2.esciencecenter.nl/defining-the-roles-of-research-software-21535a43f23&quot;&gt;role&lt;/a&gt;, or the context where it is produced and used. Second, &lt;a href=&quot;https://blog2.esciencecenter.nl/defining-the-roles-of-research-software-21535a43f23&quot;&gt;the complexity and maturity of research software vary&lt;/a&gt;, ranging from &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.4940273&quot;&gt;analysis code to prototype tools to mature research software infrastructure&lt;/a&gt;. Institutions need to account for all these levels of complexity in their policies without being overly prescriptive or incomplete for different cases. Third, multiple stakeholders, including senior management, IT services, libraries, enterprise and innovation offices, and open science/open source policy offices, need to be involved in creating research software policies. The challenge lies in avoiding a situation where “if everyone is responsible, no one is”. Fourth, research software policies are interconnected with other university policies and processes. Integrating a new policy with existing policies can raise new questions and challenges.&lt;/p&gt;
&lt;p&gt;The challenges pointed out by Neil Chue Hong and the audience were reflected in &lt;a href=&quot;https://www.universiteitleiden.nl/medewerkers/jacko-koster#tab-1&quot;&gt;Jacko Koster&lt;/a&gt;’s talk. Jacko provided a snapshot of Leiden University’s work in progress in developing such a policy. The variety of parties involved, as well as the many aspects of research software, make for a complicated process that involves discussing with many stakeholders at all levels of the university. &lt;a href=&quot;https://www.tudelft.nl/library/research-data-management/r/support/data-stewardship/contact/paula-martinez-lavanchy&quot;&gt;Paula Martinez Lavanchy&lt;/a&gt; from TU Delft discussed her university’s success story. In 2021, she led the drafting and implementation of &lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.4629661&quot;&gt;TU Delft’s research software policy&lt;/a&gt; together with a group of TU Delft’s employees. She started by putting together a working group that encompassed relevant stakeholders from all areas: researchers, librarians, data stewards, valorisation center employees, legal services and the ICT department. The inclusion of many different parties and integration of all their perspectives was crucial to her success.&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://zenodo.org/doi/10.5281/zenodo.4629661)Click&quot;&gt;https://zenodo.org/doi/10.5281/zenodo.4629661)Click&lt;/a&gt; the image to read TU Delft’s research software policyTU Delft’s experience provides valuable insights into what can make institutional research software policies effective. For example, TU Delft has made sure that the implementation and software workflow described by the policy is solidly integrated into training for staff. This approach fits well with findings by the PASTEUR40A project, which investigated success factors in implementing policies at universities. In their project, they investigated Open Access policies at 120 different universities. Drawing from these experiences with implementing Open Access policies, they wrote &lt;a href=&quot;https://doi.org/10.5281/zenodo.35635&quot;&gt;a paper&lt;/a&gt; that concluded that effective policies should be minimally burdensome, mandatory, linked to evaluation and incentives, and applied at the optimal time in the lifecycle. Additionally, they must align with funders’ policies for university staff to adhere to them.&lt;/p&gt;
&lt;p&gt;The challenge of drafting and implementing research software policies for individuals at knowledge institutions has inspired the formation of the recently approved RDA working group PRO4RS, a joint initiative by ReSA and the RDA, with support of the RDA Tiger project. For those wondering how to go about drafting an institutional research software policy, this group is working on an overview of existing policies. Next steps will include putting together resources on how to achieve policy change at an institute, and to develop a common framework for research software policy, specifically. You can &lt;a href=&quot;https://www.rd-alliance.org/groups/rda-resa-policies-research-organisations-research-software-pro4rs&quot;&gt;join this group&lt;/a&gt; to receive updates and information about the group’s work, as well as sessions during the RDA plenary (two times per year). A summary of the working group’s most recent (autumn 2023) RDA plenary session is available &lt;a href=&quot;https://www.rd-alliance.org/group/rda-resa-policies-research-organisations-research-software-pro4rs/post/summary-rda-plenary-21&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The participants at our event brainstormed about what should be part of their research software policies. They agreed that at a minimum, a definition of research software should be included in the policy. Most participants agreed that it should include rules about licensing and sharing software, too. An interesting point of discussion was the question whether guidelines on good practices in software development should be part of a research software policy, and where to draw the line regarding this. For example, some participants agreed that pointers on research software quality and a commitment to training researchers on good practices should be part of a research software policy, while others did not.&lt;/p&gt;
&lt;h3 id=&quot;next-steps&quot;&gt;Next steps**&lt;/h3&gt;
&lt;p&gt;We invite anyone interested in staying up to date about institutional research software policies to **attend &lt;strong&gt;&lt;a href=&quot;https://www.eventbrite.com/e/institutional-research-software-policies-tickets-765126843987?aff=oddtdtcreator&quot;&gt;&lt;strong&gt;our webinar&lt;/strong&gt;&lt;/a&gt;&lt;/strong&gt; on 16 January 2024 to continue the conversation about institutional research software policies in the Netherlands. **During this webinar, we plan to include an update from the PRO4RS RDA working group and reiterate the most important points from our workshop on 3 October to those who missed it. Sign up &lt;a href=&quot;https://www.eventbrite.com/e/institutional-research-software-policies-tickets-765126843987?aff=oddtdtcreator&quot;&gt;here&lt;/a&gt; to join the webinar.&lt;/p&gt;
&lt;p&gt;If you are interested in developing institutional research software policies, you can** subscribe to updates from the PRO4RS RDA working group **&lt;a href=&quot;https://www.rd-alliance.org/groups/rda-resa-policies-research-organisations-research-software-pro4rs&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, on 23 April 2024, the eScience Center is jointly organising &lt;a href=&quot;https://www.eventbrite.com/e/national-research-software-day-tickets-761242004327?aff=oddtdtcreator&quot;&gt;&lt;strong&gt;National Research Software Day&lt;/strong&gt;&lt;/a&gt;, where policy makers, research supporters and community leaders will come together to discuss all things research software. You can find out more and sign up for this day here.&lt;/p&gt;
&lt;p&gt;Written by Lieke de Boer. Thanks to Carlos Martinez-Ortiz, Maaike de Jong, Maria Cruz and Meron Vermaas for comments.*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/navigating-research-software-policies-in-ea981e66.xiUpiGH6.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Cracking the (moisture) tracking code</title><link>https://blog2.esciencecenter.nl/posts/2023-11-21---cracking-the-moisture-tracking-code</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-11-21---cracking-the-moisture-tracking-code</guid><description>&lt;h2 id=&quot;an-exclusive-interview-with-our-project-partners&quot;&gt;An exclusive interview with our project partners&lt;/h2&gt;
&lt;p&gt;This post is part of a series on our 2021 Small Scale Initiative Call in Software Performance Optimization. This week’s highlight: “&lt;a href=&quot;https://research-software-directory.org/projects/optimizing-tracking-of-moisture-in-the-atmosphere&quot;&gt;Optimizing tracking of moisture in the atmosphere&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;What is moisture tracking? Can Python deliver optimal performance? What’s it like to have others modify your code? How can a team avoid alienation in coding? Will the output of this project be part of CMIP? Find out in this exclusive interview with project team members &lt;a href=&quot;https://www.linkedin.com/in/imme-benedict-abab09b8&quot;&gt;Imme Benedict&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/ruud-van-der-ent-79142b11&quot;&gt;Ruud van der Ent&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/chris-weijenborg-17ab1431/&quot;&gt;Chris Weijenborg&lt;/a&gt;, and Peter Kalverla!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;560&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-e7c68a7c.D1PgIWpw_Z1fDxMi.webp&quot; srcset=&quot;&quot;&gt;
Project team. Imme and Ruud, Peter, Chris and Yang (top-to-bottom, left-to-right).&lt;/p&gt;
&lt;h3 id=&quot;chris-youre-an-expert-in-atmospheric-dynamics-can-you-explain-what-moisture-tracking-is-and-why-it-is-useful&quot;&gt;Chris, you’re an expert in atmospheric dynamics. Can you explain what moisture tracking is, and why it is useful?**&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Chris&lt;/em&gt;: The essential question you want to answer with moisture tracking is where moisture leading to precipitation in a certain area is coming from. This can be related to a particular event, think about for example the floods in West-Europe in 2021, but also related to the climatological precipitation. This is useful, since it gives us other insights then just looking at precipitation and or wind fields directly. For example, if the sea surface temperature is increasing in a warmer climate, does this lead to an increased climatological precipitation at another location? Or are the Floods in 2021 caused by increased sea surface temperatures in the Mediterranean Sea or the increased soil moisture over the continent? You might wonder now how all of this works: it’s complicated, but we have a nice animation to show the basics:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;169&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-8a91d349.CMAsRdvw_ZSbsc8.webp&quot; srcset=&quot;&quot;&gt;
Animation of a moisture-tracking experiment. The video first runs forward, then reversed. On the left, you see the total water content in the atmosphere, on the right only the part that contributed to the 2021 floods over the Eiffel and the Ardennes.&lt;/p&gt;
&lt;h3 id=&quot;imme-you-were-the-main-applicant-for-this-project-what-was-your-original-goal-with-the-proposal&quot;&gt;&lt;strong&gt;Imme, you were the main applicant for this project. What was your original goal with the proposal?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Imme&lt;/em&gt;: I had been working in my PhD with the &lt;a href=&quot;https://research-software-directory.org/software/wam2layers&quot;&gt;WAM2layers model&lt;/a&gt; and also adapted parts of the code. When I got a position as lecturer and researcher, I was keen on continuing the work on moisture tracking, and one way was to work with MSc thesis projects. However, the tool became a bit outdated as it was written to use &lt;a href=&quot;https://climatedataguide.ucar.edu/climate-data/era-interim&quot;&gt;ERA-Interim dataset&lt;/a&gt; as input, while for most recent events only the newest dataset ERA5 was available, as the ERA-Interim dataset was phased out. Therefore,&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;I became hesitant to use moisture tracking in my own and students research, which I thought was a shame.&lt;/p&gt;
&lt;p&gt;Then I wrote this proposal to update and speed-up the code such that researchers new in the field (like students) could easily start to use it.&lt;/p&gt;
&lt;h3 id=&quot;ruud-as-the-original-developer-of-wam2layers-you-published-your-code-many-years-ago-what-were-your-expectations-back-then-and-how-do-you-look-back-on-that-today&quot;&gt;&lt;strong&gt;Ruud, as the original developer of WAM2layers you published your code many years ago. What were your expectations back then? And how do you look back on that today?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;: Initially I just wanted to archive the code, so other researchers would more easily be able to find it. I naively thought of the code as something quite static. Since then, demand for moisture tracking in various fields of application has increased enormously and so has the importance to develop and maintain the code. I hope that with the user community around WAM2layers we can keep the software up to date with the latest developments and relevant for several years to come.&lt;/p&gt;
&lt;h3 id=&quot;peter-you-have-a-background-in-meteorology--wageningen-university-what-was-it-like-to-go-back-to-your-roots-in-this-project&quot;&gt;&lt;strong&gt;Peter, you have a background in meteorology @ Wageningen University. What was it like to go back to your roots in this project?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Peter&lt;/em&gt;: Indeed, this project was right up my alley. I benefited a lot from my meteorology background and I enjoyed delving into some of the equations I’d almost forgotten about. I also liked the collaboration in this project. It felt like a real team effort, where everyone brought their own unique expertise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;When I left Wageningen to join the eScience Center, I wanted to improve my own research software engineering skills so I could apply them to the benefit of academic research. I think that really worked out well with this project.&lt;/p&gt;
&lt;h3 id=&quot;now-that-were-past-the-introductions-lets-take-a-deeper-dive-into-the-project-you-mentioned-the-code-was-too-slow-to-work-with-high-resolution-data-like-era5-did-you-solve-this-problem-and-how&quot;&gt;&lt;strong&gt;Now that we’re past the introductions, let’s take a deeper dive into the project. You mentioned the code was too slow to work with high-resolution data like ERA5. Did you solve this problem, and how?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Peter&lt;/em&gt;: Yes, we did. The easiest win was changing the code from Python2 to Python3, and then some relatively straightforward changes, for example better use of numpy’s broadcasting capabilities.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;47&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-c3bdc752.9PiMDSLZ_Z23B0zl.webp&quot; srcset=&quot;&quot;&gt;
Illustration of the time steps in the input data (above) and in the model time loop (below).&lt;/p&gt;
&lt;h3 id=&quot;wam2layers-was-originally-written-in-matlab-then-translated-to-python-wasnt-it-time-for-another-switch-especially-considering-pythons-reputation-regarding-performance&quot;&gt;WAM2layers was originally written in Matlab, then translated to Python. Wasn’t it time for another switch, especially considering Python’s reputation regarding performance?**&lt;/h3&gt;
&lt;p&gt;Peter*: We considered it. I’ve been experimenting a bit with Julia in the past and it seems like a suitable alternative. However, we wanted to make sure that the code was still understandable for scientists or students: even if they are not actively changing the code, it’s good if they can understand what’s going on. Python still is by far the most widely known language in the field.&lt;/p&gt;
&lt;p&gt;Moreover, Python is fast enough for now. For most operations we use highly optimized numpy functions. If we wanted to squeeze out even more we could still look into numba, for example. Having said that, some of the changes we made to the code structure &lt;em&gt;do&lt;/em&gt; actually make it easier to replace expensive operations with optimized code in another language, should we ever wish to do that.&lt;/p&gt;
&lt;h3 id=&quot;in-the-end-you-did-more-than-make-it-faster-can-you-elaborate-on-some-of-the-unexpected-changes&quot;&gt;&lt;strong&gt;In the end, you did more than make it faster. Can you elaborate on some of the unexpected changes?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Peter&lt;/em&gt;: yes, one example is that we made it easier to (pip) install the model and use it from the command line.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;People can now get the software working in a matter of minutes. One does not need to be an expert anymore, which is a great development.&lt;/p&gt;
&lt;p&gt;However, when people do research with it, I still hope that they involve someone from the core development team as there might be some tricky devils in the details.&lt;/p&gt;
&lt;h3 id=&quot;in-retrospect-what-are-the-main-things-you-got-out-of-this-project&quot;&gt;&lt;strong&gt;In retrospect, what are the main things you got out of this project?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;: Personally, I really enjoyed two things: 1) working in a horizontal team, and 2) blocking time in my agenda to do some coding.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Chris&lt;/em&gt;: I really enjoyed learning something new again, moreover in the meanwhile I also was ‘forced’ to learn version control with Git.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Imme&lt;/em&gt;: Teamwork, and learning Git! But also the possibility to have students working with the tool again.&lt;/p&gt;
&lt;h3 id=&quot;can-you-elaborate-on-the-student-projects&quot;&gt;&lt;strong&gt;Can you elaborate on the student projects?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud &amp;#x26; Imme&lt;/em&gt;: Sure! Below are the results from 4 student projects: Wenyu looked at &lt;a href=&quot;http://resolver.tudelft.nl/uuid:28f594b4-b24f-4aec-b01c-662e777ca971&quot;&gt;monsoon moisture source&lt;/a&gt; for the Yangtze River Basin, Rens studied &lt;a href=&quot;http://resolver.tudelft.nl/uuid:4e8cfdc1-350f-403f-aa7e-e76b55f5a800&quot;&gt;trends in moisture sources&lt;/a&gt; related to rising lakes in Keny, Emma studied the &lt;a href=&quot;http://resolver.tudelft.nl/uuid:7185c2b7-8313-4dc9-8a10-f57a7cd5ca35&quot;&gt;drivers of rainfall variability&lt;/a&gt; in Surinam, and Vincent used WAM2layers to study the moisture sources over the Amazon region during August 2023 when a big field campaign took place to understand biosphere-atmosphere interactions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-384b7503.DDWvrbCd_Z5iS17.webp&quot; srcset=&quot;&quot;&gt;
WAM2layers output as produced and visualized in students’ projects. Shading illustrates the moisture sources for the each of the case studies.&lt;/p&gt;
&lt;h3 id=&quot;recently-a-follow-up-project-was-granted-so-this-story-will-continue&quot;&gt;&lt;strong&gt;Recently a follow-up project was granted. So this story will continue?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;: Absolutely, with the NWO Open Science project and our own time we want to make WAM2layers even more user-friendly, increase the number of features, applicability to climate models, and get a better grip on the uncertainties. To this end we will also engage with the wider moisture tracking community.&lt;/p&gt;
&lt;h3 id=&quot;will-cmip7-include-an-atmospheric-moisture-tracking-mip-in-the-future&quot;&gt;&lt;strong&gt;Will CMIP7 include an “Atmospheric moisture tracking-MIP” in the future?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Imme&lt;/em&gt;: Ha, that would be amazing of course, but realistically I think there are still some steps in between before such a big goal can be achieved. We are currently initiating a moisture tracking intercomparison project, where multiple moisture tracking models will run the same case to address uncertainty of moisture sources between models. This project will be supported by a workshop at the Lorentz centre in Leiden in May 2024.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post is part of a series on our 2021 Small Scale Initiative Call in Software Performance Optimization. See also our post on the project &lt;em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/minds-for-mobile-agents-speeding-up-social-distancing-simulations-62d3fb412ff6&quot;&gt;&lt;em&gt;Minds for Mobile Agents&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Tue, 21 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;an-exclusive-interview-with-our-project-partners&quot;&gt;An exclusive interview with our project partners&lt;/h2&gt;
&lt;p&gt;This post is part of a series on our 2021 Small Scale Initiative Call in Software Performance Optimization. This week’s highlight: “&lt;a href=&quot;https://research-software-directory.org/projects/optimizing-tracking-of-moisture-in-the-atmosphere&quot;&gt;Optimizing tracking of moisture in the atmosphere&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;What is moisture tracking? Can Python deliver optimal performance? What’s it like to have others modify your code? How can a team avoid alienation in coding? Will the output of this project be part of CMIP? Find out in this exclusive interview with project team members &lt;a href=&quot;https://www.linkedin.com/in/imme-benedict-abab09b8&quot;&gt;Imme Benedict&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/ruud-van-der-ent-79142b11&quot;&gt;Ruud van der Ent&lt;/a&gt;, &lt;a href=&quot;https://www.linkedin.com/in/chris-weijenborg-17ab1431/&quot;&gt;Chris Weijenborg&lt;/a&gt;, and Peter Kalverla!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;560&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-e7c68a7c.D1PgIWpw_Z1fDxMi.webp&quot; srcset=&quot;&quot;&gt;
Project team. Imme and Ruud, Peter, Chris and Yang (top-to-bottom, left-to-right).&lt;/p&gt;
&lt;h3 id=&quot;chris-youre-an-expert-in-atmospheric-dynamics-can-you-explain-what-moisture-tracking-is-and-why-it-is-useful&quot;&gt;Chris, you’re an expert in atmospheric dynamics. Can you explain what moisture tracking is, and why it is useful?**&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Chris&lt;/em&gt;: The essential question you want to answer with moisture tracking is where moisture leading to precipitation in a certain area is coming from. This can be related to a particular event, think about for example the floods in West-Europe in 2021, but also related to the climatological precipitation. This is useful, since it gives us other insights then just looking at precipitation and or wind fields directly. For example, if the sea surface temperature is increasing in a warmer climate, does this lead to an increased climatological precipitation at another location? Or are the Floods in 2021 caused by increased sea surface temperatures in the Mediterranean Sea or the increased soil moisture over the continent? You might wonder now how all of this works: it’s complicated, but we have a nice animation to show the basics:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;169&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-8a91d349.CMAsRdvw_ZSbsc8.webp&quot; srcset=&quot;&quot;&gt;
Animation of a moisture-tracking experiment. The video first runs forward, then reversed. On the left, you see the total water content in the atmosphere, on the right only the part that contributed to the 2021 floods over the Eiffel and the Ardennes.&lt;/p&gt;
&lt;h3 id=&quot;imme-you-were-the-main-applicant-for-this-project-what-was-your-original-goal-with-the-proposal&quot;&gt;&lt;strong&gt;Imme, you were the main applicant for this project. What was your original goal with the proposal?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Imme&lt;/em&gt;: I had been working in my PhD with the &lt;a href=&quot;https://research-software-directory.org/software/wam2layers&quot;&gt;WAM2layers model&lt;/a&gt; and also adapted parts of the code. When I got a position as lecturer and researcher, I was keen on continuing the work on moisture tracking, and one way was to work with MSc thesis projects. However, the tool became a bit outdated as it was written to use &lt;a href=&quot;https://climatedataguide.ucar.edu/climate-data/era-interim&quot;&gt;ERA-Interim dataset&lt;/a&gt; as input, while for most recent events only the newest dataset ERA5 was available, as the ERA-Interim dataset was phased out. Therefore,&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;I became hesitant to use moisture tracking in my own and students research, which I thought was a shame.&lt;/p&gt;
&lt;p&gt;Then I wrote this proposal to update and speed-up the code such that researchers new in the field (like students) could easily start to use it.&lt;/p&gt;
&lt;h3 id=&quot;ruud-as-the-original-developer-of-wam2layers-you-published-your-code-many-years-ago-what-were-your-expectations-back-then-and-how-do-you-look-back-on-that-today&quot;&gt;&lt;strong&gt;Ruud, as the original developer of WAM2layers you published your code many years ago. What were your expectations back then? And how do you look back on that today?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;: Initially I just wanted to archive the code, so other researchers would more easily be able to find it. I naively thought of the code as something quite static. Since then, demand for moisture tracking in various fields of application has increased enormously and so has the importance to develop and maintain the code. I hope that with the user community around WAM2layers we can keep the software up to date with the latest developments and relevant for several years to come.&lt;/p&gt;
&lt;h3 id=&quot;peter-you-have-a-background-in-meteorology--wageningen-university-what-was-it-like-to-go-back-to-your-roots-in-this-project&quot;&gt;&lt;strong&gt;Peter, you have a background in meteorology @ Wageningen University. What was it like to go back to your roots in this project?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Peter&lt;/em&gt;: Indeed, this project was right up my alley. I benefited a lot from my meteorology background and I enjoyed delving into some of the equations I’d almost forgotten about. I also liked the collaboration in this project. It felt like a real team effort, where everyone brought their own unique expertise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;When I left Wageningen to join the eScience Center, I wanted to improve my own research software engineering skills so I could apply them to the benefit of academic research. I think that really worked out well with this project.&lt;/p&gt;
&lt;h3 id=&quot;now-that-were-past-the-introductions-lets-take-a-deeper-dive-into-the-project-you-mentioned-the-code-was-too-slow-to-work-with-high-resolution-data-like-era5-did-you-solve-this-problem-and-how&quot;&gt;&lt;strong&gt;Now that we’re past the introductions, let’s take a deeper dive into the project. You mentioned the code was too slow to work with high-resolution data like ERA5. Did you solve this problem, and how?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Peter&lt;/em&gt;: Yes, we did. The easiest win was changing the code from Python2 to Python3, and then some relatively straightforward changes, for example better use of numpy’s broadcasting capabilities.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;47&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-c3bdc752.9PiMDSLZ_Z23B0zl.webp&quot; srcset=&quot;&quot;&gt;
Illustration of the time steps in the input data (above) and in the model time loop (below).&lt;/p&gt;
&lt;h3 id=&quot;wam2layers-was-originally-written-in-matlab-then-translated-to-python-wasnt-it-time-for-another-switch-especially-considering-pythons-reputation-regarding-performance&quot;&gt;WAM2layers was originally written in Matlab, then translated to Python. Wasn’t it time for another switch, especially considering Python’s reputation regarding performance?**&lt;/h3&gt;
&lt;p&gt;Peter*: We considered it. I’ve been experimenting a bit with Julia in the past and it seems like a suitable alternative. However, we wanted to make sure that the code was still understandable for scientists or students: even if they are not actively changing the code, it’s good if they can understand what’s going on. Python still is by far the most widely known language in the field.&lt;/p&gt;
&lt;p&gt;Moreover, Python is fast enough for now. For most operations we use highly optimized numpy functions. If we wanted to squeeze out even more we could still look into numba, for example. Having said that, some of the changes we made to the code structure &lt;em&gt;do&lt;/em&gt; actually make it easier to replace expensive operations with optimized code in another language, should we ever wish to do that.&lt;/p&gt;
&lt;h3 id=&quot;in-the-end-you-did-more-than-make-it-faster-can-you-elaborate-on-some-of-the-unexpected-changes&quot;&gt;&lt;strong&gt;In the end, you did more than make it faster. Can you elaborate on some of the unexpected changes?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Peter&lt;/em&gt;: yes, one example is that we made it easier to (pip) install the model and use it from the command line.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;People can now get the software working in a matter of minutes. One does not need to be an expert anymore, which is a great development.&lt;/p&gt;
&lt;p&gt;However, when people do research with it, I still hope that they involve someone from the core development team as there might be some tricky devils in the details.&lt;/p&gt;
&lt;h3 id=&quot;in-retrospect-what-are-the-main-things-you-got-out-of-this-project&quot;&gt;&lt;strong&gt;In retrospect, what are the main things you got out of this project?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;: Personally, I really enjoyed two things: 1) working in a horizontal team, and 2) blocking time in my agenda to do some coding.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Chris&lt;/em&gt;: I really enjoyed learning something new again, moreover in the meanwhile I also was ‘forced’ to learn version control with Git.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Imme&lt;/em&gt;: Teamwork, and learning Git! But also the possibility to have students working with the tool again.&lt;/p&gt;
&lt;h3 id=&quot;can-you-elaborate-on-the-student-projects&quot;&gt;&lt;strong&gt;Can you elaborate on the student projects?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud &amp;#x26; Imme&lt;/em&gt;: Sure! Below are the results from 4 student projects: Wenyu looked at &lt;a href=&quot;http://resolver.tudelft.nl/uuid:28f594b4-b24f-4aec-b01c-662e777ca971&quot;&gt;monsoon moisture source&lt;/a&gt; for the Yangtze River Basin, Rens studied &lt;a href=&quot;http://resolver.tudelft.nl/uuid:4e8cfdc1-350f-403f-aa7e-e76b55f5a800&quot;&gt;trends in moisture sources&lt;/a&gt; related to rising lakes in Keny, Emma studied the &lt;a href=&quot;http://resolver.tudelft.nl/uuid:7185c2b7-8313-4dc9-8a10-f57a7cd5ca35&quot;&gt;drivers of rainfall variability&lt;/a&gt; in Surinam, and Vincent used WAM2layers to study the moisture sources over the Amazon region during August 2023 when a big field campaign took place to understand biosphere-atmosphere interactions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Cracking the (moisture) tracking code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-384b7503.DDWvrbCd_Z5iS17.webp&quot; srcset=&quot;&quot;&gt;
WAM2layers output as produced and visualized in students’ projects. Shading illustrates the moisture sources for the each of the case studies.&lt;/p&gt;
&lt;h3 id=&quot;recently-a-follow-up-project-was-granted-so-this-story-will-continue&quot;&gt;&lt;strong&gt;Recently a follow-up project was granted. So this story will continue?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Ruud&lt;/em&gt;: Absolutely, with the NWO Open Science project and our own time we want to make WAM2layers even more user-friendly, increase the number of features, applicability to climate models, and get a better grip on the uncertainties. To this end we will also engage with the wider moisture tracking community.&lt;/p&gt;
&lt;h3 id=&quot;will-cmip7-include-an-atmospheric-moisture-tracking-mip-in-the-future&quot;&gt;&lt;strong&gt;Will CMIP7 include an “Atmospheric moisture tracking-MIP” in the future?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Imme&lt;/em&gt;: Ha, that would be amazing of course, but realistically I think there are still some steps in between before such a big goal can be achieved. We are currently initiating a moisture tracking intercomparison project, where multiple moisture tracking models will run the same case to address uncertainty of moisture sources between models. This project will be supported by a workshop at the Lorentz centre in Leiden in May 2024.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post is part of a series on our 2021 Small Scale Initiative Call in Software Performance Optimization. See also our post on the project &lt;em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/minds-for-mobile-agents-speeding-up-social-distancing-simulations-62d3fb412ff6&quot;&gt;&lt;em&gt;Minds for Mobile Agents&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/cracking-the-moisture-tracking-code-e7c68a7c.D1PgIWpw.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Automatic differentiation from scratch</title><link>https://blog2.esciencecenter.nl/posts/2023-11-09---automatic-differentiation-from-scratch</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-11-09---automatic-differentiation-from-scratch</guid><description>&lt;p&gt;A surprisingly simple and elegant way to teach your computer how to perform derivatives, with some Julia (and Python) examples&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;664&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-b0c3396d.DnMFMg-f_106PyB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@crissyjarvis?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Crissy Jarvis&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;first-a-disclaimer&quot;&gt;First, a disclaimer&lt;/h2&gt;
&lt;p&gt;Automatic differentiation is a well-known sub-field of applied mathematics. You definitely don’t have to implement it from scratch, unless, as I did, you want to. And why would you want to do such a thing? My motivation was a mix of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I like to understand what the packages I use do&lt;/li&gt;
&lt;li&gt;The theory behind automatic differentiation happens to be very beautiful&lt;/li&gt;
&lt;li&gt;I could use it as a case study to improve my understanding of the Julia language&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, if you are interested in performance, you’d likely want to focus on backward automatic differentiation, and not, as I did, on the forward one.&lt;/p&gt;
&lt;p&gt;If you are still reading, it means that after all these disclaimers your intrinsic motivation is still intact. Great! Let me introduce you to the fascinating topic of automatic differentiation and my (quick and dirty) implementation.&lt;/p&gt;
&lt;h2 id=&quot;enter-the-dual-numbers&quot;&gt;Enter the dual numbers&lt;/h2&gt;
&lt;p&gt;Probably you remember it from your high school years. The nightmare of derivatives! All those tables you had to memorize, all those rules you had to apply… chances are that it is not a good memory!&lt;/p&gt;
&lt;p&gt;Would it be possible to teach a computer the rules of differentiation? The answer is yes! It is not only possible but can even be elegant. Enter the dual numbers! A dual number is very similar to a two-dimensional vector:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;112&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-7efd31d4.BZRFlLQG_1WlpU.webp&quot; srcset=&quot;&quot;&gt;
the first element represents the value of a function at a given point, and the second one is its derivative at the same point. For instance, the constant 3 will be written as the dual number (3, 0) (the 0 means that it’s a constant and thus its derivative is 0) and the variable x = 3 will be written as (3,1) (the 1 meaning that 3 is an evaluation of the variable x, and thus its derivative respective to x is 1). I know this sounds strange, but stick with me; it will become clearer later.&lt;/p&gt;
&lt;p&gt;So, we have a new mathematical toy. We have to write down the game rules if we want to have any fun with it: let’s start defining addition, subtraction, and multiplication by a scalar. We decide they follow exactly the same rules that vectors do:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;353&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0f2bc067.CsOggy-q_Z1qaYlh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;353&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-7ea6a471.pmZHmzUA_Ac09a.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;224&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0c493360.CSP6ISNI_1hG8U0.webp&quot; srcset=&quot;&quot;&gt;
So far, nothing exciting. The multiplication is defined in a more interesting way:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;355&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0256af77.DY7pq6De_1hBSac.webp&quot; srcset=&quot;&quot;&gt;
Why? Because we said the second term represents a derivative, it has to follow the product rule for derivatives.&lt;/p&gt;
&lt;p&gt;What about quotients? You guessed… the division of dual numbers follows the quotient rule for derivatives:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;219&quot; height=&quot;39&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-ae806035.B-ZZ78wS_Z28zKXt.webp&quot; srcset=&quot;&quot;&gt;
Last but not least, the power of a dual number to a real number is defined as:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;278&quot; height=&quot;27&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-dfaecdf1.8__mDMGS_1ztMN1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Perhaps you feel curiosity about the multiplication by u’. This corresponds to the chain rule, and enables our dual numbers for something as desirable as function composition.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The operations defined above cover a lot of ground. Indeed, any algebraic operation can be built using them as basic components. This means that we can pass a dual number as the argument of an algebraic function, and here comes the magic, the result will be:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;340&quot; height=&quot;26&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-a331eeae.CjPBcQIW_Z1lMM62.webp&quot; srcset=&quot;&quot;&gt;
It is hard to overstate how powerful this is. The equation above tells us that just by feeding the function the dual number (x, 1) it will return its value at, plus its derivative! Two for the price of one!&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those readers familiar with complex numbers may find interesting to try the following exercise:&lt;/p&gt;
&lt;p&gt;If we define a dual number as&lt;/p&gt;
&lt;p&gt;(u, u’) = u + e u’&lt;/p&gt;
&lt;p&gt;with e² = 0, all the properties above are automatically satisfied!&lt;/p&gt;
&lt;h2 id=&quot;teaching-derivatives-to-your-computer&quot;&gt;Teaching derivatives to your computer&lt;/h2&gt;
&lt;p&gt;Just as a calculus student will do, the rules of differentiation turn a calculus problem into an algebra one. And the good news: computers are better at algebra than you!&lt;/p&gt;
&lt;p&gt;So, how can we implement these rules in a practical way on our computer? Implementing a new object (a dual number) with its own interaction rules sounds like a task for object-oriented programming. And, interestingly enough, the process is surprisingly similar to that of teaching a human student. With the difference that our “digital student” will never forget a rule, apply it the wrong way, or forget a minus sign!&lt;/p&gt;
&lt;p&gt;So, how do these rules look, for instance, in Julia? (For a Python implementation, take a look &lt;a href=&quot;https://github.com/PabRod/dualdiff&quot;&gt;here&lt;/a&gt;). First of all, we need to define a &lt;code&gt;Dual&lt;/code&gt; object, representing a dual number. In principle, it is as simple as a container for two real numbers:&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot; Structure representing a Dual number &quot;&quot;&quot;
struct Dual
x::Real
dx::Real
endLater, it will come in handy to add a couple of constructors.&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot; Structure representing a Dual number &quot;&quot;&quot;
struct Dual
x::Real
dx::Real&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;&quot;&quot; Default constructor &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function Dual(x::Real, dx::Real=0)::Dual&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    new(x, dx)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;&quot;&quot; If passed a Dual, just return it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;This will be handy later &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function Dual(x::Dual)::Dual&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;end&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don’t worry too much if you don’t understand the lines above. They have been added only making the &lt;em&gt;&lt;code&gt;*Dual*&lt;/code&gt;&lt;/em&gt; object easier to use (for instance, &lt;em&gt;&lt;code&gt;*Dual(1)*&lt;/code&gt;&lt;/em&gt; would have failed without the first constructor, and so would have done the application of &lt;em&gt;&lt;code&gt;*Dual*&lt;/code&gt;&lt;/em&gt; to a number that is already a &lt;em&gt;&lt;code&gt;*Dual*&lt;/code&gt;&lt;/em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another trick that will prove handy soon is to create a type alias for anything that is either a &lt;code&gt;Number&lt;/code&gt; (one of Julia’s base types) or a &lt;code&gt;Dual&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;const DualNumber = Union{Dual, Number}And now comes the fun part. We’ll teach our new object how to do mathematics! For instance, as we saw earlier, the rule for adding dual numbers is to add both their components, just as in a 2D vector:&lt;/p&gt;
&lt;p&gt;import Base: +
function +(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
return Dual(self.x + other.x, self.dx + other.dx)
endWe have to teach even more basic stuff. Remember a computer is dramatically devoid of common sense, so, for instance, we have to define the meaning of a plus sign in front of a &lt;code&gt;Dual&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;+(z::Dual) = z&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This sounds as idiotic as explaining that +3 is equal to 3, but the computer needs to know! Another possibility is using inheritance, but this is an advanced topic beyond the scope of this piece.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Defining minus a &lt;code&gt;Dual&lt;/code&gt; will also be needed:&lt;/p&gt;
&lt;p&gt;import Base: -
-(z::Dual) = Dual(-z.x, -z.dx)and actually, it allows us to define the subtraction of two dual numbers as a sum:&lt;/p&gt;
&lt;p&gt;function -(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
return self + (-other) # A subtraction disguised as a sum!
endSome basic operations may be slightly trickier than expected. For instance, when is a dual number smaller than another dual number? Notice that in this case, it only makes sense to compare the first elements, and ignore the derivatives:&lt;/p&gt;
&lt;p&gt;import Base: &amp;#x3C;
&amp;#x3C;(self::Dual, other::Dual) = self.x &amp;#x3C; other.xAs we saw before, more interesting stuff happens with multiplication and division:&lt;/p&gt;
&lt;p&gt;import Base: *, /&lt;/p&gt;
&lt;p&gt;function *(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
y = self.x * other.x
dy = self.dx * other.x + self.x * other.dx # Rule of product for derivatives
return Dual(y, dy)
end&lt;/p&gt;
&lt;p&gt;function /(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
y = self.x / other.x
dy = (self.dx * other.x - self.x * other.dx) / (other.x)^2 # Rule of quotient for derivatives
return Dual(y, dy)
endand with potentiation to a real number:&lt;/p&gt;
&lt;p&gt;import Base: ^
function ^(self::Dual, other::Real)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
y = self.x^other.x
dy = other.x * self.x^(other.x - 1) * self.dx # Derivative of u(x)^n
return Dual(y, dy)
endThe full list of definitions for algebraic operations &lt;a href=&quot;https://github.com/PabRod/DualDiff.jl/blob/main/src/Dual.jl&quot;&gt;is here&lt;/a&gt;. For Python, use &lt;a href=&quot;https://github.com/PabRod/dualdiff/blob/main/dualdiff/dual.py&quot;&gt;this link&lt;/a&gt;. I recommend taking a look!&lt;/p&gt;
&lt;p&gt;After this, each and every time our dual number finds one of the operations defined above in its mysterious journey down a function or a script, it will keep track of its effect on the derivative. It doesn’t matter how long, complicated, or poorly programmed the function is, the second coordinate of our dual number will manage it. Well, as long as the function is differentiable and we don’t hit the machine’s precision… but that would be asking our computer to do magic.&lt;/p&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;As an example, let’s calculate the derivative of the polynomial:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;248&quot; height=&quot;27&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-ae298bad.Bb9Nk4Zy_Z1BK9tS.webp&quot; srcset=&quot;&quot;&gt;
at x = 3.&lt;/p&gt;
&lt;p&gt;For the sake of clarity, we can compute the derivative by hand:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;224&quot; height=&quot;27&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-45eb0e13.CT0fgSsk_OLgfP.webp&quot; srcset=&quot;&quot;&gt;
it is apparent that and p(3) = 39 and p’(3) = 34.&lt;/p&gt;
&lt;p&gt;Using our &lt;code&gt;Dual&lt;/code&gt; object, we can reach the same conclusion automatically:&lt;/p&gt;
&lt;p&gt;poly = x -&gt; x^3 + x^2 + x
z = Dual(3, 1)
poly(z)&lt;/p&gt;
&lt;p&gt;&gt; Dual(39, 34)Even if the same polynomial is defined in a more intricate way, the &lt;code&gt;Dual&lt;/code&gt; object can keep track:&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot; Equivalent to poly = x -&gt; x^3 + x^2 + x
Just uglier &quot;&quot;&quot;
function poly(x)
aux = 0 # Initialize auxiliary variable
for n in 1:3 # Add x^1, x^2 and x^3
aux = aux + x^n
end
end&lt;/p&gt;
&lt;p&gt;poly(z)&lt;/p&gt;
&lt;p&gt;&gt; Dual(39, 34)&lt;/p&gt;
&lt;h2 id=&quot;what-about-non-algebraic-functions&quot;&gt;What about non-algebraic functions?&lt;/h2&gt;
&lt;p&gt;The method sketched above will fail miserably as soon as our function contains a non-algebraic element, such as a sine or an exponential. But don’t panic, we can just go to our calculus book and teach our computer some more basic derivatives. For instance, our table of derivatives tells us that the derivative of a sine is a cosine. In the language of dual numbers, this reads:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;313&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0dd189ff.BBfzEf-y_ZK9RUA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Confused about the u’? Once again, this is just the chain rule.*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rule of thumb here is, and actually was since the very beginning:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;484&quot; height=&quot;31&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-d3a44ff1.DFvVYuAW_Fgb5f.webp&quot; srcset=&quot;&quot;&gt;
We can create a &lt;code&gt;_factory&lt;/code&gt; function that abstracts this structure for us:&lt;/p&gt;
&lt;p&gt;function _factory(f::Function, df::Function)::Function
return z -&gt; Dual(f(z.x), df(z.x) * z.dx)
endSo now, we only have to open our derivatives table and fill line by line, starting with the derivative of a sine, continuing with that of a cosine, a tangent, etc.&lt;/p&gt;
&lt;p&gt;import Base: sin, cos&lt;/p&gt;
&lt;p&gt;sin(z::Dual) = _factory(sin, cos)(z)
cos(z::Dual) = _factory(cos, x -&gt; -sin(x))(z) # An explicit lambda function is often requiredIf we know our maths, we don’t even need to fill all the derivatives manually from the table. For instance, the tangent is defined as:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;135&quot; height=&quot;30&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-3c2438c8.CCr9nuWa_XoBAT.webp&quot; srcset=&quot;&quot;&gt;
and we already have automatically differentiable sine, cosine, and division in our arsenal. So this line will do the trick:&lt;/p&gt;
&lt;p&gt;import Base: tan&lt;/p&gt;
&lt;p&gt;tan(z::Dual) = sin(z) / cos(z) # We can rely on previously defined functions!Of course, hard-coding the tangent’s derivative is also possible, and probably good for code performance and numerical stability. But hey, it’s quite cool that this is even possible!&lt;/p&gt;
&lt;p&gt;See a more complete derivatives table &lt;a href=&quot;https://github.com/PabRod/DualDiff.jl/blob/main/src/primitives.jl&quot;&gt;here&lt;/a&gt; (Python version &lt;a href=&quot;https://github.com/PabRod/dualdiff/blob/main/dualdiff/primitives.py&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;example-1&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;Let’s compute the derivative of the non-algebraic function&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;335&quot; height=&quot;28&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-a6b0d3c2.Biri3LFY_Z16f0E.webp&quot; srcset=&quot;&quot;&gt;
It is easy to prove analytically that the derivative is 1 everywhere (notice that the argument of the tangent is actually constant). Now, using &lt;code&gt;Dual&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;fun = x -&gt; x + tan(cos(x)^2 + sin(x)^2)&lt;/p&gt;
&lt;p&gt;z = Dual(0, 1)
fun(z)&lt;/p&gt;
&lt;p&gt;&gt; Dual(1.557407724654902, 1.0)&lt;/p&gt;
&lt;h2 id=&quot;making-it-more-user-friendly&quot;&gt;Making it more user-friendly&lt;/h2&gt;
&lt;p&gt;We can use dual numbers to create a user-friendly derivative function:&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot;
derivative(f)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Seamlessly turns a given function f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;into&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;the function&apos;s derivative&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&quot;&quot;&quot;
function derivative(f)
df = x -&gt; f(Dual(x, 1.0)).dx
return df
endUsing this, our example above will look like:&lt;/p&gt;
&lt;p&gt;fun = x -&gt; x + tan(cos(x)^2 + sin(x)^2)&lt;/p&gt;
&lt;p&gt;dfun = derivative(f)
dfun(0)&lt;/p&gt;
&lt;p&gt;&gt; 1.0&lt;/p&gt;
&lt;h3 id=&quot;another-example&quot;&gt;Another example**&lt;/h3&gt;
&lt;p&gt;Now we want to calculate and visualize the derivatives of:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;388&quot; height=&quot;31&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-7e1f04a0.DGpBHSBj_vC9q5.webp&quot; srcset=&quot;&quot;&gt;
First, we have to input the function, and the derivative gets calculated automatically:&lt;/p&gt;
&lt;p&gt;f(x) = x^2 - 5x + 6 - 5x^3 - 5 * exp(-50 * x^2)&lt;/p&gt;
&lt;p&gt;df = derivative(f)We can visualize the results by plotting a tangent line:&lt;/p&gt;
&lt;p&gt;using Plots&lt;/p&gt;
&lt;p&gt;I = [-0.7; 0.7]
δ = 0.025
@gif for a = [I[1]:δ:I[2]; I[2]-δ:-δ:I[1]+δ]
L(x) = f(a) + df(a) * (x - a)
plot(f, -1, 1, leg=false)
scatter!([a], [f(a)], m=(:red, 2))
plot!(L, -1, 1, c=:red)
ylims!(-5, 15)
end
&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-fe83078a.B4ZOJz_g_Z2lQYqz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;is-this-useful&quot;&gt;Is this useful?&lt;/h2&gt;
&lt;p&gt;Automatic differentiation is particularly useful in the field of Machine Learning, where multidimensional derivatives (better known as gradients) have to be performed as fast and exactly as possible. Said this, automatic differentiation for Machine Learning is usually implemented in a different way, the so-called backward or reverse mode, for efficiency reasons.&lt;/p&gt;
&lt;p&gt;A well-established library for automatic differentiation is &lt;a href=&quot;https://jax.readthedocs.io/en/latest/&quot;&gt;JAX&lt;/a&gt; (for Python). Machine learning frameworks such as &lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;Tensorflow&lt;/a&gt; and &lt;a href=&quot;https://pytorch.org/&quot;&gt;Pytorch&lt;/a&gt; also implement automatic differentiation. For Julia, multiple libraries &lt;a href=&quot;https://juliadiff.org/&quot;&gt;seem to be competing&lt;/a&gt;, but &lt;a href=&quot;https://enzyme.mit.edu/&quot;&gt;Enzyme.jl&lt;/a&gt; seems to be ahead. &lt;a href=&quot;https://juliadiff.org/ForwardDiff.jl/stable/&quot;&gt;Forwarddiff.jl&lt;/a&gt; is also worth taking a look at.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I want to say thanks to my colleague and friend &lt;a href=&quot;https://abelsiqueira.com&quot;&gt;Abel Siqueira&lt;/a&gt;, for kindly introducing me to Julia and reviewing this post, and to &lt;a href=&quot;https://medium.com/@aronpjansen&quot;&gt;Aron Jansen&lt;/a&gt;, for his kind and useful suggestions. A more in-depth introduction can be found in &lt;a href=&quot;https://book.sciml.ai/notes/08-Forward-Mode_Automatic_Differentiation_(AD)_via_High_Dimensional_Algebras/&quot;&gt;this episode&lt;/a&gt; of Chris Rackauckas’ &lt;a href=&quot;https://book.sciml.ai/&quot;&gt;book on scientific machine learning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/mathaddons/tex-math-here&quot;&gt;TeX Math Here&lt;/a&gt; browser add-in also played an important role: it allowed me to transfer my Latex equations from Markdown to Medium in an (almost) painless way.&lt;/p&gt;</description><pubDate>Thu, 09 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A surprisingly simple and elegant way to teach your computer how to perform derivatives, with some Julia (and Python) examples&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;664&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-b0c3396d.DnMFMg-f_106PyB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@crissyjarvis?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Crissy Jarvis&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;first-a-disclaimer&quot;&gt;First, a disclaimer&lt;/h2&gt;
&lt;p&gt;Automatic differentiation is a well-known sub-field of applied mathematics. You definitely don’t have to implement it from scratch, unless, as I did, you want to. And why would you want to do such a thing? My motivation was a mix of the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I like to understand what the packages I use do&lt;/li&gt;
&lt;li&gt;The theory behind automatic differentiation happens to be very beautiful&lt;/li&gt;
&lt;li&gt;I could use it as a case study to improve my understanding of the Julia language&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, if you are interested in performance, you’d likely want to focus on backward automatic differentiation, and not, as I did, on the forward one.&lt;/p&gt;
&lt;p&gt;If you are still reading, it means that after all these disclaimers your intrinsic motivation is still intact. Great! Let me introduce you to the fascinating topic of automatic differentiation and my (quick and dirty) implementation.&lt;/p&gt;
&lt;h2 id=&quot;enter-the-dual-numbers&quot;&gt;Enter the dual numbers&lt;/h2&gt;
&lt;p&gt;Probably you remember it from your high school years. The nightmare of derivatives! All those tables you had to memorize, all those rules you had to apply… chances are that it is not a good memory!&lt;/p&gt;
&lt;p&gt;Would it be possible to teach a computer the rules of differentiation? The answer is yes! It is not only possible but can even be elegant. Enter the dual numbers! A dual number is very similar to a two-dimensional vector:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;112&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-7efd31d4.BZRFlLQG_1WlpU.webp&quot; srcset=&quot;&quot;&gt;
the first element represents the value of a function at a given point, and the second one is its derivative at the same point. For instance, the constant 3 will be written as the dual number (3, 0) (the 0 means that it’s a constant and thus its derivative is 0) and the variable x = 3 will be written as (3,1) (the 1 meaning that 3 is an evaluation of the variable x, and thus its derivative respective to x is 1). I know this sounds strange, but stick with me; it will become clearer later.&lt;/p&gt;
&lt;p&gt;So, we have a new mathematical toy. We have to write down the game rules if we want to have any fun with it: let’s start defining addition, subtraction, and multiplication by a scalar. We decide they follow exactly the same rules that vectors do:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;353&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0f2bc067.CsOggy-q_Z1qaYlh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;353&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-7ea6a471.pmZHmzUA_Ac09a.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;224&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0c493360.CSP6ISNI_1hG8U0.webp&quot; srcset=&quot;&quot;&gt;
So far, nothing exciting. The multiplication is defined in a more interesting way:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;355&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0256af77.DY7pq6De_1hBSac.webp&quot; srcset=&quot;&quot;&gt;
Why? Because we said the second term represents a derivative, it has to follow the product rule for derivatives.&lt;/p&gt;
&lt;p&gt;What about quotients? You guessed… the division of dual numbers follows the quotient rule for derivatives:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;219&quot; height=&quot;39&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-ae806035.B-ZZ78wS_Z28zKXt.webp&quot; srcset=&quot;&quot;&gt;
Last but not least, the power of a dual number to a real number is defined as:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;278&quot; height=&quot;27&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-dfaecdf1.8__mDMGS_1ztMN1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Perhaps you feel curiosity about the multiplication by u’. This corresponds to the chain rule, and enables our dual numbers for something as desirable as function composition.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The operations defined above cover a lot of ground. Indeed, any algebraic operation can be built using them as basic components. This means that we can pass a dual number as the argument of an algebraic function, and here comes the magic, the result will be:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;340&quot; height=&quot;26&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-a331eeae.CjPBcQIW_Z1lMM62.webp&quot; srcset=&quot;&quot;&gt;
It is hard to overstate how powerful this is. The equation above tells us that just by feeding the function the dual number (x, 1) it will return its value at, plus its derivative! Two for the price of one!&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those readers familiar with complex numbers may find interesting to try the following exercise:&lt;/p&gt;
&lt;p&gt;If we define a dual number as&lt;/p&gt;
&lt;p&gt;(u, u’) = u + e u’&lt;/p&gt;
&lt;p&gt;with e² = 0, all the properties above are automatically satisfied!&lt;/p&gt;
&lt;h2 id=&quot;teaching-derivatives-to-your-computer&quot;&gt;Teaching derivatives to your computer&lt;/h2&gt;
&lt;p&gt;Just as a calculus student will do, the rules of differentiation turn a calculus problem into an algebra one. And the good news: computers are better at algebra than you!&lt;/p&gt;
&lt;p&gt;So, how can we implement these rules in a practical way on our computer? Implementing a new object (a dual number) with its own interaction rules sounds like a task for object-oriented programming. And, interestingly enough, the process is surprisingly similar to that of teaching a human student. With the difference that our “digital student” will never forget a rule, apply it the wrong way, or forget a minus sign!&lt;/p&gt;
&lt;p&gt;So, how do these rules look, for instance, in Julia? (For a Python implementation, take a look &lt;a href=&quot;https://github.com/PabRod/dualdiff&quot;&gt;here&lt;/a&gt;). First of all, we need to define a &lt;code&gt;Dual&lt;/code&gt; object, representing a dual number. In principle, it is as simple as a container for two real numbers:&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot; Structure representing a Dual number &quot;&quot;&quot;
struct Dual
x::Real
dx::Real
endLater, it will come in handy to add a couple of constructors.&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot; Structure representing a Dual number &quot;&quot;&quot;
struct Dual
x::Real
dx::Real&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;&quot;&quot; Default constructor &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function Dual(x::Real, dx::Real=0)::Dual&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    new(x, dx)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;&quot;&quot; If passed a Dual, just return it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;This will be handy later &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function Dual(x::Dual)::Dual&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;end&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don’t worry too much if you don’t understand the lines above. They have been added only making the &lt;em&gt;&lt;code&gt;*Dual*&lt;/code&gt;&lt;/em&gt; object easier to use (for instance, &lt;em&gt;&lt;code&gt;*Dual(1)*&lt;/code&gt;&lt;/em&gt; would have failed without the first constructor, and so would have done the application of &lt;em&gt;&lt;code&gt;*Dual*&lt;/code&gt;&lt;/em&gt; to a number that is already a &lt;em&gt;&lt;code&gt;*Dual*&lt;/code&gt;&lt;/em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another trick that will prove handy soon is to create a type alias for anything that is either a &lt;code&gt;Number&lt;/code&gt; (one of Julia’s base types) or a &lt;code&gt;Dual&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;const DualNumber = Union{Dual, Number}And now comes the fun part. We’ll teach our new object how to do mathematics! For instance, as we saw earlier, the rule for adding dual numbers is to add both their components, just as in a 2D vector:&lt;/p&gt;
&lt;p&gt;import Base: +
function +(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
return Dual(self.x + other.x, self.dx + other.dx)
endWe have to teach even more basic stuff. Remember a computer is dramatically devoid of common sense, so, for instance, we have to define the meaning of a plus sign in front of a &lt;code&gt;Dual&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;+(z::Dual) = z&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This sounds as idiotic as explaining that +3 is equal to 3, but the computer needs to know! Another possibility is using inheritance, but this is an advanced topic beyond the scope of this piece.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Defining minus a &lt;code&gt;Dual&lt;/code&gt; will also be needed:&lt;/p&gt;
&lt;p&gt;import Base: -
-(z::Dual) = Dual(-z.x, -z.dx)and actually, it allows us to define the subtraction of two dual numbers as a sum:&lt;/p&gt;
&lt;p&gt;function -(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
return self + (-other) # A subtraction disguised as a sum!
endSome basic operations may be slightly trickier than expected. For instance, when is a dual number smaller than another dual number? Notice that in this case, it only makes sense to compare the first elements, and ignore the derivatives:&lt;/p&gt;
&lt;p&gt;import Base: &amp;#x3C;
&amp;#x3C;(self::Dual, other::Dual) = self.x &amp;#x3C; other.xAs we saw before, more interesting stuff happens with multiplication and division:&lt;/p&gt;
&lt;p&gt;import Base: *, /&lt;/p&gt;
&lt;p&gt;function *(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
y = self.x * other.x
dy = self.dx * other.x + self.x * other.dx # Rule of product for derivatives
return Dual(y, dy)
end&lt;/p&gt;
&lt;p&gt;function /(self::DualNumber, other::DualNumber)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
y = self.x / other.x
dy = (self.dx * other.x - self.x * other.dx) / (other.x)^2 # Rule of quotient for derivatives
return Dual(y, dy)
endand with potentiation to a real number:&lt;/p&gt;
&lt;p&gt;import Base: ^
function ^(self::Dual, other::Real)::Dual
self, other = Dual(self), Dual(other) # Coerce into Dual
y = self.x^other.x
dy = other.x * self.x^(other.x - 1) * self.dx # Derivative of u(x)^n
return Dual(y, dy)
endThe full list of definitions for algebraic operations &lt;a href=&quot;https://github.com/PabRod/DualDiff.jl/blob/main/src/Dual.jl&quot;&gt;is here&lt;/a&gt;. For Python, use &lt;a href=&quot;https://github.com/PabRod/dualdiff/blob/main/dualdiff/dual.py&quot;&gt;this link&lt;/a&gt;. I recommend taking a look!&lt;/p&gt;
&lt;p&gt;After this, each and every time our dual number finds one of the operations defined above in its mysterious journey down a function or a script, it will keep track of its effect on the derivative. It doesn’t matter how long, complicated, or poorly programmed the function is, the second coordinate of our dual number will manage it. Well, as long as the function is differentiable and we don’t hit the machine’s precision… but that would be asking our computer to do magic.&lt;/p&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;As an example, let’s calculate the derivative of the polynomial:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;248&quot; height=&quot;27&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-ae298bad.Bb9Nk4Zy_Z1BK9tS.webp&quot; srcset=&quot;&quot;&gt;
at x = 3.&lt;/p&gt;
&lt;p&gt;For the sake of clarity, we can compute the derivative by hand:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;224&quot; height=&quot;27&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-45eb0e13.CT0fgSsk_OLgfP.webp&quot; srcset=&quot;&quot;&gt;
it is apparent that and p(3) = 39 and p’(3) = 34.&lt;/p&gt;
&lt;p&gt;Using our &lt;code&gt;Dual&lt;/code&gt; object, we can reach the same conclusion automatically:&lt;/p&gt;
&lt;p&gt;poly = x -&gt; x^3 + x^2 + x
z = Dual(3, 1)
poly(z)&lt;/p&gt;
&lt;p&gt;&gt; Dual(39, 34)Even if the same polynomial is defined in a more intricate way, the &lt;code&gt;Dual&lt;/code&gt; object can keep track:&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot; Equivalent to poly = x -&gt; x^3 + x^2 + x
Just uglier &quot;&quot;&quot;
function poly(x)
aux = 0 # Initialize auxiliary variable
for n in 1:3 # Add x^1, x^2 and x^3
aux = aux + x^n
end
end&lt;/p&gt;
&lt;p&gt;poly(z)&lt;/p&gt;
&lt;p&gt;&gt; Dual(39, 34)&lt;/p&gt;
&lt;h2 id=&quot;what-about-non-algebraic-functions&quot;&gt;What about non-algebraic functions?&lt;/h2&gt;
&lt;p&gt;The method sketched above will fail miserably as soon as our function contains a non-algebraic element, such as a sine or an exponential. But don’t panic, we can just go to our calculus book and teach our computer some more basic derivatives. For instance, our table of derivatives tells us that the derivative of a sine is a cosine. In the language of dual numbers, this reads:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;313&quot; height=&quot;25&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-0dd189ff.BBfzEf-y_ZK9RUA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Confused about the u’? Once again, this is just the chain rule.*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rule of thumb here is, and actually was since the very beginning:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;484&quot; height=&quot;31&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-d3a44ff1.DFvVYuAW_Fgb5f.webp&quot; srcset=&quot;&quot;&gt;
We can create a &lt;code&gt;_factory&lt;/code&gt; function that abstracts this structure for us:&lt;/p&gt;
&lt;p&gt;function _factory(f::Function, df::Function)::Function
return z -&gt; Dual(f(z.x), df(z.x) * z.dx)
endSo now, we only have to open our derivatives table and fill line by line, starting with the derivative of a sine, continuing with that of a cosine, a tangent, etc.&lt;/p&gt;
&lt;p&gt;import Base: sin, cos&lt;/p&gt;
&lt;p&gt;sin(z::Dual) = _factory(sin, cos)(z)
cos(z::Dual) = _factory(cos, x -&gt; -sin(x))(z) # An explicit lambda function is often requiredIf we know our maths, we don’t even need to fill all the derivatives manually from the table. For instance, the tangent is defined as:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;135&quot; height=&quot;30&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-3c2438c8.CCr9nuWa_XoBAT.webp&quot; srcset=&quot;&quot;&gt;
and we already have automatically differentiable sine, cosine, and division in our arsenal. So this line will do the trick:&lt;/p&gt;
&lt;p&gt;import Base: tan&lt;/p&gt;
&lt;p&gt;tan(z::Dual) = sin(z) / cos(z) # We can rely on previously defined functions!Of course, hard-coding the tangent’s derivative is also possible, and probably good for code performance and numerical stability. But hey, it’s quite cool that this is even possible!&lt;/p&gt;
&lt;p&gt;See a more complete derivatives table &lt;a href=&quot;https://github.com/PabRod/DualDiff.jl/blob/main/src/primitives.jl&quot;&gt;here&lt;/a&gt; (Python version &lt;a href=&quot;https://github.com/PabRod/dualdiff/blob/main/dualdiff/primitives.py&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;example-1&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;Let’s compute the derivative of the non-algebraic function&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;335&quot; height=&quot;28&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-a6b0d3c2.Biri3LFY_Z16f0E.webp&quot; srcset=&quot;&quot;&gt;
It is easy to prove analytically that the derivative is 1 everywhere (notice that the argument of the tangent is actually constant). Now, using &lt;code&gt;Dual&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;fun = x -&gt; x + tan(cos(x)^2 + sin(x)^2)&lt;/p&gt;
&lt;p&gt;z = Dual(0, 1)
fun(z)&lt;/p&gt;
&lt;p&gt;&gt; Dual(1.557407724654902, 1.0)&lt;/p&gt;
&lt;h2 id=&quot;making-it-more-user-friendly&quot;&gt;Making it more user-friendly&lt;/h2&gt;
&lt;p&gt;We can use dual numbers to create a user-friendly derivative function:&lt;/p&gt;
&lt;p&gt;&quot;&quot;&quot;
derivative(f)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Seamlessly turns a given function f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;into&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;the function&apos;s derivative&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&quot;&quot;&quot;
function derivative(f)
df = x -&gt; f(Dual(x, 1.0)).dx
return df
endUsing this, our example above will look like:&lt;/p&gt;
&lt;p&gt;fun = x -&gt; x + tan(cos(x)^2 + sin(x)^2)&lt;/p&gt;
&lt;p&gt;dfun = derivative(f)
dfun(0)&lt;/p&gt;
&lt;p&gt;&gt; 1.0&lt;/p&gt;
&lt;h3 id=&quot;another-example&quot;&gt;Another example**&lt;/h3&gt;
&lt;p&gt;Now we want to calculate and visualize the derivatives of:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;388&quot; height=&quot;31&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-7e1f04a0.DGpBHSBj_vC9q5.webp&quot; srcset=&quot;&quot;&gt;
First, we have to input the function, and the derivative gets calculated automatically:&lt;/p&gt;
&lt;p&gt;f(x) = x^2 - 5x + 6 - 5x^3 - 5 * exp(-50 * x^2)&lt;/p&gt;
&lt;p&gt;df = derivative(f)We can visualize the results by plotting a tangent line:&lt;/p&gt;
&lt;p&gt;using Plots&lt;/p&gt;
&lt;p&gt;I = [-0.7; 0.7]
δ = 0.025
@gif for a = [I[1]:δ:I[2]; I[2]-δ:-δ:I[1]+δ]
L(x) = f(a) + df(a) * (x - a)
plot(f, -1, 1, leg=false)
scatter!([a], [f(a)], m=(:red, 2))
plot!(L, -1, 1, c=:red)
ylims!(-5, 15)
end
&lt;img alt=&quot;Automatic differentiation from scratch&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/automatic-differentiation-from-scratch-fe83078a.B4ZOJz_g_Z2lQYqz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;is-this-useful&quot;&gt;Is this useful?&lt;/h2&gt;
&lt;p&gt;Automatic differentiation is particularly useful in the field of Machine Learning, where multidimensional derivatives (better known as gradients) have to be performed as fast and exactly as possible. Said this, automatic differentiation for Machine Learning is usually implemented in a different way, the so-called backward or reverse mode, for efficiency reasons.&lt;/p&gt;
&lt;p&gt;A well-established library for automatic differentiation is &lt;a href=&quot;https://jax.readthedocs.io/en/latest/&quot;&gt;JAX&lt;/a&gt; (for Python). Machine learning frameworks such as &lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;Tensorflow&lt;/a&gt; and &lt;a href=&quot;https://pytorch.org/&quot;&gt;Pytorch&lt;/a&gt; also implement automatic differentiation. For Julia, multiple libraries &lt;a href=&quot;https://juliadiff.org/&quot;&gt;seem to be competing&lt;/a&gt;, but &lt;a href=&quot;https://enzyme.mit.edu/&quot;&gt;Enzyme.jl&lt;/a&gt; seems to be ahead. &lt;a href=&quot;https://juliadiff.org/ForwardDiff.jl/stable/&quot;&gt;Forwarddiff.jl&lt;/a&gt; is also worth taking a look at.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I want to say thanks to my colleague and friend &lt;a href=&quot;https://abelsiqueira.com&quot;&gt;Abel Siqueira&lt;/a&gt;, for kindly introducing me to Julia and reviewing this post, and to &lt;a href=&quot;https://medium.com/@aronpjansen&quot;&gt;Aron Jansen&lt;/a&gt;, for his kind and useful suggestions. A more in-depth introduction can be found in &lt;a href=&quot;https://book.sciml.ai/notes/08-Forward-Mode_Automatic_Differentiation_(AD)_via_High_Dimensional_Algebras/&quot;&gt;this episode&lt;/a&gt; of Chris Rackauckas’ &lt;a href=&quot;https://book.sciml.ai/&quot;&gt;book on scientific machine learning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/mathaddons/tex-math-here&quot;&gt;TeX Math Here&lt;/a&gt; browser add-in also played an important role: it allowed me to transfer my Latex equations from Markdown to Medium in an (almost) painless way.&lt;/p&gt;</content:encoded><media:content url="data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAAAZCAYAAADpG6rZAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAtGVYSWZJSSoACAAAAAYAEgEDAAEAAAABAAAAGgEFAAEAAABWAAAAGwEFAAEAAABeAAAAKAEDAAEAAAACAAAAEwIDAAEAAAABAAAAaYcEAAEAAABmAAAAAAAAAEgAAAABAAAASAAAAAEAAAAGAACQBwAEAAAAMDIxMAGRBwAEAAAAAQIDAACgBwAEAAAAMDEwMAGgAwABAAAA//8AAAKgBAABAAAAcAAAAAOgBAABAAAAGQAAAAAAAADeQpc6AAADQElEQVR4nN1ajXXiMAyW7rFAV+BGSEeAEXIjcCNwI4QRygjtCM0IzQhkhDKC+j4i94xjJzblJ/H3HhAcx7ItS5Y+h0WEcgMzl0RUi8iRZgJm3hDRioj+mn4zM/63ItKGnvtFmYG7iSjmpDzFloiw8JZWWUNEL8xchB7inCyQO8srReQPzQiqoA/1Gmvn3hMRvRPR2rcos7FA7gZawQXR/ICFB+zcG6q0PSwxawtkZgzwKCL/aGZgZljfk4j8Hqhz0P2xtssXlAGYGfsG9r7gBEy870WE59jrPlnn6EJLbPhD0drE+45IEwoawhuiVFV4lgqsaZ4oVDmD0MXZWPulX4GI5OBvmflTQ3JTXjAzTHiKwUsxpkCMhZkrZn63x+WM71Xbu7QvSTL0d+ULXgJotP5/IIgxH735qWHrh16XWv5q153Kh7q+4WI5UAdj2Oo1ItVPT51qrJ2RflwkQ3PWWBm9dt0g5hQIWEzAUicIDz6nrETX1BOBPSE2HVjha2T/21j5Fcbks7JR1mMEF8kQEVhVLNpeu5Faj14lD7DAqhtG8H5hWQYGj4sXp463PKEPN5cR8jbBNEL9M3KrXeIqmRSk67vpv/EK7n5pypupynAACz9Z8WKM1ZghpziElSb7btRnuMZ6JjK+sQjwctufKE/3zrN8JRHHG1l9qQmxi+KKeeQ9ZDReBaryvGQwwuMEmgrt9MLoBGDhxBLSbUwlPZrp1bfSkJ0duEUk1o+QYQK2Y0+BqjxMek9Jqfmfuo/R5PRKaM3kuTxhAK5lu5N+ihQ987JP8ApJMhJx1vbCCVhqPX/CCjGTUSjRGp1G3BMiUjMzRbhsM2Hf9XTcW+d+4VhGpROOeXi+kYxYnNywXWAs0AQsjcXsG6FQ5NkZ1QTxZgUJXmDvYWbklmBL4IKMW1srcQGesTdBFvsxytD8QEYs8Oy54kNsgFaebP7n9HVDRIfIuoa+Ohublg2xOVVCfy6SMdJm6WN3cjoPPPjOy67YfkoQd7fzzizOAxU733nZNeAe4dwbKr/0nXfmcpxEJijQ92KujW3CicEtECRVsnGhMS8AXQJdEO2j6ETrLTsvuZ+VAsnJZ+dOA1rESnDv/QJBeKCfziT5nwAAAABJRU5ErkJggg==" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!</title><link>https://blog2.esciencecenter.nl/posts/2023-11-06---how-easy-it-can-be-to-whip-up-your-own-orange3-widget-a-chat</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-11-06---how-easy-it-can-be-to-whip-up-your-own-orange3-widget-a-chat</guid><description>&lt;p&gt;4&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Are you ready to dive into the captivating world of Orange3 widgets and unleash your inner chatbot whisperer? 🚀✨ Whether you’re a coding connoisseur or a newbie explorer, developing your own widget doesn’t have to be a Herculean task. In fact, with a little sprinkle of curiosity and a dash of HuggingChat magic, you’ll be crafting your own chatbot widget in no time!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;616&quot; height=&quot;229&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-63271872.CxrTmfMj_8LbTW.webp&quot; srcset=&quot;&quot;&gt;
In a future blog &lt;a href=&quot;https://blog2.esciencecenter.nl/the-orange3-data-mining-platform-as-a-research-tool-2167336a5c0d&quot;&gt;post&lt;/a&gt; by my colleague, Kody Moodley, you will catch a glimpse of what Orange3 is all about, along with its snazzy uniqueness (if not, seriously, what are you waiting for? Go give it a whirl!). But for now, I bet you’re riding the wave of curiosity mixed with a sprinkle of concern — “Will it be a brain drain, and will I get tangled in the web of complexity while treading the path of development?”&lt;/p&gt;
&lt;p&gt;What I aim to convey through this post is that creating widgets on Orange3 is as easy as pie! However, writing the post takes me some serious brainpower. I’ve been on an epic quest to unravel the secrets of making the content simple, yet captivating. But you know what they say, inspiration strikes in the most unexpected places. Picture this: I’m casually chatting with a friend on the newly released Android client of ChatGPT, and bam! Just like that, it hit me — why not roll up my sleeves and craft my very own chatbot widget on Orange3?&lt;/p&gt;
&lt;p&gt;My initial brainstorm led me straight to a ChatGPT-powered chatbot, but alas, I wear the open-source cape proudly! Thus, I turned my gaze toward the enchanting realm of HuggingChat. 🌟 With a dash of curiosity, I dove into the API docs at lightning speed and spent a solid three hours conjuring up all the magic you’re about to read.&lt;/p&gt;
&lt;h2 id=&quot;before-diving-into-the-core&quot;&gt;Before diving into the core&lt;/h2&gt;
&lt;p&gt;Embarking on a journey is always thrilling, but you might find yourself going, “Where in the world do I begin?” Fret not, for Orange3 has your back with a nifty add-on template. No need to suffer the pains of starting from scratch — just give ’em a friendly clone from &lt;a href=&quot;https://github.com/biolab/orange3-example-addon&quot;&gt;GitHub&lt;/a&gt; to your computer and sprinkle in the required Python libraries.&lt;/p&gt;
&lt;p&gt;#Clone the repo of the example Orange3 add-on
git clone &lt;a href=&quot;https://github.com/biolab/orange3-example-addon.git&quot;&gt;https://github.com/biolab/orange3-example-addon.git&lt;/a&gt;
cd orange3-example-addon&lt;/p&gt;
&lt;p&gt;#Install Orange3 and other required packages
python -m venv orangedev&lt;br&gt;
source orangedev/bin/activate
pip install pyqt6 pyqt6-webengine orange3 hugchatTime for a little detective work! Execute these commands to check if you have everything in the right place.&lt;/p&gt;
&lt;p&gt;#Install the example add-on and open the GUI application of Orange
pip install -e .&lt;br&gt;
python -m Orange.canvas  If everything goes well, you should be able to see the following window popping up, where you can find that your &lt;em&gt;Example&lt;/em&gt; add-on and &lt;em&gt;Hello World&lt;/em&gt; widget are already there.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;520&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-0731634a.BnLglC5T_Z1fmEqy.webp&quot; srcset=&quot;&quot;&gt;
The canvas application with the example add-on installed.&lt;/p&gt;
&lt;h2 id=&quot;the-serious-showdown&quot;&gt;The serious showdown&lt;/h2&gt;
&lt;p&gt;Before we wade into the treacherous waters ahead, let’s take a peek at what awaits from these three hours of dedicated effort.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1232&quot; height=&quot;822&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-e0526449.CWhEQcUE_1eLMh3.webp&quot; srcset=&quot;&quot;&gt;
The chatbot widget.In brief, I have a chatbot that allows me to log in with my own HuggingFace account and password, answer my questions, and record all of the historical conversations. The only thing I did was create a Python file named “HugChat.py*” *and put it in the folder “orange3-example-addon/orangecontrib/example/widgets”. Check the content of my file to get a first impression of how easy the work is.&lt;/p&gt;
&lt;p&gt;#Content of the HugChat.py file
from Orange.data import Table
from Orange.widgets import gui
from Orange.widgets.settings import Setting
from Orange.widgets.widget import OWWidget, Output
from Orange.data.pandas_compat import table_from_frame&lt;/p&gt;
&lt;p&gt;from hugchat.login import Login
from hugchat import hugchat
import textwrap
import pandas as pd&lt;/p&gt;
&lt;p&gt;class HugChat(OWWidget):
name = “Hugging Chatbot”
description = “Orange3 widget instance of HuggingChat.”
icon = “icons/mywidget.svg”
want_main_area = True&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;email = Setting(&quot;&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;passwd = Setting(&quot;&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;query = Setting(&quot;&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class Outputs:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    data = Output(&quot;Data&quot;, Table)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;def __init__(self):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    super().__init__()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.queries = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.replies = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.chatbot = None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # control area: login&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.lineEdit(widget=self.controlArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 value=&quot;email&quot;, label=&quot;Email&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.lineEdit(widget=self.controlArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 value=&quot;passwd&quot;, label=&quot;Password&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.button(widget=self.controlArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;               label=&quot;Login&quot;, callback=self.init_chatbot)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # main area: chatbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.lineEdit(widget=self.mainArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 value=&quot;query&quot;, label=&quot;Query&quot;, callback=self.chat)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.reply = gui.WebviewWidget(parent=None, debug=False)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.mainArea.layout().addWidget(self.reply)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;def init_chatbot(self):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    sign = Login(self.email, self.passwd) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # cookies setup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cookie_path_dir = &quot;./cookies_snapshot&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    sign.saveCookiesToDir(cookie_path_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cookies = sign.login()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # initialize chatbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.chatbot = hugchat.ChatBot(cookies=cookies.get_dict())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # initialize a new conversation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id = self.chatbot.new_conversation()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.chatbot.change_conversation(id)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;def chat(self):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    reply_text = self.chatbot.chat(text=self.query)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.reply.setHtml(reply_text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # update the output table&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.queries.append(self.query)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.replies.append(reply_text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    df_output = pd.DataFrame({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &quot;Query&quot;: self.queries, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &quot;Reply&quot;: self.replies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.Outputs.data.send(table_from_frame(df_output))Now, let’s look at the details. The code above defines a class that contains all the features and functions of our widget. This class is inherited from another class named `OWWidget`, which is the base class of all Orange3 widgets. From there, we can rewrite existing functions and create new functions to satisfy our requirements.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the top of the class, we have a brief description of the widget, including its name, a short text explaining what it does, and a path string pointing to the location of the widget icon. An additional flag called &lt;code&gt;want_main_area&lt;/code&gt; is assigned to be true, which means that we want to present the main area of the widget and show things there.&lt;/p&gt;
&lt;p&gt;name = “Hugging Chatbot”
description = “Orange3 widget instance of HuggingChat.”
icon = “icons/mywidget.svg”
want_main_area = TrueA widget can contain both the control and main area, while the main area is optional. To briefly explain, the control area should contain all of the utilities for preparing the widget, while the main area is for the major functionality.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;438&quot; height=&quot;129&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-92940abc.n9LoFlfw_1iwNgH.webp&quot; srcset=&quot;&quot;&gt;
Sub-interface of our widget that includes both the control and main area.We also have three class attributes defined, which will be used to store the result of interacting with the GUI controls (I will come back to this later). If there are any output tables, they will be defined in an inner class named &lt;code&gt;Outputs&lt;/code&gt;. In our case, we only have one output table for outputting the chatting history.&lt;/p&gt;
&lt;p&gt;email = Setting(&quot;&quot;)
passwd = Setting(&quot;&quot;)
query = Setting(&quot;&quot;)&lt;/p&gt;
&lt;p&gt;class Outputs:
data = Output(“Data”, Table)Next, we defined the &lt;code&gt;__init__&lt;/code&gt; method, where we run &lt;code&gt;__init__&lt;/code&gt; of the parent class, initialize all the instance attributes, and define the GUI of the widget. We got two empty lists, &lt;code&gt;queries&lt;/code&gt; and &lt;code&gt;replies&lt;/code&gt;, for storing the chat history, and &lt;code&gt;chatbot&lt;/code&gt; which is the HuggingChat object. Now, let’s focus on the part of GUI construction.&lt;/p&gt;
&lt;h1 id=&quot;control-area-login&quot;&gt;control area: login&lt;/h1&gt;
&lt;p&gt;gui.lineEdit(widget=self.controlArea, master=self,
value=“email”, label=“Email”)
gui.lineEdit(widget=self.controlArea, master=self,
value=“passwd”, label=“Password”)
gui.button(widget=self.controlArea, master=self,
label=“Login”, callback=self.init_chatbot)&lt;/p&gt;
&lt;h1 id=&quot;main-area-chatbot&quot;&gt;main area: chatbot&lt;/h1&gt;
&lt;p&gt;gui.lineEdit(widget=self.mainArea, master=self,
value=“query”, label=“Query”, callback=self.chat)
self.reply = gui.WebviewWidget(parent=None, debug=False)
self.mainArea.layout().addWidget(self.reply)The above code adds GUI controls to both the control and main area, where GUI controls will be added and placed in the interface by following the order of their definitions in the code. You should be able to find three types of GUI controls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lineEdit&lt;/code&gt; that allows the user to input some text,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;button&lt;/code&gt; that will trigger a pre-defined function by clicking, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WebviewWidget&lt;/code&gt; that will render some HTML content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blog, I will not explain everything so that you will have the motivation to check the &lt;a href=&quot;https://orange-widget-base.readthedocs.io/en/latest/gui.html&quot;&gt;documentation&lt;/a&gt; yourselves. To briefly summarize:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the control area, two &lt;code&gt;lineEdit&lt;/code&gt; controls are defined to accept the login information as input and store them in the pre-defined class attributes &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;query&lt;/code&gt;. They are followed by a button to trigger the callback method &lt;code&gt;self.init_chatbot&lt;/code&gt; for initializing the chatbot instance.&lt;/li&gt;
&lt;li&gt;In the main area, another &lt;code&gt;lineEdit&lt;/code&gt; control is defined as accepting the user’s query, with the callback &lt;code&gt;self.chat&lt;/code&gt; to send the query to the chatbot instance and get the reply, triggered by enter-clicking. The callback method is also responded to display the reply message in the &lt;code&gt;WebviewWidget&lt;/code&gt; below.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Up to this point, we have thoroughly reviewed the process of defining a widget. In simple terms, it includes widget descriptions, input-output definitions, and GUI control definitions. Although the functionalities of different widgets may vary, the design process is largely similar. Orange3 defines a multitude of foundational classes, standardizes data transfer between widgets, and establishes a comprehensive and efficient workflow engine. This enables developers to better focus on the modular design and development of widget functionalities&lt;/p&gt;
&lt;h2 id=&quot;the-adventure-has-just-begun&quot;&gt;The adventure has just begun&lt;/h2&gt;
&lt;p&gt;So, I bet you’re already getting the hang of developing your own widgets on Orange3, and you’re practically bursting with creative energy – high five to that! But hold your horses, my friend, because this blog post is just the opening scene of our grand adventure. There’s a whole treasure trove of discoveries waiting for you, like defining your very own add-on, crafting widgets that dance with interactive visuals, and even sending your widgets off to the fancy official platform. Don’t panic, though – these aren’t things you need to wrestle with right now. And guess what? You’re not alone on this journey! Craving more Orange3 tales and tech tidbits? Get in touch with us (&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-kody-moodley/&quot;&gt;Kody&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-ji-qi/&quot;&gt;me&lt;/a&gt;)! Or drop a hint for more juicy insights below this blog! Can’t wait to bump into you again on this wild Orange3 expedition!&lt;/p&gt;
&lt;p&gt;DISCLAIMER: As you probably found out from the start: we also called in some AI support for the creation of this blogpost. We prompted ChatGPT to make the original text ‘more fun to read’. We hope reading it actually sparked some joy for you!*&lt;/p&gt;</description><pubDate>Mon, 06 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;4&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Are you ready to dive into the captivating world of Orange3 widgets and unleash your inner chatbot whisperer? 🚀✨ Whether you’re a coding connoisseur or a newbie explorer, developing your own widget doesn’t have to be a Herculean task. In fact, with a little sprinkle of curiosity and a dash of HuggingChat magic, you’ll be crafting your own chatbot widget in no time!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;616&quot; height=&quot;229&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-63271872.CxrTmfMj_8LbTW.webp&quot; srcset=&quot;&quot;&gt;
In a future blog &lt;a href=&quot;https://blog2.esciencecenter.nl/the-orange3-data-mining-platform-as-a-research-tool-2167336a5c0d&quot;&gt;post&lt;/a&gt; by my colleague, Kody Moodley, you will catch a glimpse of what Orange3 is all about, along with its snazzy uniqueness (if not, seriously, what are you waiting for? Go give it a whirl!). But for now, I bet you’re riding the wave of curiosity mixed with a sprinkle of concern — “Will it be a brain drain, and will I get tangled in the web of complexity while treading the path of development?”&lt;/p&gt;
&lt;p&gt;What I aim to convey through this post is that creating widgets on Orange3 is as easy as pie! However, writing the post takes me some serious brainpower. I’ve been on an epic quest to unravel the secrets of making the content simple, yet captivating. But you know what they say, inspiration strikes in the most unexpected places. Picture this: I’m casually chatting with a friend on the newly released Android client of ChatGPT, and bam! Just like that, it hit me — why not roll up my sleeves and craft my very own chatbot widget on Orange3?&lt;/p&gt;
&lt;p&gt;My initial brainstorm led me straight to a ChatGPT-powered chatbot, but alas, I wear the open-source cape proudly! Thus, I turned my gaze toward the enchanting realm of HuggingChat. 🌟 With a dash of curiosity, I dove into the API docs at lightning speed and spent a solid three hours conjuring up all the magic you’re about to read.&lt;/p&gt;
&lt;h2 id=&quot;before-diving-into-the-core&quot;&gt;Before diving into the core&lt;/h2&gt;
&lt;p&gt;Embarking on a journey is always thrilling, but you might find yourself going, “Where in the world do I begin?” Fret not, for Orange3 has your back with a nifty add-on template. No need to suffer the pains of starting from scratch — just give ’em a friendly clone from &lt;a href=&quot;https://github.com/biolab/orange3-example-addon&quot;&gt;GitHub&lt;/a&gt; to your computer and sprinkle in the required Python libraries.&lt;/p&gt;
&lt;p&gt;#Clone the repo of the example Orange3 add-on
git clone &lt;a href=&quot;https://github.com/biolab/orange3-example-addon.git&quot;&gt;https://github.com/biolab/orange3-example-addon.git&lt;/a&gt;
cd orange3-example-addon&lt;/p&gt;
&lt;p&gt;#Install Orange3 and other required packages
python -m venv orangedev&lt;br&gt;
source orangedev/bin/activate
pip install pyqt6 pyqt6-webengine orange3 hugchatTime for a little detective work! Execute these commands to check if you have everything in the right place.&lt;/p&gt;
&lt;p&gt;#Install the example add-on and open the GUI application of Orange
pip install -e .&lt;br&gt;
python -m Orange.canvas  If everything goes well, you should be able to see the following window popping up, where you can find that your &lt;em&gt;Example&lt;/em&gt; add-on and &lt;em&gt;Hello World&lt;/em&gt; widget are already there.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;520&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-0731634a.BnLglC5T_Z1fmEqy.webp&quot; srcset=&quot;&quot;&gt;
The canvas application with the example add-on installed.&lt;/p&gt;
&lt;h2 id=&quot;the-serious-showdown&quot;&gt;The serious showdown&lt;/h2&gt;
&lt;p&gt;Before we wade into the treacherous waters ahead, let’s take a peek at what awaits from these three hours of dedicated effort.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1232&quot; height=&quot;822&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-e0526449.CWhEQcUE_1eLMh3.webp&quot; srcset=&quot;&quot;&gt;
The chatbot widget.In brief, I have a chatbot that allows me to log in with my own HuggingFace account and password, answer my questions, and record all of the historical conversations. The only thing I did was create a Python file named “HugChat.py*” *and put it in the folder “orange3-example-addon/orangecontrib/example/widgets”. Check the content of my file to get a first impression of how easy the work is.&lt;/p&gt;
&lt;p&gt;#Content of the HugChat.py file
from Orange.data import Table
from Orange.widgets import gui
from Orange.widgets.settings import Setting
from Orange.widgets.widget import OWWidget, Output
from Orange.data.pandas_compat import table_from_frame&lt;/p&gt;
&lt;p&gt;from hugchat.login import Login
from hugchat import hugchat
import textwrap
import pandas as pd&lt;/p&gt;
&lt;p&gt;class HugChat(OWWidget):
name = “Hugging Chatbot”
description = “Orange3 widget instance of HuggingChat.”
icon = “icons/mywidget.svg”
want_main_area = True&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;email = Setting(&quot;&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;passwd = Setting(&quot;&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;query = Setting(&quot;&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;class Outputs:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    data = Output(&quot;Data&quot;, Table)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;def __init__(self):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    super().__init__()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.queries = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.replies = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.chatbot = None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # control area: login&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.lineEdit(widget=self.controlArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 value=&quot;email&quot;, label=&quot;Email&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.lineEdit(widget=self.controlArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 value=&quot;passwd&quot;, label=&quot;Password&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.button(widget=self.controlArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;               label=&quot;Login&quot;, callback=self.init_chatbot)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # main area: chatbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    gui.lineEdit(widget=self.mainArea, master=self, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                 value=&quot;query&quot;, label=&quot;Query&quot;, callback=self.chat)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.reply = gui.WebviewWidget(parent=None, debug=False)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.mainArea.layout().addWidget(self.reply)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;def init_chatbot(self):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    sign = Login(self.email, self.passwd) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # cookies setup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cookie_path_dir = &quot;./cookies_snapshot&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    sign.saveCookiesToDir(cookie_path_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    cookies = sign.login()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # initialize chatbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.chatbot = hugchat.ChatBot(cookies=cookies.get_dict())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # initialize a new conversation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id = self.chatbot.new_conversation()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.chatbot.change_conversation(id)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;def chat(self):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    reply_text = self.chatbot.chat(text=self.query)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.reply.setHtml(reply_text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    # update the output table&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.queries.append(self.query)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.replies.append(reply_text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    df_output = pd.DataFrame({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &quot;Query&quot;: self.queries, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        &quot;Reply&quot;: self.replies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    self.Outputs.data.send(table_from_frame(df_output))Now, let’s look at the details. The code above defines a class that contains all the features and functions of our widget. This class is inherited from another class named `OWWidget`, which is the base class of all Orange3 widgets. From there, we can rewrite existing functions and create new functions to satisfy our requirements.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the top of the class, we have a brief description of the widget, including its name, a short text explaining what it does, and a path string pointing to the location of the widget icon. An additional flag called &lt;code&gt;want_main_area&lt;/code&gt; is assigned to be true, which means that we want to present the main area of the widget and show things there.&lt;/p&gt;
&lt;p&gt;name = “Hugging Chatbot”
description = “Orange3 widget instance of HuggingChat.”
icon = “icons/mywidget.svg”
want_main_area = TrueA widget can contain both the control and main area, while the main area is optional. To briefly explain, the control area should contain all of the utilities for preparing the widget, while the main area is for the major functionality.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How Easy It Can Be to Whip Up Your Own Orange3 Widget: A Chatbot Adventure with HuggingChat!&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;438&quot; height=&quot;129&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-92940abc.n9LoFlfw_1iwNgH.webp&quot; srcset=&quot;&quot;&gt;
Sub-interface of our widget that includes both the control and main area.We also have three class attributes defined, which will be used to store the result of interacting with the GUI controls (I will come back to this later). If there are any output tables, they will be defined in an inner class named &lt;code&gt;Outputs&lt;/code&gt;. In our case, we only have one output table for outputting the chatting history.&lt;/p&gt;
&lt;p&gt;email = Setting(&quot;&quot;)
passwd = Setting(&quot;&quot;)
query = Setting(&quot;&quot;)&lt;/p&gt;
&lt;p&gt;class Outputs:
data = Output(“Data”, Table)Next, we defined the &lt;code&gt;__init__&lt;/code&gt; method, where we run &lt;code&gt;__init__&lt;/code&gt; of the parent class, initialize all the instance attributes, and define the GUI of the widget. We got two empty lists, &lt;code&gt;queries&lt;/code&gt; and &lt;code&gt;replies&lt;/code&gt;, for storing the chat history, and &lt;code&gt;chatbot&lt;/code&gt; which is the HuggingChat object. Now, let’s focus on the part of GUI construction.&lt;/p&gt;
&lt;h1 id=&quot;control-area-login&quot;&gt;control area: login&lt;/h1&gt;
&lt;p&gt;gui.lineEdit(widget=self.controlArea, master=self,
value=“email”, label=“Email”)
gui.lineEdit(widget=self.controlArea, master=self,
value=“passwd”, label=“Password”)
gui.button(widget=self.controlArea, master=self,
label=“Login”, callback=self.init_chatbot)&lt;/p&gt;
&lt;h1 id=&quot;main-area-chatbot&quot;&gt;main area: chatbot&lt;/h1&gt;
&lt;p&gt;gui.lineEdit(widget=self.mainArea, master=self,
value=“query”, label=“Query”, callback=self.chat)
self.reply = gui.WebviewWidget(parent=None, debug=False)
self.mainArea.layout().addWidget(self.reply)The above code adds GUI controls to both the control and main area, where GUI controls will be added and placed in the interface by following the order of their definitions in the code. You should be able to find three types of GUI controls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lineEdit&lt;/code&gt; that allows the user to input some text,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;button&lt;/code&gt; that will trigger a pre-defined function by clicking, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WebviewWidget&lt;/code&gt; that will render some HTML content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blog, I will not explain everything so that you will have the motivation to check the &lt;a href=&quot;https://orange-widget-base.readthedocs.io/en/latest/gui.html&quot;&gt;documentation&lt;/a&gt; yourselves. To briefly summarize:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In the control area, two &lt;code&gt;lineEdit&lt;/code&gt; controls are defined to accept the login information as input and store them in the pre-defined class attributes &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;query&lt;/code&gt;. They are followed by a button to trigger the callback method &lt;code&gt;self.init_chatbot&lt;/code&gt; for initializing the chatbot instance.&lt;/li&gt;
&lt;li&gt;In the main area, another &lt;code&gt;lineEdit&lt;/code&gt; control is defined as accepting the user’s query, with the callback &lt;code&gt;self.chat&lt;/code&gt; to send the query to the chatbot instance and get the reply, triggered by enter-clicking. The callback method is also responded to display the reply message in the &lt;code&gt;WebviewWidget&lt;/code&gt; below.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Up to this point, we have thoroughly reviewed the process of defining a widget. In simple terms, it includes widget descriptions, input-output definitions, and GUI control definitions. Although the functionalities of different widgets may vary, the design process is largely similar. Orange3 defines a multitude of foundational classes, standardizes data transfer between widgets, and establishes a comprehensive and efficient workflow engine. This enables developers to better focus on the modular design and development of widget functionalities&lt;/p&gt;
&lt;h2 id=&quot;the-adventure-has-just-begun&quot;&gt;The adventure has just begun&lt;/h2&gt;
&lt;p&gt;So, I bet you’re already getting the hang of developing your own widgets on Orange3, and you’re practically bursting with creative energy – high five to that! But hold your horses, my friend, because this blog post is just the opening scene of our grand adventure. There’s a whole treasure trove of discoveries waiting for you, like defining your very own add-on, crafting widgets that dance with interactive visuals, and even sending your widgets off to the fancy official platform. Don’t panic, though – these aren’t things you need to wrestle with right now. And guess what? You’re not alone on this journey! Craving more Orange3 tales and tech tidbits? Get in touch with us (&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-kody-moodley/&quot;&gt;Kody&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-ji-qi/&quot;&gt;me&lt;/a&gt;)! Or drop a hint for more juicy insights below this blog! Can’t wait to bump into you again on this wild Orange3 expedition!&lt;/p&gt;
&lt;p&gt;DISCLAIMER: As you probably found out from the start: we also called in some AI support for the creation of this blogpost. We prompted ChatGPT to make the original text ‘more fun to read’. We hope reading it actually sparked some joy for you!*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-easy-it-can-be-to-whip-up-your-own-o-63271872.CxrTmfMj.png" medium="image"/><author>Ji Qi</author></item><item><title>Investing in people: anticipating the future of research software</title><link>https://blog2.esciencecenter.nl/posts/2023-11-02---investing-in-people-anticipating-the-future-of-research-soft</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-11-02---investing-in-people-anticipating-the-future-of-research-soft</guid><description>&lt;p&gt;*Authored by &lt;em&gt;&lt;a href=&quot;https://www.researchsoft.org/people/&quot;&gt;&lt;em&gt;Kim Hartley&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and *&lt;a href=&quot;https://www.researchsoft.org/people/&quot;&gt;&lt;em&gt;Michelle Barker&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Investing in people: anticipating the future of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/investing-in-people-anticipating-the-fut-ec87efa8.660bh7id_nX0HL.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Photo credit: ADORE.Software&lt;/em&gt; at the International Research Software Funders WorkshopThis article was cross-posted on &lt;a href=&quot;https://adore.software/2023/10/investing-in-people-anticipating-the-future-of-research-software/&quot;&gt;Adore.software&lt;/a&gt; and reports on the progress of the Amsterdam Declaration on Funding Research Software Sustainability. To read more about this initiative and the initial workshop see &lt;a href=&quot;https://blog2.esciencecenter.nl/the-future-of-research-software-602878378c5f&quot;&gt;this blogpost&lt;/a&gt; from November 2022.&lt;/p&gt;
&lt;p&gt;We are proud to report that the second &lt;a href=&quot;https://adore.software/international-research-software-funders-workshop/&quot;&gt;International Research Software Funders Workshop&lt;/a&gt;, co-hosted by the &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt; (the Alliance) and the &lt;a href=&quot;https://www.researchsoft.org/&quot;&gt;Research Software Alliance&lt;/a&gt; (ReSA) from 18–20 September was a great success. People are at the heart of research software sustainability and funders can lead the way by investing in the people who develop and maintain research software. That is why the workshop theme was “Investing in People: Anticipating the Future of Research Software”. The event aimed to set the future agenda for government, philanthropic, and industry funders to support sustainable research software and communities.&lt;/p&gt;
&lt;p&gt;In total, 50 representatives from more than 35 organisations — including funders and organisations that support research software from around the globe — attended the hybrid workshop held in Montreal, Canada, and virtually. During the three-day workshop, experts explored how research software funders can facilitate capacity building through funder practices; research software platforms, infrastructure, and communities; and new initiatives. Moreover, &lt;a href=&quot;https://adore.software/2023/09/adore-software-is-ready-for-signing/&quot;&gt;Version 1.0 of the Amsterdam Declaration on Funding Research Software Sustainability (ADORE.software)&lt;/a&gt; was released and is now available for &lt;a href=&quot;https://adore.software/get-involved/&quot;&gt;signing&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background**&lt;/h2&gt;
&lt;p&gt;This second iteration of the funders workshop built on the inaugural &lt;a href=&quot;https://future-of-research-software.org/&quot;&gt;International Funders Workshop: The Future of Research Software&lt;/a&gt;, co-hosted by the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and ReSA in November 2022 in Amsterdam. During this first workshop, more than 40 funding organisations gathered to set the agenda for supporting sustainable research software and drafting of the &lt;a href=&quot;https://adore.software/declaration/&quot;&gt;ADORE.software&lt;/a&gt;. Following public consultation in 2023 and 19 organisational expressions of interest in becoming signatories,&lt;a href=&quot;https://adore.software/2023/09/adore-software-is-ready-for-signing/&quot;&gt; Version 1.0 of the Declaration was released&lt;/a&gt; in advance of the Montreal workshop and is now available for &lt;a href=&quot;https://adore.software/get-involved/&quot;&gt;signing&lt;/a&gt;. ADORE.software is the first step towards formalising, on a global level, the basic principles and recommendations related to funding the sustainability of research software, including the people needed to achieve this goal.&lt;/p&gt;
&lt;p&gt;The first workshop marked a further step in the development of the research software community. Stakeholders have continued to build on this momentum through involvement in the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt;, convened by ReSA, and its funder-led working groups. The Alliance and ReSA, together with the workshop Steering Committee, organised the 2nd International Research Software Funders Workshop to continue this important work and facilitate global collaboration among funders and other key decision makers and influencers across the research software ecosystem.&lt;/p&gt;
&lt;h2 id=&quot;2nd-international-research-software-funders-workshop&quot;&gt;&lt;strong&gt;2nd International Research Software Funders Workshop&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Pre-workshop — September 18&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The event commenced with a pre-workshop, including a session on &lt;a href=&quot;https://docs.google.com/presentation/d/1UP_UGOPxYi0R4UAE5PRpGWoJzrQ2FkVmCdDBILR6t2U/edit#slide=id.g241153165a8_0_0&quot;&gt;How to Explicitly Support Research Software as Part of Your Funding Program&lt;/a&gt;, delivered by ReSA, and a session on &lt;a href=&quot;https://zenodo.org/records/8356278&quot;&gt;CiteSoftware&lt;/a&gt;, led by a group of stakeholders aiming to drive the adoption of a common research software preservation and citation guidance resource for the research community.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Investing in people: anticipating the future of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/investing-in-people-anticipating-the-fut-708c46e1.d9EqJ9Ja_274aPE.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Photo credit: ADORE.Software&lt;/em&gt; at the International Research Software Funders Workshop&lt;em&gt;&lt;strong&gt;Workshop Day 1 — September 19&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The first day of the workshop included presentations that set the scene for participants to explore the crucial role funders play in supporting sustainable research software and communities.&lt;/p&gt;
&lt;p&gt;Carole Goble from the Software Sustainability Institute (SSI)/ELIXIR-UK/University of Manchester &lt;a href=&quot;https://docs.google.com/presentation/d/1dJrhjm7SAcLA96adZsBT-mFiJiwL3Fby/edit?usp=share_link&amp;#x26;ouid=116347134185833638908&amp;#x26;rtpof=true&amp;#x26;sd=true&quot;&gt;provided an overview&lt;/a&gt; of what research software is and why it is critical to the research endeavour. Carole highlighted that the people who make, use, and resource software are fundamental to research software sustainability. Moreover, research software needs resources and both direct (e.g., money) and indirect (e.g., community, reward, recognition, open-source support, etc.) forms of support for sustainability.&lt;/p&gt;
&lt;p&gt;Josh Greenberg from the Alfred P. Sloan Foundation delivered a &lt;a href=&quot;https://drive.google.com/file/d/1MPQ3LgO1jZdJIaF74oSz71XGye2ZjG64/view?usp=share_link&quot;&gt;keynote&lt;/a&gt; that provided a funder’s perspective. He asked attendees several pertinent questions: How much (and when) should we worry about technical debt? How much attention should we pay to user interface design in research software? Who should do which kinds of software? How central should “open source” be? How can we help institutions build capacity for research software development (and maintenance)?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Funders benefit from investing both before (community/need development) and after (ongoing maintenance and re-use) research software development.&lt;/li&gt;
&lt;li&gt;International collaboration and collective action are critical and valuable (e.g., building a multilateral funding initiative due to the global nature of research software).&lt;/li&gt;
&lt;li&gt;Funders should consider how to support and sustain Research Software Engineers (RSEs) but also incentivise researcher-developers to develop better software engineering practices.&lt;/li&gt;
&lt;li&gt;The research software community needs a set of high-level classes to measure the impact of research software, such as citations and mentions of software maturity, or combining mention analysis and dependency analysis.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Malvika Sharan from The Alan Turing Institute and Open Life Science provided a research software community perspective in her &lt;a href=&quot;https://zenodo.org/records/8361334&quot;&gt;talk&lt;/a&gt; on Exploring ‘Do No Harm’ Principles in Open Research Communities. Malvika’s compelling keynote encouraged funders to become leaders in the research software ecosystem by incentivising and recognising all types of research roles; investing in capacity-building goals that focus on bridging scientific and economic divides; and applying community-oriented frameworks to extend the benefits of research to the broader community that ‘do no harm’, thereby ensuring open science practices enable equitable research and research outcomes.&lt;/p&gt;
&lt;p&gt;During the second breakout session, participants investigated capacity building through research software platforms, infrastructure, and communities. One group explored the role of &lt;a href=&quot;https://www.researchsoft.org/blog/2023-06/&quot;&gt;Open Source Program Offices&lt;/a&gt; (OSPOs), noting that OSPOs as centres of software could ultimately help research institutions understand their software investments. Another group considered why and how to support research software communities, highlighting the need for more evidence-led recommendations and exploring the possibility of reversing the funding mechanism to fund projects after the fact, as a function of how much they were used. In discussing research software in research assessment reform, participants noted that very few research software outputs are being assessed and indicators are fragmented and field-specific. Some solutions include sharing guidance on how software is being evaluated in a single place, sharing job profiles for RSEs, and sharing existing examples of research indicators that include software. Finally, another group highlighted that the environmental impact of research software is an emerging field, and persuading researchers to think about making their code efficient is a challenge.&lt;/p&gt;
&lt;p&gt;Workshop Day 2 — September 20***&lt;/p&gt;
&lt;p&gt;The final breakout session focused on building capacity through new initiatives. Participants explored how funders can implement &lt;a href=&quot;https://www.nature.com/articles/s41597-022-01710-x&quot;&gt;FAIR for Research Software&lt;/a&gt; (FAIR4RS) in funder policy. As some funders are developing guidance, questions arose about whether funders should create guidance individually or collectively and how the community should help funders do this. Through a discussion on how funders use persistent identifiers (PIDs), the need to engage publishers around software citation has become clear. And building on the theme of software citation, participants explored how the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt;, a free open-source platform, supports software citation.&lt;/p&gt;
&lt;p&gt;For the final &lt;a href=&quot;https://drive.google.com/file/d/1tzh5cSKX-3yZpqEqzMx7XtfEM9S6jtQY/view?usp=share_link&quot;&gt;keynote&lt;/a&gt;, Jean-Baptiste Poline from McGill University provided a researcher’s perspective on the impact of funders’ investments in research software. Jean-Baptiste presented the role of research software from multiple viewpoints, offering key takeaways such as the value of building a community of researchers through collaborative projects; the need for community-endorsed standards and practices that support open and FAIR (Findable, Accessible, Interoperable, and Reusable) scientific research (e.g., &lt;a href=&quot;https://www.incf.org/&quot;&gt;INCF Network&lt;/a&gt;) to maximise research value; the importance of addressing incentives first; and the idea of funding new technologies and large labs but giving precedence to well-governed communities more than centralised projects. He recommended creating the tools needed to change culture, improving training and open practices, developing community standards, and changing incentives.&lt;/p&gt;
&lt;p&gt;The workshop culminated with a Do-a-Thon, “a short collaboration where participants from different perspectives and skill sets work together on challenges, projects, or to learn something new” (&lt;a href=&quot;https://opencon-cascadia.github.io/doathon/&quot;&gt;OpenCon Cascadia&lt;/a&gt;). Prior to the workshop, participants were invited to submit do-able ideas. During the Do-a-Thon, attendees worked in small groups on the following topics: the &lt;a href=&quot;https://kumu.io/jstarr/ossci-moss&quot;&gt;Map of Open Source Science&lt;/a&gt;; linking software to community usage; and ten things applicants should do to make it easier to assess the impact of funding programs, to build on &lt;a href=&quot;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC9671312/&quot;&gt;Ten simple rules for funding scientific open source software&lt;/a&gt; by Carly Strasser et al. This dynamic collaboration resulted in participants considering next steps, crowdsourcing tips, and determining some practical and generalisable approaches to address the challenges explored.&lt;/p&gt;
&lt;h2 id=&quot;overall-outcomes-and-how-you-can-get-involved&quot;&gt;&lt;strong&gt;Overall outcomes and how you can get involved&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The workshop solidified the importance of international collaboration to support research software. There is a widening group of funders with awareness of the need to support research software and an understanding of how to do this. The &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; has been building momentum since its inception in early 2022; its dedicated funder-led working groups are expanding their reach by engaging with other stakeholders and organisations, such as the &lt;a href=&quot;https://globalresearchcouncil.org/&quot;&gt;Global Research Council&lt;/a&gt;. Moreover, the workshop highlighted areas where coordination by funders would be beneficial, for example, in supporting the &lt;a href=&quot;https://adore.software/declaration/&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability&lt;/a&gt;. Participants also expressed an interest in exploring opportunities for forums, for example to engage publishers around software citations (along with the existing &lt;a href=&quot;https://www.researchsoft.org/taskforces/&quot;&gt;ReSA Task Force on Code Availability&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;We thank all the participants for their engagement during the workshop sessions. We’re grateful to the workshop Steering Committee for their efforts in organising a successful hybrid workshop. A full report, written and edited collectively by workshop participants, is forthcoming.&lt;/p&gt;
&lt;p&gt;To stay up to date on ADORE.software, visit &lt;a href=&quot;http://www.adore.software/&quot;&gt;www.adore.software&lt;/a&gt;. If you want to show your support for the Declaration, you can become a &lt;a href=&quot;https://adore.software/sign/&quot;&gt;signatory&lt;/a&gt; (for funders) or &lt;a href=&quot;https://adore.software/support/&quot;&gt;supporter&lt;/a&gt; (for non-funders) and help share the &lt;a href=&quot;https://adore.software/2023/09/adore-software-is-ready-for-signing/&quot;&gt;news&lt;/a&gt;. To receive updates on news related to the Declaration and future activities, subscribe to the &lt;a href=&quot;https://landing.mailerlite.com/webforms/landing/i5e1h2&quot;&gt;ReSA newsletter&lt;/a&gt;. Funders are invited to join the (free) &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; by contacting ReSA at &lt;a href=&quot;mailto:info@researchsoft.org&quot;&gt;info@researchsoft.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you’re interested in learning more about ReSA and its activities, join our next &lt;a href=&quot;https://www.researchsoft.org/events/2022-06/&quot;&gt;Research Software Community Leaders Forum&lt;/a&gt; on 15 November at 20:00 UTC. ReSA’s Community Leaders Forum is open to all, and you can &lt;a href=&quot;https://landing.mailerlite.com/webforms/landing/o1n4v3&quot;&gt;sign up&lt;/a&gt; for calendar invites.&lt;/p&gt;
&lt;p&gt;We would like to express our sincere gratitude to our community, Founding Members, and Organisational Members — without whom none of this work would have been possible.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This project has also been made possible in part by grant 2021–000000 from the &lt;em&gt;&lt;a href=&quot;https://chanzuckerberg.com/&quot;&gt;&lt;em&gt;Chan Zuckerberg Initiative DAF&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, an advised fund of the Silicon Valley Community Foundation; and the &lt;em&gt;&lt;a href=&quot;https://sloan.org/&quot;&gt;&lt;em&gt;Alfred P. Sloan Foundation&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 02 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;*Authored by &lt;em&gt;&lt;a href=&quot;https://www.researchsoft.org/people/&quot;&gt;&lt;em&gt;Kim Hartley&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and *&lt;a href=&quot;https://www.researchsoft.org/people/&quot;&gt;&lt;em&gt;Michelle Barker&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Investing in people: anticipating the future of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/investing-in-people-anticipating-the-fut-ec87efa8.660bh7id_nX0HL.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Photo credit: ADORE.Software&lt;/em&gt; at the International Research Software Funders WorkshopThis article was cross-posted on &lt;a href=&quot;https://adore.software/2023/10/investing-in-people-anticipating-the-future-of-research-software/&quot;&gt;Adore.software&lt;/a&gt; and reports on the progress of the Amsterdam Declaration on Funding Research Software Sustainability. To read more about this initiative and the initial workshop see &lt;a href=&quot;https://blog2.esciencecenter.nl/the-future-of-research-software-602878378c5f&quot;&gt;this blogpost&lt;/a&gt; from November 2022.&lt;/p&gt;
&lt;p&gt;We are proud to report that the second &lt;a href=&quot;https://adore.software/international-research-software-funders-workshop/&quot;&gt;International Research Software Funders Workshop&lt;/a&gt;, co-hosted by the &lt;a href=&quot;https://alliancecan.ca/en&quot;&gt;Digital Research Alliance of Canada&lt;/a&gt; (the Alliance) and the &lt;a href=&quot;https://www.researchsoft.org/&quot;&gt;Research Software Alliance&lt;/a&gt; (ReSA) from 18–20 September was a great success. People are at the heart of research software sustainability and funders can lead the way by investing in the people who develop and maintain research software. That is why the workshop theme was “Investing in People: Anticipating the Future of Research Software”. The event aimed to set the future agenda for government, philanthropic, and industry funders to support sustainable research software and communities.&lt;/p&gt;
&lt;p&gt;In total, 50 representatives from more than 35 organisations — including funders and organisations that support research software from around the globe — attended the hybrid workshop held in Montreal, Canada, and virtually. During the three-day workshop, experts explored how research software funders can facilitate capacity building through funder practices; research software platforms, infrastructure, and communities; and new initiatives. Moreover, &lt;a href=&quot;https://adore.software/2023/09/adore-software-is-ready-for-signing/&quot;&gt;Version 1.0 of the Amsterdam Declaration on Funding Research Software Sustainability (ADORE.software)&lt;/a&gt; was released and is now available for &lt;a href=&quot;https://adore.software/get-involved/&quot;&gt;signing&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background**&lt;/h2&gt;
&lt;p&gt;This second iteration of the funders workshop built on the inaugural &lt;a href=&quot;https://future-of-research-software.org/&quot;&gt;International Funders Workshop: The Future of Research Software&lt;/a&gt;, co-hosted by the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and ReSA in November 2022 in Amsterdam. During this first workshop, more than 40 funding organisations gathered to set the agenda for supporting sustainable research software and drafting of the &lt;a href=&quot;https://adore.software/declaration/&quot;&gt;ADORE.software&lt;/a&gt;. Following public consultation in 2023 and 19 organisational expressions of interest in becoming signatories,&lt;a href=&quot;https://adore.software/2023/09/adore-software-is-ready-for-signing/&quot;&gt; Version 1.0 of the Declaration was released&lt;/a&gt; in advance of the Montreal workshop and is now available for &lt;a href=&quot;https://adore.software/get-involved/&quot;&gt;signing&lt;/a&gt;. ADORE.software is the first step towards formalising, on a global level, the basic principles and recommendations related to funding the sustainability of research software, including the people needed to achieve this goal.&lt;/p&gt;
&lt;p&gt;The first workshop marked a further step in the development of the research software community. Stakeholders have continued to build on this momentum through involvement in the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt;, convened by ReSA, and its funder-led working groups. The Alliance and ReSA, together with the workshop Steering Committee, organised the 2nd International Research Software Funders Workshop to continue this important work and facilitate global collaboration among funders and other key decision makers and influencers across the research software ecosystem.&lt;/p&gt;
&lt;h2 id=&quot;2nd-international-research-software-funders-workshop&quot;&gt;&lt;strong&gt;2nd International Research Software Funders Workshop&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Pre-workshop — September 18&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The event commenced with a pre-workshop, including a session on &lt;a href=&quot;https://docs.google.com/presentation/d/1UP_UGOPxYi0R4UAE5PRpGWoJzrQ2FkVmCdDBILR6t2U/edit#slide=id.g241153165a8_0_0&quot;&gt;How to Explicitly Support Research Software as Part of Your Funding Program&lt;/a&gt;, delivered by ReSA, and a session on &lt;a href=&quot;https://zenodo.org/records/8356278&quot;&gt;CiteSoftware&lt;/a&gt;, led by a group of stakeholders aiming to drive the adoption of a common research software preservation and citation guidance resource for the research community.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Investing in people: anticipating the future of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/investing-in-people-anticipating-the-fut-708c46e1.d9EqJ9Ja_274aPE.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Photo credit: ADORE.Software&lt;/em&gt; at the International Research Software Funders Workshop&lt;em&gt;&lt;strong&gt;Workshop Day 1 — September 19&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The first day of the workshop included presentations that set the scene for participants to explore the crucial role funders play in supporting sustainable research software and communities.&lt;/p&gt;
&lt;p&gt;Carole Goble from the Software Sustainability Institute (SSI)/ELIXIR-UK/University of Manchester &lt;a href=&quot;https://docs.google.com/presentation/d/1dJrhjm7SAcLA96adZsBT-mFiJiwL3Fby/edit?usp=share_link&amp;#x26;ouid=116347134185833638908&amp;#x26;rtpof=true&amp;#x26;sd=true&quot;&gt;provided an overview&lt;/a&gt; of what research software is and why it is critical to the research endeavour. Carole highlighted that the people who make, use, and resource software are fundamental to research software sustainability. Moreover, research software needs resources and both direct (e.g., money) and indirect (e.g., community, reward, recognition, open-source support, etc.) forms of support for sustainability.&lt;/p&gt;
&lt;p&gt;Josh Greenberg from the Alfred P. Sloan Foundation delivered a &lt;a href=&quot;https://drive.google.com/file/d/1MPQ3LgO1jZdJIaF74oSz71XGye2ZjG64/view?usp=share_link&quot;&gt;keynote&lt;/a&gt; that provided a funder’s perspective. He asked attendees several pertinent questions: How much (and when) should we worry about technical debt? How much attention should we pay to user interface design in research software? Who should do which kinds of software? How central should “open source” be? How can we help institutions build capacity for research software development (and maintenance)?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Funders benefit from investing both before (community/need development) and after (ongoing maintenance and re-use) research software development.&lt;/li&gt;
&lt;li&gt;International collaboration and collective action are critical and valuable (e.g., building a multilateral funding initiative due to the global nature of research software).&lt;/li&gt;
&lt;li&gt;Funders should consider how to support and sustain Research Software Engineers (RSEs) but also incentivise researcher-developers to develop better software engineering practices.&lt;/li&gt;
&lt;li&gt;The research software community needs a set of high-level classes to measure the impact of research software, such as citations and mentions of software maturity, or combining mention analysis and dependency analysis.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Malvika Sharan from The Alan Turing Institute and Open Life Science provided a research software community perspective in her &lt;a href=&quot;https://zenodo.org/records/8361334&quot;&gt;talk&lt;/a&gt; on Exploring ‘Do No Harm’ Principles in Open Research Communities. Malvika’s compelling keynote encouraged funders to become leaders in the research software ecosystem by incentivising and recognising all types of research roles; investing in capacity-building goals that focus on bridging scientific and economic divides; and applying community-oriented frameworks to extend the benefits of research to the broader community that ‘do no harm’, thereby ensuring open science practices enable equitable research and research outcomes.&lt;/p&gt;
&lt;p&gt;During the second breakout session, participants investigated capacity building through research software platforms, infrastructure, and communities. One group explored the role of &lt;a href=&quot;https://www.researchsoft.org/blog/2023-06/&quot;&gt;Open Source Program Offices&lt;/a&gt; (OSPOs), noting that OSPOs as centres of software could ultimately help research institutions understand their software investments. Another group considered why and how to support research software communities, highlighting the need for more evidence-led recommendations and exploring the possibility of reversing the funding mechanism to fund projects after the fact, as a function of how much they were used. In discussing research software in research assessment reform, participants noted that very few research software outputs are being assessed and indicators are fragmented and field-specific. Some solutions include sharing guidance on how software is being evaluated in a single place, sharing job profiles for RSEs, and sharing existing examples of research indicators that include software. Finally, another group highlighted that the environmental impact of research software is an emerging field, and persuading researchers to think about making their code efficient is a challenge.&lt;/p&gt;
&lt;p&gt;Workshop Day 2 — September 20***&lt;/p&gt;
&lt;p&gt;The final breakout session focused on building capacity through new initiatives. Participants explored how funders can implement &lt;a href=&quot;https://www.nature.com/articles/s41597-022-01710-x&quot;&gt;FAIR for Research Software&lt;/a&gt; (FAIR4RS) in funder policy. As some funders are developing guidance, questions arose about whether funders should create guidance individually or collectively and how the community should help funders do this. Through a discussion on how funders use persistent identifiers (PIDs), the need to engage publishers around software citation has become clear. And building on the theme of software citation, participants explored how the &lt;a href=&quot;https://research-software-directory.org/&quot;&gt;Research Software Directory&lt;/a&gt;, a free open-source platform, supports software citation.&lt;/p&gt;
&lt;p&gt;For the final &lt;a href=&quot;https://drive.google.com/file/d/1tzh5cSKX-3yZpqEqzMx7XtfEM9S6jtQY/view?usp=share_link&quot;&gt;keynote&lt;/a&gt;, Jean-Baptiste Poline from McGill University provided a researcher’s perspective on the impact of funders’ investments in research software. Jean-Baptiste presented the role of research software from multiple viewpoints, offering key takeaways such as the value of building a community of researchers through collaborative projects; the need for community-endorsed standards and practices that support open and FAIR (Findable, Accessible, Interoperable, and Reusable) scientific research (e.g., &lt;a href=&quot;https://www.incf.org/&quot;&gt;INCF Network&lt;/a&gt;) to maximise research value; the importance of addressing incentives first; and the idea of funding new technologies and large labs but giving precedence to well-governed communities more than centralised projects. He recommended creating the tools needed to change culture, improving training and open practices, developing community standards, and changing incentives.&lt;/p&gt;
&lt;p&gt;The workshop culminated with a Do-a-Thon, “a short collaboration where participants from different perspectives and skill sets work together on challenges, projects, or to learn something new” (&lt;a href=&quot;https://opencon-cascadia.github.io/doathon/&quot;&gt;OpenCon Cascadia&lt;/a&gt;). Prior to the workshop, participants were invited to submit do-able ideas. During the Do-a-Thon, attendees worked in small groups on the following topics: the &lt;a href=&quot;https://kumu.io/jstarr/ossci-moss&quot;&gt;Map of Open Source Science&lt;/a&gt;; linking software to community usage; and ten things applicants should do to make it easier to assess the impact of funding programs, to build on &lt;a href=&quot;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC9671312/&quot;&gt;Ten simple rules for funding scientific open source software&lt;/a&gt; by Carly Strasser et al. This dynamic collaboration resulted in participants considering next steps, crowdsourcing tips, and determining some practical and generalisable approaches to address the challenges explored.&lt;/p&gt;
&lt;h2 id=&quot;overall-outcomes-and-how-you-can-get-involved&quot;&gt;&lt;strong&gt;Overall outcomes and how you can get involved&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The workshop solidified the importance of international collaboration to support research software. There is a widening group of funders with awareness of the need to support research software and an understanding of how to do this. The &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; has been building momentum since its inception in early 2022; its dedicated funder-led working groups are expanding their reach by engaging with other stakeholders and organisations, such as the &lt;a href=&quot;https://globalresearchcouncil.org/&quot;&gt;Global Research Council&lt;/a&gt;. Moreover, the workshop highlighted areas where coordination by funders would be beneficial, for example, in supporting the &lt;a href=&quot;https://adore.software/declaration/&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability&lt;/a&gt;. Participants also expressed an interest in exploring opportunities for forums, for example to engage publishers around software citations (along with the existing &lt;a href=&quot;https://www.researchsoft.org/taskforces/&quot;&gt;ReSA Task Force on Code Availability&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;We thank all the participants for their engagement during the workshop sessions. We’re grateful to the workshop Steering Committee for their efforts in organising a successful hybrid workshop. A full report, written and edited collectively by workshop participants, is forthcoming.&lt;/p&gt;
&lt;p&gt;To stay up to date on ADORE.software, visit &lt;a href=&quot;http://www.adore.software/&quot;&gt;www.adore.software&lt;/a&gt;. If you want to show your support for the Declaration, you can become a &lt;a href=&quot;https://adore.software/sign/&quot;&gt;signatory&lt;/a&gt; (for funders) or &lt;a href=&quot;https://adore.software/support/&quot;&gt;supporter&lt;/a&gt; (for non-funders) and help share the &lt;a href=&quot;https://adore.software/2023/09/adore-software-is-ready-for-signing/&quot;&gt;news&lt;/a&gt;. To receive updates on news related to the Declaration and future activities, subscribe to the &lt;a href=&quot;https://landing.mailerlite.com/webforms/landing/i5e1h2&quot;&gt;ReSA newsletter&lt;/a&gt;. Funders are invited to join the (free) &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; by contacting ReSA at &lt;a href=&quot;mailto:info@researchsoft.org&quot;&gt;info@researchsoft.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you’re interested in learning more about ReSA and its activities, join our next &lt;a href=&quot;https://www.researchsoft.org/events/2022-06/&quot;&gt;Research Software Community Leaders Forum&lt;/a&gt; on 15 November at 20:00 UTC. ReSA’s Community Leaders Forum is open to all, and you can &lt;a href=&quot;https://landing.mailerlite.com/webforms/landing/o1n4v3&quot;&gt;sign up&lt;/a&gt; for calendar invites.&lt;/p&gt;
&lt;p&gt;We would like to express our sincere gratitude to our community, Founding Members, and Organisational Members — without whom none of this work would have been possible.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This project has also been made possible in part by grant 2021–000000 from the &lt;em&gt;&lt;a href=&quot;https://chanzuckerberg.com/&quot;&gt;&lt;em&gt;Chan Zuckerberg Initiative DAF&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, an advised fund of the Silicon Valley Community Foundation; and the &lt;em&gt;&lt;a href=&quot;https://sloan.org/&quot;&gt;&lt;em&gt;Alfred P. Sloan Foundation&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/investing-in-people-anticipating-the-fut-708c46e1.d9EqJ9Ja.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>The Orange3 data mining platform for the Social Sciences and Humanities</title><link>https://blog2.esciencecenter.nl/posts/2023-11-02---the-orange3-data-mining-platform-for-the-social-sciences-and</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-11-02---the-orange3-data-mining-platform-for-the-social-sciences-and</guid><description>&lt;h1 id=&quot;the-orange3-data-mining-platform-for-the-social-sciences-and-humanities&quot;&gt;&lt;em&gt;The Orange3 data mining platform for the Social Sciences and Humanities&lt;/em&gt;&lt;/h1&gt;
&lt;h2 id=&quot;why-arent-more-ssh-researchers-using-and-extending-the-platform&quot;&gt;Why aren’t more SSH researchers using and extending the platform?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://orangedatamining.com/&quot;&gt;Orange&lt;/a&gt; is an open-source &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;-based &lt;a href=&quot;https://www.britannica.com/technology/data-structure&quot;&gt;data mining&lt;/a&gt; application with a graphical user interface (GUI). It allows people with no knowledge of programming to apply Machine Learning as well as advanced data processing, analysis, and visualization using a point-and-click, drag-and-drop interface. Those who have seen &lt;a href=&quot;https://scratch.mit.edu/&quot;&gt;Scratch&lt;/a&gt; will be familiar with this mode of interaction, although Orange is more advanced and is used for data mining, rather than educational programming. The following screenshot shows what a typical Orange &lt;a href=&quot;https://orangedatamining.com/workflows/&quot;&gt;workflow&lt;/a&gt; looks like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;396&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-9fc38229.CnwyeOCH_ZuG0x0.webp&quot; srcset=&quot;&quot;&gt;
Screenshot of an example data mining workflow in Orange3The three small circles labeled ‘File’, ‘Data Table’, and ‘Scatter Plot’ in the image above, are called Orange &lt;a href=&quot;https://docs.biolab.si/orange/2/widgets/rst/index.html&quot;&gt;widgets&lt;/a&gt;. They are the basic building blocks of a data analysis workflow (or pipeline) in Orange. Each widget is a software unit that performs some sort of data processing, analysis, or visualization and potentially has a set of inputs and outputs. You can connect the outputs of some widgets to the inputs of others to create a chain of processing and analysis operations. A great feature of Orange is its extensibility. There are loads of custom plugins for Orange (called &lt;em&gt;add-ons&lt;/em&gt;) developed by researchers and the Orange user community. Add-ons usually comprise multiple widgets. Two mature and extensively used Orange add-ons are &lt;a href=&quot;https://orange3-text.readthedocs.io/en/latest/&quot;&gt;Orange-Text&lt;/a&gt; and &lt;a href=&quot;https://orange3-network.readthedocs.io/en/latest/&quot;&gt;Network&lt;/a&gt; which are used for &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_theory&quot;&gt;network analysis &lt;/a&gt;respectively.&lt;/p&gt;
&lt;p&gt;Story Navigator: a custom Orange add-on I am developing**&lt;/p&gt;
&lt;p&gt;I am currently in the process of developing an add-on as part of a project with researchers at the &lt;a href=&quot;https://www.utwente.nl/&quot;&gt;University of Twente&lt;/a&gt; in the Netherlands. The add-on is called the &lt;a href=&quot;https://github.com/navigating-stories/orange-story-navigator&quot;&gt;Story Navigator&lt;/a&gt;. The aim of the Story Navigator is to enable computer-aided analysis of written stories for students and researchers who study &lt;a href=&quot;https://en.wikipedia.org/wiki/Narrative_psychology&quot;&gt;narrative psychology&lt;/a&gt;. The add-on has several widgets to analyse different aspects of a story. It uses a combination of &lt;a href=&quot;https://encyclopediaofmath.org/wiki/Natural_language_processing&quot;&gt;natural language processing&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt;, and general data analysis techniques to implement theories in narrative psychology, such as &lt;a href=&quot;https://natureofwriting.com/courses/introduction-to-rhetoric/lessons/burkes-pentad/&quot;&gt;Burke’s pentad&lt;/a&gt;. Here’s a screen:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;348&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-4f3fee29.BjVBybBx_ZxVMsq.webp&quot; srcset=&quot;&quot;&gt;
Screenshot of the Story Navigator add-on (not yet released) for Orange3.The add-on works by first importing textual stories into the workflow using the existing &lt;a href=&quot;https://orangedatamining.com/widget-catalog/text-mining/importdocuments/&quot;&gt;“Import Documents”&lt;/a&gt; widget from the Orange-Text add-on. Thereafter the researcher can choose a widget from the add-on for analysing some aspects of the imported stories. The actor analysis widget, for example, highlights potential characters in the stories; shows which kinds of actions (verbs) the characters are associated with; and calculates different measures for how central specific characters are to the stories.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;422&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-7e54b23a.GDy6a0Pm_ZtLkmE.webp&quot; srcset=&quot;&quot;&gt;
Quantitative story analysis widgets from the Story Navigator add-on for Orange3.While it did take some time to develop the widgets for this add-on, what surprised me is that it took me only about two hours, from scratch, with no prior knowledge of Orange, to develop my first widget that showed up in the Orange3 interface when I started it up. Granted, the widget did not do anything except display. But the return on my two-hour investment was that I could now free up my creativity to develop whatever functionality I wanted in the widget, without having to create my own GUI. In doing so, I got to take advantage of a myriad of benefits including being able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make my add-on available for anyone to use regardless of their programming knowledge&lt;/li&gt;
&lt;li&gt;Receive development and usage feedback from an existing Orange community about my add-on (without having to further promote the add-on or build another community myself from scratch)&lt;/li&gt;
&lt;li&gt;Demo my plugin to anyone, thanks to the GUI&lt;/li&gt;
&lt;li&gt;Share data analyses made with my add-on with other Orange users — enabling reproducibility (currently &lt;a href=&quot;https://www.nature.com/articles/d41586-019-00067-3&quot;&gt;undergoing a crisis&lt;/a&gt; in science)&lt;/li&gt;
&lt;li&gt;Forget about writing installation instructions — they’re already &lt;a href=&quot;https://orangedatamining.com/blog/2012/11/30/the-easy-way-to-install-add-ons/&quot;&gt;here&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite what some readers might think at this point, I am not an Orange evangelist. In fact, I am not swooning over the capabilities and potential of Orange specifically. Orange does have competing platforms that try to do similar things such as &lt;a href=&quot;https://www.knime.com/&quot;&gt;KNIME&lt;/a&gt; and &lt;a href=&quot;https://www.cs.waikato.ac.nz/ml/weka/&quot;&gt;WEKA&lt;/a&gt; which are both &lt;a href=&quot;https://www.java.com/en/&quot;&gt;Java&lt;/a&gt;-based and therefore inherit some concerns due to &lt;a href=&quot;https://www.tiobe.com/tiobe-index/&quot;&gt;Java’s declining popularity&lt;/a&gt;. Orange itself also has some clear disadvantages, not least of which are the &lt;a href=&quot;https://orangedatamining.com/blog/2012/01/03/parallel-orange/&quot;&gt;scalability issues&lt;/a&gt; and the &lt;a href=&quot;https://orange3-example-addon.readthedocs.io/en/latest/&quot;&gt;add-on development documentation&lt;/a&gt; (the latter is not very accessible for less experienced developers).&lt;/p&gt;
&lt;p&gt;But the point I am trying to make is that I am mostly just inspired by the philosophy behind platforms like these: people coming together to develop and share an extensible “workbench-style” software platform with a user-friendly interface. When I refer to software I don’t mean software that has a highly niche purpose, but software that aims to be an ever-evolving toolbox with the potential to address a multitude of research problems. Where your own creativity is the only limit in terms of contributing to it. Where the knowledge barriers to be able to contribute to it are super low, and where there are no qualifying criteria for those who can experience and benefit from the contributions.&lt;/p&gt;
&lt;p&gt;Orange was developed at the &lt;a href=&quot;https://fri.uni-lj.si/en/laboratory/biolab&quot;&gt;Laboratory for Bioinformatics&lt;/a&gt; at the University of Ljubljana. It makes sense then that most of its user base uses it for data mining in &lt;a href=&quot;https://www.britannica.com/science/bioinformatics&quot;&gt;bioinformatics&lt;/a&gt; (see for instance &lt;a href=&quot;https://www.mdpi.com/2076-3417/11/5/2218&quot;&gt;this study&lt;/a&gt; using Orange for early diagnosis of diabetes). But Orange itself is not at all designed to be domain-specific. Its add-ons and widgets are designed for domain-agnostic data mining (&lt;a href=&quot;https://www.mdpi.com/2076-3417/10/11/3894&quot;&gt;here’s a study&lt;/a&gt; using Orange to predict student performance in higher education). This begs the question, why aren’t more researchers in the Social Sciences and Humanities using it, extending it, or building similar platforms?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bethesda.net/dashboard&quot;&gt;Bethesda Softworks&lt;/a&gt; is a US-based video game development company that is famous for its many franchises, one of which is “&lt;a href=&quot;https://elderscrolls.bethesda.net/en/&quot;&gt;Elder Scrolls&lt;/a&gt;”. The games in this franchise are “&lt;a href=&quot;https://en.wikipedia.org/wiki/Role-playing_game&quot;&gt;RPGs&lt;/a&gt;” that put the player in control of a character from a fictional fantasy world with the goal to… wait for it… save the world from destruction (if you’re new to the term RPGs imagine a video game based on &lt;a href=&quot;https://www.hbo.com/game-of-thrones&quot;&gt;Game of Thrones&lt;/a&gt; and you’ll get the gist). In 2002, Bethesda released its third installment of Elder Scrolls, called “&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Elder_Scrolls_III:_Morrowind&quot;&gt;Morrowind&lt;/a&gt;”. The super interesting part is that they also released software called the &lt;a href=&quot;https://cs.elderscrolls.com/index.php?title=Main_Page&quot;&gt;Elder Scrolls Construction Set&lt;/a&gt; alongside the game. This software allowed players to make customizations to their own copy of the game. They could do things such as create new clothing, buildings, and other items; create their own character voices; make new quests, and customize the color of the sky. These modifications (mods *as they are now commonly referred to) vary in terms of how much software literacy is required in order to build them, but many of them require no more knowledge than being able to install a program and click a few buttons.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;367&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-8e688f2b.2Iv0nc2J_1lSNPy.webp&quot; srcset=&quot;&quot;&gt;
Fancy introducing Spiderman-suited creatures crawling around a medieval town into your video-gaming experience? Well, someone &lt;a href=&quot;https://www.nexusmods.com/skyrim/mods/4308&quot;&gt;has already created a mod for this&lt;/a&gt; in &lt;a href=&quot;https://elderscrolls.bethesda.net/en/skyrim&quot;&gt;Skyrim&lt;/a&gt;.Twenty years later, and Bethesda has become known and celebrated for giving its customers the freedom to customize their gaming experience. &lt;a href=&quot;https://www.nexusmods.com/&quot;&gt;Nexusmods&lt;/a&gt; is one of the prominent hubs for hosting large collections of player-created mods for games by Bethesda and other major video game companies. I quote some jaw-dropping statistics from this site here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“We host 477,145 mods for 2,342 games from 118,005 authors serving 41,902,274 members with 8,184,840,124 downloads to date.”&lt;/p&gt;
&lt;p&gt;In academia, terms like “outputs”, “impact”, “community building” and “community engagement” are often bandied about as performance goals and metrics for work. However, despite their purported importance, these terms are hard to define and measure. But when I look at those numbers, I feel like we don’t need unambiguous definitions for those terms in order to verify that the mod concept ticks all those boxes and then some.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;254&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-caf3ed3a.-Gb9CStu_M5Dvq.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://www.nexusmods.com/&quot;&gt;Nexusmods&lt;/a&gt; demonstrates that the mod concept is a winner.“Okay Kody, what does this all have to do with Orange?”, you may ask. Well, in some ways there are parallels in this story to the concept of Orange as a software platform.&lt;/p&gt;
&lt;p&gt;First, there is a &lt;em&gt;product that many people enjoy&lt;/em&gt; (or find useful). In Bethesda’s case, it is the “vanilla” Elder Scrolls games. In Orange’s case, it is a data mining platform which is a generic tool that is useful regardless of the research domain and data. The GUI aspect of Orange also opens it up to a much larger user base (not just a small group of researchers with development experience working in a niche field).&lt;/p&gt;
&lt;p&gt;Second, there is the *enabling of customization. *In Bethesda’s case, it is the provision of customization software such as the &lt;a href=&quot;https://store.steampowered.com/app/1946180/Skyrim_Special_Edition_Creation_Kit/&quot;&gt;Skyrim Creation Kit&lt;/a&gt;; in the case of Orange, it is the release of the code under an open-source license with reusable example code and plugin-writing tutorials.&lt;/p&gt;
&lt;p&gt;Thirdly, and what I find to be the most critical, is *making it easy to customize. *In Bethesda’s case, they have made user-friendly software that does not require extremely specialized skills to use. Almost anyone can create a mod. In Orange’s case, you still need to know how to program to develop add-ons. But you don’t need advanced knowledge of the GUI frameworks that Orange uses — &lt;a href=&quot;https://en.wikipedia.org/wiki/Qt_(software)&quot;&gt;Qt&lt;/a&gt; and &lt;a href=&quot;https://wiki.python.org/moin/PyQt&quot;&gt;PyQt&lt;/a&gt;. In other words, if you know how to create any kind of computational script or software in Python, you can easily create an Orange widget to “house” or “wrap” its functionality. Furthermore, others, regardless of their technical nous, will be able to use it and “chain” your widget with other software in an Orange workflow.&lt;/p&gt;
&lt;p&gt;What I have experienced and want to emphasize, is that plugging your software into existing platforms like Orange (especially ones that have a nice GUI) can increase its visibility and usage, over publishing it solely in a code repository. Decently designed GUIs help users to more quickly understand what your software does which goes a long way to maximizing its value. Platforms like Orange provide a mechanism by which developers can take advantage of these GUI benefits “for free” (well, not really for free, but with &lt;em&gt;much&lt;/em&gt; less time investment than building and designing GUIs from scratch). It frees them up to use their creativity to solve research problems through widget development; it exposes their software to a much wider audience; and it allows users to interact with their software in a more intuitive way.&lt;/p&gt;
&lt;p&gt;In short, platforms like Orange can be extremely useful both for researchers who want to quickly apply computational analyses in the SSH fields (without writing code) and for developers who want to increase the usability, visibility, and sustainability of their software. While it does, to some extent, tie the success of your software to the success of Orange, you are not “putting all your eggs in one basket”. Due to the modularity and already-in-place Python package structure of Orange add-ons and widgets, you can very easily strip the GUI out of your code and release your work as a stand-alone package, or migrate it to another platform.&lt;/p&gt;
&lt;p&gt;If you are interested, my colleague &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-ji-qi/&quot;&gt;Ji Qi&lt;/a&gt; has written a &lt;a href=&quot;https://medium.com/escience-center/how-easy-it-can-be-to-whip-up-your-own-orange3-widget-a-chatbot-adventure-with-huggingchat-ded982ac0ef4&quot;&gt;post&lt;/a&gt; about how to get started with Orange add-on development — be sure to check it out!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take home messages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Orange is an open-source extensible data mining platform that is usable by people with little to no technical experience. If you are a researcher in SSH consider using it for your research. If it doesn’t have a feature you need, &lt;a href=&quot;https://github.com/biolab/orange3/issues&quot;&gt;ask the developers if they can add it as a default feature to Orange&lt;/a&gt;. If they can’t add it, and if you or a colleague has Python experience, consider &lt;a href=&quot;http://jiblogpost&quot;&gt;creating a custom add-on&lt;/a&gt;. It is surprisingly quick and easy to create one if you know a bit of Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1903.06039.pdf&quot;&gt;Research software sustainability is a challenge&lt;/a&gt;. Building and maintaining communities around the development of research software is hard. Don’t let your software become JAG (&lt;strong&gt;J&lt;/strong&gt;ust-&lt;strong&gt;A&lt;/strong&gt;nother-&lt;strong&gt;G&lt;/strong&gt;ithub repo). Take inspiration for how to avoid this from platforms like Orange. This does not mean that you need to create a graphical user interface for your software. It means: &lt;em&gt;find a home for your software&lt;/em&gt; or &lt;em&gt;find an existing toolbox in which to integrate your software, before creating your own toolbox&lt;/em&gt;. Integrating into existing platforms or packages will probably increase its usage and visibility over publishing as a stand-alone item.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #1:&lt;/strong&gt; From the start, consider building software that solves &lt;em&gt;generic&lt;/em&gt; problems in your field. i.e., problems that are shared by others in the field as well, rather than for highly specialized use cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #2:&lt;/strong&gt; Make your software easy to use by as many &lt;em&gt;types&lt;/em&gt; of people as possible. Not just for experienced developers. Also, ensure that someone can rapidly understand what your software does.&lt;/li&gt;
&lt;li&gt;**Inspiration point #3: **Make it easy for as many people as possible to customize and extend your software.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 02 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;the-orange3-data-mining-platform-for-the-social-sciences-and-humanities&quot;&gt;&lt;em&gt;The Orange3 data mining platform for the Social Sciences and Humanities&lt;/em&gt;&lt;/h1&gt;
&lt;h2 id=&quot;why-arent-more-ssh-researchers-using-and-extending-the-platform&quot;&gt;Why aren’t more SSH researchers using and extending the platform?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://orangedatamining.com/&quot;&gt;Orange&lt;/a&gt; is an open-source &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;-based &lt;a href=&quot;https://www.britannica.com/technology/data-structure&quot;&gt;data mining&lt;/a&gt; application with a graphical user interface (GUI). It allows people with no knowledge of programming to apply Machine Learning as well as advanced data processing, analysis, and visualization using a point-and-click, drag-and-drop interface. Those who have seen &lt;a href=&quot;https://scratch.mit.edu/&quot;&gt;Scratch&lt;/a&gt; will be familiar with this mode of interaction, although Orange is more advanced and is used for data mining, rather than educational programming. The following screenshot shows what a typical Orange &lt;a href=&quot;https://orangedatamining.com/workflows/&quot;&gt;workflow&lt;/a&gt; looks like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;396&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-9fc38229.CnwyeOCH_ZuG0x0.webp&quot; srcset=&quot;&quot;&gt;
Screenshot of an example data mining workflow in Orange3The three small circles labeled ‘File’, ‘Data Table’, and ‘Scatter Plot’ in the image above, are called Orange &lt;a href=&quot;https://docs.biolab.si/orange/2/widgets/rst/index.html&quot;&gt;widgets&lt;/a&gt;. They are the basic building blocks of a data analysis workflow (or pipeline) in Orange. Each widget is a software unit that performs some sort of data processing, analysis, or visualization and potentially has a set of inputs and outputs. You can connect the outputs of some widgets to the inputs of others to create a chain of processing and analysis operations. A great feature of Orange is its extensibility. There are loads of custom plugins for Orange (called &lt;em&gt;add-ons&lt;/em&gt;) developed by researchers and the Orange user community. Add-ons usually comprise multiple widgets. Two mature and extensively used Orange add-ons are &lt;a href=&quot;https://orange3-text.readthedocs.io/en/latest/&quot;&gt;Orange-Text&lt;/a&gt; and &lt;a href=&quot;https://orange3-network.readthedocs.io/en/latest/&quot;&gt;Network&lt;/a&gt; which are used for &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_theory&quot;&gt;network analysis &lt;/a&gt;respectively.&lt;/p&gt;
&lt;p&gt;Story Navigator: a custom Orange add-on I am developing**&lt;/p&gt;
&lt;p&gt;I am currently in the process of developing an add-on as part of a project with researchers at the &lt;a href=&quot;https://www.utwente.nl/&quot;&gt;University of Twente&lt;/a&gt; in the Netherlands. The add-on is called the &lt;a href=&quot;https://github.com/navigating-stories/orange-story-navigator&quot;&gt;Story Navigator&lt;/a&gt;. The aim of the Story Navigator is to enable computer-aided analysis of written stories for students and researchers who study &lt;a href=&quot;https://en.wikipedia.org/wiki/Narrative_psychology&quot;&gt;narrative psychology&lt;/a&gt;. The add-on has several widgets to analyse different aspects of a story. It uses a combination of &lt;a href=&quot;https://encyclopediaofmath.org/wiki/Natural_language_processing&quot;&gt;natural language processing&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt;, and general data analysis techniques to implement theories in narrative psychology, such as &lt;a href=&quot;https://natureofwriting.com/courses/introduction-to-rhetoric/lessons/burkes-pentad/&quot;&gt;Burke’s pentad&lt;/a&gt;. Here’s a screen:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;348&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-4f3fee29.BjVBybBx_ZxVMsq.webp&quot; srcset=&quot;&quot;&gt;
Screenshot of the Story Navigator add-on (not yet released) for Orange3.The add-on works by first importing textual stories into the workflow using the existing &lt;a href=&quot;https://orangedatamining.com/widget-catalog/text-mining/importdocuments/&quot;&gt;“Import Documents”&lt;/a&gt; widget from the Orange-Text add-on. Thereafter the researcher can choose a widget from the add-on for analysing some aspects of the imported stories. The actor analysis widget, for example, highlights potential characters in the stories; shows which kinds of actions (verbs) the characters are associated with; and calculates different measures for how central specific characters are to the stories.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;422&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-7e54b23a.GDy6a0Pm_ZtLkmE.webp&quot; srcset=&quot;&quot;&gt;
Quantitative story analysis widgets from the Story Navigator add-on for Orange3.While it did take some time to develop the widgets for this add-on, what surprised me is that it took me only about two hours, from scratch, with no prior knowledge of Orange, to develop my first widget that showed up in the Orange3 interface when I started it up. Granted, the widget did not do anything except display. But the return on my two-hour investment was that I could now free up my creativity to develop whatever functionality I wanted in the widget, without having to create my own GUI. In doing so, I got to take advantage of a myriad of benefits including being able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make my add-on available for anyone to use regardless of their programming knowledge&lt;/li&gt;
&lt;li&gt;Receive development and usage feedback from an existing Orange community about my add-on (without having to further promote the add-on or build another community myself from scratch)&lt;/li&gt;
&lt;li&gt;Demo my plugin to anyone, thanks to the GUI&lt;/li&gt;
&lt;li&gt;Share data analyses made with my add-on with other Orange users — enabling reproducibility (currently &lt;a href=&quot;https://www.nature.com/articles/d41586-019-00067-3&quot;&gt;undergoing a crisis&lt;/a&gt; in science)&lt;/li&gt;
&lt;li&gt;Forget about writing installation instructions — they’re already &lt;a href=&quot;https://orangedatamining.com/blog/2012/11/30/the-easy-way-to-install-add-ons/&quot;&gt;here&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite what some readers might think at this point, I am not an Orange evangelist. In fact, I am not swooning over the capabilities and potential of Orange specifically. Orange does have competing platforms that try to do similar things such as &lt;a href=&quot;https://www.knime.com/&quot;&gt;KNIME&lt;/a&gt; and &lt;a href=&quot;https://www.cs.waikato.ac.nz/ml/weka/&quot;&gt;WEKA&lt;/a&gt; which are both &lt;a href=&quot;https://www.java.com/en/&quot;&gt;Java&lt;/a&gt;-based and therefore inherit some concerns due to &lt;a href=&quot;https://www.tiobe.com/tiobe-index/&quot;&gt;Java’s declining popularity&lt;/a&gt;. Orange itself also has some clear disadvantages, not least of which are the &lt;a href=&quot;https://orangedatamining.com/blog/2012/01/03/parallel-orange/&quot;&gt;scalability issues&lt;/a&gt; and the &lt;a href=&quot;https://orange3-example-addon.readthedocs.io/en/latest/&quot;&gt;add-on development documentation&lt;/a&gt; (the latter is not very accessible for less experienced developers).&lt;/p&gt;
&lt;p&gt;But the point I am trying to make is that I am mostly just inspired by the philosophy behind platforms like these: people coming together to develop and share an extensible “workbench-style” software platform with a user-friendly interface. When I refer to software I don’t mean software that has a highly niche purpose, but software that aims to be an ever-evolving toolbox with the potential to address a multitude of research problems. Where your own creativity is the only limit in terms of contributing to it. Where the knowledge barriers to be able to contribute to it are super low, and where there are no qualifying criteria for those who can experience and benefit from the contributions.&lt;/p&gt;
&lt;p&gt;Orange was developed at the &lt;a href=&quot;https://fri.uni-lj.si/en/laboratory/biolab&quot;&gt;Laboratory for Bioinformatics&lt;/a&gt; at the University of Ljubljana. It makes sense then that most of its user base uses it for data mining in &lt;a href=&quot;https://www.britannica.com/science/bioinformatics&quot;&gt;bioinformatics&lt;/a&gt; (see for instance &lt;a href=&quot;https://www.mdpi.com/2076-3417/11/5/2218&quot;&gt;this study&lt;/a&gt; using Orange for early diagnosis of diabetes). But Orange itself is not at all designed to be domain-specific. Its add-ons and widgets are designed for domain-agnostic data mining (&lt;a href=&quot;https://www.mdpi.com/2076-3417/10/11/3894&quot;&gt;here’s a study&lt;/a&gt; using Orange to predict student performance in higher education). This begs the question, why aren’t more researchers in the Social Sciences and Humanities using it, extending it, or building similar platforms?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bethesda.net/dashboard&quot;&gt;Bethesda Softworks&lt;/a&gt; is a US-based video game development company that is famous for its many franchises, one of which is “&lt;a href=&quot;https://elderscrolls.bethesda.net/en/&quot;&gt;Elder Scrolls&lt;/a&gt;”. The games in this franchise are “&lt;a href=&quot;https://en.wikipedia.org/wiki/Role-playing_game&quot;&gt;RPGs&lt;/a&gt;” that put the player in control of a character from a fictional fantasy world with the goal to… wait for it… save the world from destruction (if you’re new to the term RPGs imagine a video game based on &lt;a href=&quot;https://www.hbo.com/game-of-thrones&quot;&gt;Game of Thrones&lt;/a&gt; and you’ll get the gist). In 2002, Bethesda released its third installment of Elder Scrolls, called “&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Elder_Scrolls_III:_Morrowind&quot;&gt;Morrowind&lt;/a&gt;”. The super interesting part is that they also released software called the &lt;a href=&quot;https://cs.elderscrolls.com/index.php?title=Main_Page&quot;&gt;Elder Scrolls Construction Set&lt;/a&gt; alongside the game. This software allowed players to make customizations to their own copy of the game. They could do things such as create new clothing, buildings, and other items; create their own character voices; make new quests, and customize the color of the sky. These modifications (mods *as they are now commonly referred to) vary in terms of how much software literacy is required in order to build them, but many of them require no more knowledge than being able to install a program and click a few buttons.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;367&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-8e688f2b.2Iv0nc2J_1lSNPy.webp&quot; srcset=&quot;&quot;&gt;
Fancy introducing Spiderman-suited creatures crawling around a medieval town into your video-gaming experience? Well, someone &lt;a href=&quot;https://www.nexusmods.com/skyrim/mods/4308&quot;&gt;has already created a mod for this&lt;/a&gt; in &lt;a href=&quot;https://elderscrolls.bethesda.net/en/skyrim&quot;&gt;Skyrim&lt;/a&gt;.Twenty years later, and Bethesda has become known and celebrated for giving its customers the freedom to customize their gaming experience. &lt;a href=&quot;https://www.nexusmods.com/&quot;&gt;Nexusmods&lt;/a&gt; is one of the prominent hubs for hosting large collections of player-created mods for games by Bethesda and other major video game companies. I quote some jaw-dropping statistics from this site here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“We host 477,145 mods for 2,342 games from 118,005 authors serving 41,902,274 members with 8,184,840,124 downloads to date.”&lt;/p&gt;
&lt;p&gt;In academia, terms like “outputs”, “impact”, “community building” and “community engagement” are often bandied about as performance goals and metrics for work. However, despite their purported importance, these terms are hard to define and measure. But when I look at those numbers, I feel like we don’t need unambiguous definitions for those terms in order to verify that the mod concept ticks all those boxes and then some.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The Orange3 data mining platform for the Social Sciences and Humanities&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;254&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-caf3ed3a.-Gb9CStu_M5Dvq.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://www.nexusmods.com/&quot;&gt;Nexusmods&lt;/a&gt; demonstrates that the mod concept is a winner.“Okay Kody, what does this all have to do with Orange?”, you may ask. Well, in some ways there are parallels in this story to the concept of Orange as a software platform.&lt;/p&gt;
&lt;p&gt;First, there is a &lt;em&gt;product that many people enjoy&lt;/em&gt; (or find useful). In Bethesda’s case, it is the “vanilla” Elder Scrolls games. In Orange’s case, it is a data mining platform which is a generic tool that is useful regardless of the research domain and data. The GUI aspect of Orange also opens it up to a much larger user base (not just a small group of researchers with development experience working in a niche field).&lt;/p&gt;
&lt;p&gt;Second, there is the *enabling of customization. *In Bethesda’s case, it is the provision of customization software such as the &lt;a href=&quot;https://store.steampowered.com/app/1946180/Skyrim_Special_Edition_Creation_Kit/&quot;&gt;Skyrim Creation Kit&lt;/a&gt;; in the case of Orange, it is the release of the code under an open-source license with reusable example code and plugin-writing tutorials.&lt;/p&gt;
&lt;p&gt;Thirdly, and what I find to be the most critical, is *making it easy to customize. *In Bethesda’s case, they have made user-friendly software that does not require extremely specialized skills to use. Almost anyone can create a mod. In Orange’s case, you still need to know how to program to develop add-ons. But you don’t need advanced knowledge of the GUI frameworks that Orange uses — &lt;a href=&quot;https://en.wikipedia.org/wiki/Qt_(software)&quot;&gt;Qt&lt;/a&gt; and &lt;a href=&quot;https://wiki.python.org/moin/PyQt&quot;&gt;PyQt&lt;/a&gt;. In other words, if you know how to create any kind of computational script or software in Python, you can easily create an Orange widget to “house” or “wrap” its functionality. Furthermore, others, regardless of their technical nous, will be able to use it and “chain” your widget with other software in an Orange workflow.&lt;/p&gt;
&lt;p&gt;What I have experienced and want to emphasize, is that plugging your software into existing platforms like Orange (especially ones that have a nice GUI) can increase its visibility and usage, over publishing it solely in a code repository. Decently designed GUIs help users to more quickly understand what your software does which goes a long way to maximizing its value. Platforms like Orange provide a mechanism by which developers can take advantage of these GUI benefits “for free” (well, not really for free, but with &lt;em&gt;much&lt;/em&gt; less time investment than building and designing GUIs from scratch). It frees them up to use their creativity to solve research problems through widget development; it exposes their software to a much wider audience; and it allows users to interact with their software in a more intuitive way.&lt;/p&gt;
&lt;p&gt;In short, platforms like Orange can be extremely useful both for researchers who want to quickly apply computational analyses in the SSH fields (without writing code) and for developers who want to increase the usability, visibility, and sustainability of their software. While it does, to some extent, tie the success of your software to the success of Orange, you are not “putting all your eggs in one basket”. Due to the modularity and already-in-place Python package structure of Orange add-ons and widgets, you can very easily strip the GUI out of your code and release your work as a stand-alone package, or migrate it to another platform.&lt;/p&gt;
&lt;p&gt;If you are interested, my colleague &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-ji-qi/&quot;&gt;Ji Qi&lt;/a&gt; has written a &lt;a href=&quot;https://medium.com/escience-center/how-easy-it-can-be-to-whip-up-your-own-orange3-widget-a-chatbot-adventure-with-huggingchat-ded982ac0ef4&quot;&gt;post&lt;/a&gt; about how to get started with Orange add-on development — be sure to check it out!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take home messages&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Orange is an open-source extensible data mining platform that is usable by people with little to no technical experience. If you are a researcher in SSH consider using it for your research. If it doesn’t have a feature you need, &lt;a href=&quot;https://github.com/biolab/orange3/issues&quot;&gt;ask the developers if they can add it as a default feature to Orange&lt;/a&gt;. If they can’t add it, and if you or a colleague has Python experience, consider &lt;a href=&quot;http://jiblogpost&quot;&gt;creating a custom add-on&lt;/a&gt;. It is surprisingly quick and easy to create one if you know a bit of Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1903.06039.pdf&quot;&gt;Research software sustainability is a challenge&lt;/a&gt;. Building and maintaining communities around the development of research software is hard. Don’t let your software become JAG (&lt;strong&gt;J&lt;/strong&gt;ust-&lt;strong&gt;A&lt;/strong&gt;nother-&lt;strong&gt;G&lt;/strong&gt;ithub repo). Take inspiration for how to avoid this from platforms like Orange. This does not mean that you need to create a graphical user interface for your software. It means: &lt;em&gt;find a home for your software&lt;/em&gt; or &lt;em&gt;find an existing toolbox in which to integrate your software, before creating your own toolbox&lt;/em&gt;. Integrating into existing platforms or packages will probably increase its usage and visibility over publishing as a stand-alone item.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #1:&lt;/strong&gt; From the start, consider building software that solves &lt;em&gt;generic&lt;/em&gt; problems in your field. i.e., problems that are shared by others in the field as well, rather than for highly specialized use cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #2:&lt;/strong&gt; Make your software easy to use by as many &lt;em&gt;types&lt;/em&gt; of people as possible. Not just for experienced developers. Also, ensure that someone can rapidly understand what your software does.&lt;/li&gt;
&lt;li&gt;**Inspiration point #3: **Make it easy for as many people as possible to customize and extend your software.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/the-orange3-data-mining-platform-for-the-9fc38229.CnwyeOCH.png" medium="image"/><author>Kody Moodley</author></item><item><title>Open Science Festival: What infrastructures do we need to preserve research software?</title><link>https://blog2.esciencecenter.nl/posts/2023-10-26---open-science-festival-what-infrastructures-do-we-need-to-pre</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-10-26---open-science-festival-what-infrastructures-do-we-need-to-pre</guid><description>&lt;p&gt;*written by &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-luisa-orozco/&quot;&gt;&lt;em&gt;Luisa Orozco&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;http://www.linkedin.com/in/danielagawehns/&quot;&gt;&lt;em&gt;Daniela Gawehns&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and *&lt;a href=&quot;https://medium.com/@c.martinez&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Open Science Festival: What infrastructures do we need to preserve research software?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/open-science-festival-what-infrastructur-9069ad56.Bg1b7T0q_biUgK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Earlier this year, the 2023 edition of the Dutch &lt;a href=&quot;https://opensciencefestival.nl/&quot;&gt;Open Science Festival&lt;/a&gt; was held. We (the eScience Center and Leiden University) organised the session “National infrastructure for sustainable research software”. In this session we discussed the benefits and limits of available software preservation platforms (or infrastructures) and if national infrastructures for research software development are feasible and desirable.&lt;/p&gt;
&lt;p&gt;Research software increasingly forms a critically important element of many research projects across a wide array of domains. To achieve truly sustainable and reproducible research, not only the software itself but also the computational environment it depends on needs to be preserved. Different types of infrastructure are required to support these preservation activities.&lt;/p&gt;
&lt;p&gt;One user-friendly example of a friendly way to package computational environmetns are Docker containers. These containers can be archived on privately owned platforms like Docker Hub and GitHub or on publicly funded archives such as Zenodo. Such platforms become part of the infrastructure needed to rerun and reuse research code associated with research results.&lt;/p&gt;
&lt;h2 id=&quot;panel-composition-and-pitches&quot;&gt;Panel composition and pitches&lt;/h2&gt;
&lt;p&gt;The session was organised as a series of panel pitches, followed by a group discussion. The panel shared their insights and experiences, as we explored current issues with container storage platforms and related infrastructure and the role the Dutch research landscape can take as a provider of independent and government funded infrastructure for sustainable research software.&lt;/p&gt;
&lt;p&gt;The panel was composed of national and international experts from different domains and backgrounds to contribute (researcher, software engineer, administrator of research servers, science funders). Panellists were John Swinbank from ASTRON, Niki van Stein from LIACS, Leiden University, Matthijs Moed from SURF and Jeremy Cohen from Imperial College London.&lt;/p&gt;
&lt;p&gt;Panellists were asked to prepare a short pitch with their view on the following question:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Which infrastructures (version control, containers publication, Zenodo, testing infrastructure, any other?) are most important to the work your organisation does?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is a summary of the pitches from each panellist:&lt;/p&gt;
&lt;h2 id=&quot;john-swinbank-astron&quot;&gt;John Swinbank, ASTRON&lt;/h2&gt;
&lt;p&gt;ASTRON works on a regime of big data. We are already working with tens of petabytes of data from telescopes like LOFAR, and that will increase to the order of 1 Exabyte per year when SKA (Ed.: a &lt;a href=&quot;https://www.astron.nl/category/telescopes/ska/&quot;&gt;new radio telescope&lt;/a&gt;) comes online later this decade. Our task is to make sure this volume of data is in a format that is usable for astronomers. The astronomical community has been working towards full reproducibility, but it is not yet completely embedded in the culture. In terms of infrastructure, we have a local GitLab instance for code sharing;using containers and publishing on Zenodo is not yet universally accepted.&lt;/p&gt;
&lt;h2 id=&quot;niki-van-stein-liacs-leiden-university&quot;&gt;Niki van Stein, LIACS, Leiden University&lt;/h2&gt;
&lt;p&gt;In my group reproducibility is a big thing. Both to verify research results from us and other groups and also to build and document on code developed by master and PhD students. We use version control, and docker. Code alone is not enough, we aim to share the whole environment. But this is challenging when the code requires multiple CPUs and GPUs, you cannot easily put that in a docker container!&lt;/p&gt;
&lt;h2 id=&quot;matthijs-moed-surf&quot;&gt;Matthijs Moed, SURF&lt;/h2&gt;
&lt;p&gt;At SURF, we build tools that fit in the workflow of researchers. Our biggest challenge is finding out what researchers actually need and how they can use our tools in their work. We work not only with organisations like Astron, who need very special infrastructure, but also for the majority of researchers who use computational methods but are not specialists in using them. Offering the right tools to them involves sometimes knowing their needs without them being able to formulate them. Meeting researchers where they are is key to developing sustainable research software.&lt;/p&gt;
&lt;h2 id=&quot;jeremy-cohen-imperial-college-london&quot;&gt;Jeremy Cohen, Imperial College London&lt;/h2&gt;
&lt;p&gt;Infrastructure to support software, such as version control, is particularly important in my work and that of people I collaborate with. Containers are becoming more important in the research community as a method to help support reproducibility and address challenges such as working across different computing platforms. Continuous integration (CI) (Ed: continuously testing code while expanding its functionality) is also growing in importance. At Imperial College London, as in many other research institutions, we have access to such services, but of course, as the use of software and computing infrastructure in research continues to grow, there are frequently new opportunities emerging to improve the offerings and infrastructure that are provided to researchers. This is something that I aim to help support as a leader of our local research software community.&lt;/p&gt;
&lt;h2 id=&quot;discussion-session&quot;&gt;Discussion session&lt;/h2&gt;
&lt;p&gt;While we had prepared some questions for the panellists, we also allowed the discussion to flow organically. Members of the audience were also invited to ask their own questions. This is a summary of some of these questions and the panel’s responses.&lt;/p&gt;
&lt;p&gt;How is national infrastructure organised in the UK, and how does it compare to the Netherlands?***&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jeremy&lt;/em&gt;: While there is national research computing infrastructure in the UK, many resources are also provided at a local or regional level. There is wide use of commercial services for managing code, such as GitHub. I feel that there is scope for improvement in the context of providing coordinated research software infrastructure at a national level but it can be difficult to assess the value of this and how to make it available. A key discussion point is who pays for such infrastructure and how? And how do we make sure people have equal access to these resources particularly when they are paid services?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Matthijs:&lt;/em&gt; at SURF we provide national infrastructure. There are technical difficulties like federation (Ed: sharing resources across multiple organisations), but we probably need to revisit some of these limitations and see what is possible as technology changes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;John&lt;/em&gt;: One thing we notice is that the barrier to external contributors is high with our local GitLab instance — working on GitHub makes it easier for astronomers around the world to collaborate, and some of our collaborators are based around the world, in places such as the USA and China.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Audience member #1&lt;/em&gt;: National infrastructure also creates fragmentation. Maybe we need a roadmap / strategy, not only infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;In your opinion, which infrastructures are missing, that you/your organisation would benefit if they were available?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This question sparked a short discussion and several audience members contributed to it: One audience member said that guidance on HPC resources is very valuable. They have HPC resources available from SURF (Lisa, Research Cloud, etc.) but still need some guidance on when to use which one. Another audience member experienced SURF as an invaluable resource for navigating the different solutions available for their research needs. Another point that was raised were generic skills that would help all researchers working with high computational needs, like basic GPU and CPU programing. The audience member mentioned that there is a hurdle to getting to know all these systems, while, at the same time, a bit of speedup in your results is indeed an invaluable resource.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How about the code itself? Are there quality criteria applicable to all code, making it FAIR and sustainable? Should we educate all researchers?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jeremy&lt;/em&gt;: Not every researcher should be a computer scientist, but some level of understanding on code quality and how to think about writing your code is still valuable. For example, how you think about the problem. Software being considered a first class output would make researchers see more value in producing good code. Architecture of code makes code more sustainable. Good quality documentation should provide the information users will need. Documenting decisions on choices of libraries used is also useful.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;John&lt;/em&gt;: At ASTRON there are some practices we follow to make code better, and we should do more. We have professional engineers who are not (necessarily) astronomers. In this group we encourage good practices like code reviews. I am curious about using Sonarqube (Ed: an &lt;a href=&quot;https://www.sonarsource.com/products/sonarqube/&quot;&gt;open-source platform for continuous analysis of code quality&lt;/a&gt;), but just playing with it at the moment. One thing that resonated from what Jeremy said, is that there are astronomers who get really involved in developing code (such as astropy), but it does not get recognition — it will not get you tenure. This is a problem for the sustainability of astropy. And we do not have funding models for it, such as turning packages into part of the infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Are we creating walls around science? “To be an astronomer you need to know a long list of things”?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;John&lt;/em&gt;: You do need to have some level of knowledge. We have been using things like mentoring or google summer of code to develop some of these skills on people who use them.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Audience&lt;/em&gt;: what I find interesting are the collaborations for example in digital humanities: computer scientists &amp;#x26; historians, more collaboration is the way to go.&lt;/p&gt;
&lt;p&gt;It is in a way similar to a chemistry lab: at the lab you have materials available, and protocols you need to follow to use those materials. Researchers get trained on how to use those materials, but they do not need to build them themselves. Research software is similar to those materials, researchers need to be trained on how to use them, but they can work together with research software engineers that can help them build those materials.&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Most important points/Key Message&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;During our panel session on infrastructure for sustainable research software, we discussed several services for tracking changes, sharing computational environments and high performance computing. Interestingly, the discussion quickly moved from technical solutions towards a more broader view of what constitutes infrastructure:&lt;/p&gt;
&lt;p&gt;The panel and audience agreed that it should be acknowledged that infrastructure is not only facilities and services, but that people, and in some cases software, can also be a critical part of infrastructure.&lt;/p&gt;
&lt;p&gt;For the panel session itself, we cannot say that the panellists and audience agreed on which services exactly are critical or absolutely essential to be offered at national level. What the audience and panellists agreed on was that we need a national strategy or roadmap to organise infrastructure in a way that is technically sound, as well as useful for the end users. And not just the technical infrastructure, but also the organisational infrastructure and personnel to provide better support to researchers by providing consultancy, training and implementation. Furthermore, everyone in the room saw the need to include the points of view from a diverse set of users when deciding on the infrastructure. Not all users will want or need to have a say in what type of services are offered, but they will want to be informed on how to use and access those services when needed.&lt;/p&gt;</description><pubDate>Thu, 26 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;*written by &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-luisa-orozco/&quot;&gt;&lt;em&gt;Luisa Orozco&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;http://www.linkedin.com/in/danielagawehns/&quot;&gt;&lt;em&gt;Daniela Gawehns&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and *&lt;a href=&quot;https://medium.com/@c.martinez&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Open Science Festival: What infrastructures do we need to preserve research software?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/open-science-festival-what-infrastructur-9069ad56.Bg1b7T0q_biUgK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Earlier this year, the 2023 edition of the Dutch &lt;a href=&quot;https://opensciencefestival.nl/&quot;&gt;Open Science Festival&lt;/a&gt; was held. We (the eScience Center and Leiden University) organised the session “National infrastructure for sustainable research software”. In this session we discussed the benefits and limits of available software preservation platforms (or infrastructures) and if national infrastructures for research software development are feasible and desirable.&lt;/p&gt;
&lt;p&gt;Research software increasingly forms a critically important element of many research projects across a wide array of domains. To achieve truly sustainable and reproducible research, not only the software itself but also the computational environment it depends on needs to be preserved. Different types of infrastructure are required to support these preservation activities.&lt;/p&gt;
&lt;p&gt;One user-friendly example of a friendly way to package computational environmetns are Docker containers. These containers can be archived on privately owned platforms like Docker Hub and GitHub or on publicly funded archives such as Zenodo. Such platforms become part of the infrastructure needed to rerun and reuse research code associated with research results.&lt;/p&gt;
&lt;h2 id=&quot;panel-composition-and-pitches&quot;&gt;Panel composition and pitches&lt;/h2&gt;
&lt;p&gt;The session was organised as a series of panel pitches, followed by a group discussion. The panel shared their insights and experiences, as we explored current issues with container storage platforms and related infrastructure and the role the Dutch research landscape can take as a provider of independent and government funded infrastructure for sustainable research software.&lt;/p&gt;
&lt;p&gt;The panel was composed of national and international experts from different domains and backgrounds to contribute (researcher, software engineer, administrator of research servers, science funders). Panellists were John Swinbank from ASTRON, Niki van Stein from LIACS, Leiden University, Matthijs Moed from SURF and Jeremy Cohen from Imperial College London.&lt;/p&gt;
&lt;p&gt;Panellists were asked to prepare a short pitch with their view on the following question:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Which infrastructures (version control, containers publication, Zenodo, testing infrastructure, any other?) are most important to the work your organisation does?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is a summary of the pitches from each panellist:&lt;/p&gt;
&lt;h2 id=&quot;john-swinbank-astron&quot;&gt;John Swinbank, ASTRON&lt;/h2&gt;
&lt;p&gt;ASTRON works on a regime of big data. We are already working with tens of petabytes of data from telescopes like LOFAR, and that will increase to the order of 1 Exabyte per year when SKA (Ed.: a &lt;a href=&quot;https://www.astron.nl/category/telescopes/ska/&quot;&gt;new radio telescope&lt;/a&gt;) comes online later this decade. Our task is to make sure this volume of data is in a format that is usable for astronomers. The astronomical community has been working towards full reproducibility, but it is not yet completely embedded in the culture. In terms of infrastructure, we have a local GitLab instance for code sharing;using containers and publishing on Zenodo is not yet universally accepted.&lt;/p&gt;
&lt;h2 id=&quot;niki-van-stein-liacs-leiden-university&quot;&gt;Niki van Stein, LIACS, Leiden University&lt;/h2&gt;
&lt;p&gt;In my group reproducibility is a big thing. Both to verify research results from us and other groups and also to build and document on code developed by master and PhD students. We use version control, and docker. Code alone is not enough, we aim to share the whole environment. But this is challenging when the code requires multiple CPUs and GPUs, you cannot easily put that in a docker container!&lt;/p&gt;
&lt;h2 id=&quot;matthijs-moed-surf&quot;&gt;Matthijs Moed, SURF&lt;/h2&gt;
&lt;p&gt;At SURF, we build tools that fit in the workflow of researchers. Our biggest challenge is finding out what researchers actually need and how they can use our tools in their work. We work not only with organisations like Astron, who need very special infrastructure, but also for the majority of researchers who use computational methods but are not specialists in using them. Offering the right tools to them involves sometimes knowing their needs without them being able to formulate them. Meeting researchers where they are is key to developing sustainable research software.&lt;/p&gt;
&lt;h2 id=&quot;jeremy-cohen-imperial-college-london&quot;&gt;Jeremy Cohen, Imperial College London&lt;/h2&gt;
&lt;p&gt;Infrastructure to support software, such as version control, is particularly important in my work and that of people I collaborate with. Containers are becoming more important in the research community as a method to help support reproducibility and address challenges such as working across different computing platforms. Continuous integration (CI) (Ed: continuously testing code while expanding its functionality) is also growing in importance. At Imperial College London, as in many other research institutions, we have access to such services, but of course, as the use of software and computing infrastructure in research continues to grow, there are frequently new opportunities emerging to improve the offerings and infrastructure that are provided to researchers. This is something that I aim to help support as a leader of our local research software community.&lt;/p&gt;
&lt;h2 id=&quot;discussion-session&quot;&gt;Discussion session&lt;/h2&gt;
&lt;p&gt;While we had prepared some questions for the panellists, we also allowed the discussion to flow organically. Members of the audience were also invited to ask their own questions. This is a summary of some of these questions and the panel’s responses.&lt;/p&gt;
&lt;p&gt;How is national infrastructure organised in the UK, and how does it compare to the Netherlands?***&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jeremy&lt;/em&gt;: While there is national research computing infrastructure in the UK, many resources are also provided at a local or regional level. There is wide use of commercial services for managing code, such as GitHub. I feel that there is scope for improvement in the context of providing coordinated research software infrastructure at a national level but it can be difficult to assess the value of this and how to make it available. A key discussion point is who pays for such infrastructure and how? And how do we make sure people have equal access to these resources particularly when they are paid services?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Matthijs:&lt;/em&gt; at SURF we provide national infrastructure. There are technical difficulties like federation (Ed: sharing resources across multiple organisations), but we probably need to revisit some of these limitations and see what is possible as technology changes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;John&lt;/em&gt;: One thing we notice is that the barrier to external contributors is high with our local GitLab instance — working on GitHub makes it easier for astronomers around the world to collaborate, and some of our collaborators are based around the world, in places such as the USA and China.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Audience member #1&lt;/em&gt;: National infrastructure also creates fragmentation. Maybe we need a roadmap / strategy, not only infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;In your opinion, which infrastructures are missing, that you/your organisation would benefit if they were available?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This question sparked a short discussion and several audience members contributed to it: One audience member said that guidance on HPC resources is very valuable. They have HPC resources available from SURF (Lisa, Research Cloud, etc.) but still need some guidance on when to use which one. Another audience member experienced SURF as an invaluable resource for navigating the different solutions available for their research needs. Another point that was raised were generic skills that would help all researchers working with high computational needs, like basic GPU and CPU programing. The audience member mentioned that there is a hurdle to getting to know all these systems, while, at the same time, a bit of speedup in your results is indeed an invaluable resource.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How about the code itself? Are there quality criteria applicable to all code, making it FAIR and sustainable? Should we educate all researchers?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jeremy&lt;/em&gt;: Not every researcher should be a computer scientist, but some level of understanding on code quality and how to think about writing your code is still valuable. For example, how you think about the problem. Software being considered a first class output would make researchers see more value in producing good code. Architecture of code makes code more sustainable. Good quality documentation should provide the information users will need. Documenting decisions on choices of libraries used is also useful.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;John&lt;/em&gt;: At ASTRON there are some practices we follow to make code better, and we should do more. We have professional engineers who are not (necessarily) astronomers. In this group we encourage good practices like code reviews. I am curious about using Sonarqube (Ed: an &lt;a href=&quot;https://www.sonarsource.com/products/sonarqube/&quot;&gt;open-source platform for continuous analysis of code quality&lt;/a&gt;), but just playing with it at the moment. One thing that resonated from what Jeremy said, is that there are astronomers who get really involved in developing code (such as astropy), but it does not get recognition — it will not get you tenure. This is a problem for the sustainability of astropy. And we do not have funding models for it, such as turning packages into part of the infrastructure.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Are we creating walls around science? “To be an astronomer you need to know a long list of things”?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;John&lt;/em&gt;: You do need to have some level of knowledge. We have been using things like mentoring or google summer of code to develop some of these skills on people who use them.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Audience&lt;/em&gt;: what I find interesting are the collaborations for example in digital humanities: computer scientists &amp;#x26; historians, more collaboration is the way to go.&lt;/p&gt;
&lt;p&gt;It is in a way similar to a chemistry lab: at the lab you have materials available, and protocols you need to follow to use those materials. Researchers get trained on how to use those materials, but they do not need to build them themselves. Research software is similar to those materials, researchers need to be trained on how to use them, but they can work together with research software engineers that can help them build those materials.&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Most important points/Key Message&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;During our panel session on infrastructure for sustainable research software, we discussed several services for tracking changes, sharing computational environments and high performance computing. Interestingly, the discussion quickly moved from technical solutions towards a more broader view of what constitutes infrastructure:&lt;/p&gt;
&lt;p&gt;The panel and audience agreed that it should be acknowledged that infrastructure is not only facilities and services, but that people, and in some cases software, can also be a critical part of infrastructure.&lt;/p&gt;
&lt;p&gt;For the panel session itself, we cannot say that the panellists and audience agreed on which services exactly are critical or absolutely essential to be offered at national level. What the audience and panellists agreed on was that we need a national strategy or roadmap to organise infrastructure in a way that is technically sound, as well as useful for the end users. And not just the technical infrastructure, but also the organisational infrastructure and personnel to provide better support to researchers by providing consultancy, training and implementation. Furthermore, everyone in the room saw the need to include the points of view from a diverse set of users when deciding on the infrastructure. Not all users will want or need to have a say in what type of services are offered, but they will want to be informed on how to use and access those services when needed.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/open-science-festival-what-infrastructur-9069ad56.Bg1b7T0q.jpeg" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>The Utopic Git History</title><link>https://blog2.esciencecenter.nl/posts/2023-10-25---the-utopic-git-history</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-10-25---the-utopic-git-history</guid><description>&lt;p&gt;&lt;em&gt;If you love this article and can’t wait to read more about The Utopic Git History, please see &lt;em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/achieving-utopic-git-history-4cc2a1fd3107?sk=88f3dac86d55ac1833f66165bc6634c2&quot;&gt;&lt;em&gt;this follow-up article&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; by Abel.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A quick way to create discord among a group of developers is to discuss Git. More specifically, whether to merge, rebase, or squash. There are many arguments around this, simply because it involves opinions on whether the end result is good or bad. Some of these arguments verge from bad experiences with extreme cases. The most common case that I encounter is the dreadful huge pull request**.&lt;/p&gt;
&lt;p&gt;“Mm… can you review this for me?” — Cthulhu (Generated by DALL-E, modified by me)A very large pull request is one containing changes in many files, possibly with many commits. Even if best practices are followed — which we will discuss here — it is a big endeavor to review such a pull request. If best practices are not followed, then it is a nightmare, and the end result is ugly. Some common issues with the result are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sequential commits that seem unrelated.&lt;/li&gt;
&lt;li&gt;Many commits “fixing” the same thing.&lt;/li&gt;
&lt;li&gt;One huge (probably squashed) commit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s discuss how to avoid this issue, and touch on the merge vs rebase vs squash debate on the way there.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Target audience: This post should be useful for anyone interested in best practices with Git, or intermediate/advanced usage of Git. It also contains opinions on Git rebase and squash, so it might trigger some people.&lt;/p&gt;
&lt;h2 id=&quot;ugh--utopic-git-history&quot;&gt;UGH — Utopic Git History&lt;/h2&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note: UGH should be pronounced with disdain and eye-rolling.&lt;/p&gt;
&lt;p&gt;The main idea behind what I will call UGH workflow is **atomic git commits. **This is not a new subject, you can find a few blog posts about it — in fact, I just found out about the &lt;a href=&quot;https://www.youtube.com/watch?v=_e5oq4JT4_8&quot;&gt;Git Legit&lt;/a&gt; talk by Pauline Vos and I strongly recommend watching it.&lt;/p&gt;
&lt;p&gt;If you haven’t heard of atomic git commits, let me give you a short introduction. The basic idea of an atomic git commit is that it contains the shortest amount of work that does what it is supposed to do. That is, less work would not be enough to do the task, and more work would be going out of scope.&lt;/p&gt;
&lt;p&gt;Pauline describes three features of an atomic git commit, the first is what I just described. I normally like to think of the other two separately because they are good practices that we should follow even if we don’t do atomic git commits: (i) make sure that new commits do not break the code and (ii) have a clear and concise commit message. However, I understand the need to explicitly mention them, so that’s why I just explicitly mentioned them as well.&lt;/p&gt;
&lt;p&gt;If every commit is an atomic commit, then we have a beautiful git history. Every commit passes tests, so we can easily navigate around. Every commit has a non-creeping purpose, so we can cherry-pick them more easily. Every commit is self-contained, so we can revert them trivially. It is almost utopic, but it is actually attainable.&lt;/p&gt;
&lt;p&gt;If a pull request made of atomic git commits passes our way, we can review each commit individually, making our life easier. Then, what is the end result of our three merging strategies (as given by GitHub)?&lt;/p&gt;
&lt;h3 id=&quot;merge-commit&quot;&gt;Merge commit&lt;/h3&gt;
&lt;p&gt;A merge commit will be a new commit with a message like &lt;em&gt;“Merging PR #123 from branch featureX”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Visualization of Git merge with a new commit. (&lt;a href=&quot;https://doi.org/10.5281/zenodo.8032313)Here&quot;&gt;https://doi.org/10.5281/zenodo.8032313)Here&lt;/a&gt; is an example from a real GitHub repository:&lt;/p&gt;
&lt;p&gt;A main branch up top and many branches that were merged with merge commit. Source: GitHub network graph of &lt;a href=&quot;https://github.com/abelsiqueira/perprof-py&quot;&gt;https://github.com/abelsiqueira/perprof-py&lt;/a&gt;.Personally, I don’t think that this extra commit is very useful. Even when all commits in the branch are pristine, passing, and having a great message, we still have this “parallel” development, which does not add any useful information. Furthermore, the merge commits themselves are not atomic.&lt;/p&gt;
&lt;h3 id=&quot;squash&quot;&gt;Squash&lt;/h3&gt;
&lt;p&gt;Squashing is simply creating a single commit with the content of all commits, and rebasing the result.&lt;/p&gt;
&lt;p&gt;Visualization of merging with squash. (&lt;a href=&quot;https://doi.org/10.5281/zenodo.8032313)The&quot;&gt;https://doi.org/10.5281/zenodo.8032313)The&lt;/a&gt; default commit message will change the title of the commit to something like &lt;em&gt;“Title of the pull request (#pr)”&lt;/em&gt;, and then the old commit messages will be aggregated into a single commit message. This is a problem because now we have taken all atomic git commits and thrown their &lt;em&gt;atomicity&lt;/em&gt; away.&lt;/p&gt;
&lt;p&gt;The squash frequently comes into play when the pull request **does not **contain atomic git commits. Then it might be better to squash and have a single commit than a larger mess. If the resulting commit is atomic, then that is great. Otherwise, we have scope creep.&lt;/p&gt;
&lt;h3 id=&quot;rebase-and-dont-squash&quot;&gt;Rebase and don’t squash&lt;/h3&gt;
&lt;p&gt;Rebasing without squashing means rebasing the current branch on top of the current &lt;code&gt;main&lt;/code&gt; and merging with &lt;code&gt;fast-forward&lt;/code&gt;, i.e., not creating any new commit and simply updating &lt;code&gt;main&lt;/code&gt;’s pointer.&lt;/p&gt;
&lt;p&gt;Visualization of Git rebase. (&lt;a href=&quot;https://doi.org/10.5281/zenodo.8032313)Here&quot;&gt;https://doi.org/10.5281/zenodo.8032313)Here&lt;/a&gt; is an example from the same GitHub repository, from a later date:&lt;/p&gt;
&lt;p&gt;Main branch and no other branches. Source: GitHub network graph of &lt;a href=&quot;https://github.com/abelsiqueira/perprof-py&quot;&gt;https://github.com/abelsiqueira/perprof-py&lt;/a&gt;.The end result contains only &lt;code&gt;main&lt;/code&gt;. There is no information that there ever was a feature branch.&lt;/p&gt;
&lt;p&gt;This strategy was shown for last because it is my preference, but also because it is the only one of the three that will consistently keep the commits atomic — assuming that we have achieved a pull request with atomic commits.&lt;/p&gt;
&lt;h2 id=&quot;how-to-achieve-atomic-git-commits&quot;&gt;How to achieve atomic git commits&lt;/h2&gt;
&lt;p&gt;Here are some tips to make pull requests with atomic git commits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If there are too many commits, use &lt;code&gt;git rebase -i&lt;/code&gt; to reorder, fix, squash or edit commits.&lt;/li&gt;
&lt;li&gt;If there is uncommitted work that touches more than one topic, use &lt;code&gt;git add -p&lt;/code&gt; to add the parts that make sense for a single commit.&lt;/li&gt;
&lt;li&gt;If there are commits from different scopes, &lt;code&gt;rebase&lt;/code&gt; into new branches.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;git commit --amend&lt;/code&gt; to fix the current commit.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;git push --force&lt;/code&gt; to update the branch online (the &lt;code&gt;main&lt;/code&gt; branch can be protected so &lt;code&gt;main&lt;/code&gt; is not accidentally rewritten).&lt;/li&gt;
&lt;li&gt;Use a &lt;a href=&quot;http://pre-commit.com&quot;&gt;pre-commit hook&lt;/a&gt; to avoid having to create extra “fix linter” commits.&lt;/li&gt;
&lt;li&gt;Be prescient and write perfect commits — but you knew that already ;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once again I recommend Pauline’s &lt;a href=&quot;https://www.youtube.com/watch?v=_e5oq4JT4_8&quot;&gt;Git Legit&lt;/a&gt; talk for more detailed examples but feel free to leave a comment here if you think of a situation that needs more care.&lt;/p&gt;
&lt;h2 id=&quot;more-utopia-please&quot;&gt;More utopia, please&lt;/h2&gt;
&lt;p&gt;The second part of the UGH workflow is to do the same for branches, and therefore, pull requests. In other words, the pull request must have the least amount of commits necessary to do what it is supposed to do. You can read a blog post about this by &lt;a href=&quot;https://fagnerbrack.com/one-pull-request-one-concern-e84a27dfe9f1&quot;&gt;Fagner Brack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If each commit tells a story, and they are in an order that makes sense, reviewing the pull request is much easier. Even if the pull request is still huge, it can be reviewed one commit at a time.&lt;/p&gt;
&lt;p&gt;When reviewing, or receiving reviews, we should be vigilant of scope creep. The PR should do only what it is supposed to do.&lt;/p&gt;
&lt;h3 id=&quot;but-what-is-the-pr-supposed-to-do&quot;&gt;But what is the PR supposed to do?&lt;/h3&gt;
&lt;p&gt;This is the harder part because it is not just git anymore. There are different approaches to determining what is a PR, but the one I have the most experience with is to relate them with issues. In other words, the issue defines the topic, or scope, of the PR. Following this approach, an atomic definition would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each pull request should close one, and only one issue.&lt;/li&gt;
&lt;li&gt;Each issue should be small enough to not creep into more than one topic.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Clarification: not every issue leads to a pull request, but every pull request requires an issue.&lt;/p&gt;
&lt;p&gt;To achieve this, one has to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Break issues into smaller issues.&lt;/li&gt;
&lt;li&gt;Create new issues for every desired change.&lt;/li&gt;
&lt;li&gt;Merge incomplete issues and close duplicates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The actual size of the issue depends on how the team works, and who creates the issues. Some issues are user stories that involve many tasks. Some are bug reports. Some are tech-debt opportunities. Some are users’ questions.&lt;/p&gt;
&lt;p&gt;Issues that involve many tasks are sometimes called epics. *One way of dealing with epic issues is to create separate issues for each task — see the next section — but you could just as well have a larger pull request with one commit for each task. There is no one-size-fits-all solution.&lt;/p&gt;
&lt;p&gt;I find that it helps a lot to work on an epic issue as a whole, then split it into smaller parts &lt;em&gt;a posteriori&lt;/em&gt;. Then I make separate branches and create pull requests one at a time. One shortcoming of this approach is that if the reviewer makes big suggestions to one pull request, the other branches might be heavily affected.&lt;/p&gt;
&lt;h2 id=&quot;extreme-ugh&quot;&gt;Extreme UGH&lt;/h2&gt;
&lt;p&gt;What if we take these atomic definitions to the extreme?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;One commit per pull request.&lt;/p&gt;
&lt;p&gt;Since the issue is minimal, then it should be fixable with a single commit, right? Otherwise, the issue would not be minimal.&lt;/p&gt;
&lt;p&gt;Why is this extreme?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The reviewer and the developer must share the context. For instance, there might be dependencies between pull requests by the same developer. If the reviewer does not have that clear, then the pull request can actually be harder to understand than a single larger PR.&lt;/li&gt;
&lt;li&gt;It can be hard to know beforehand how to break an epic issue. Sometimes we only know how to break an issue after working on it. But what if we are not the ones responsible for updating the issue? Then we need to create a demand for the issue to be broken and wait until work can be restarted.&lt;/li&gt;
&lt;li&gt;Sometimes the code base is not modular enough. We might need API changes for a different part of the code. Scope creep might be unavoidable due to technical debt. If there is time, though, trying to pay this debt as a separate issue might be better.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Be aware of these limitations. Trying to achieve UGH can lead to loss of friends, or worst, productivity (this is a joke, managers).&lt;/p&gt;
&lt;h2 id=&quot;self-inflicted-ugh&quot;&gt;Self-inflicted UGH&lt;/h2&gt;
&lt;p&gt;A good way of starting using UGH is to follow the workflow on your own, before trying to enforce it on the team.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure that your pull requests are atomic, even if nobody is enforcing UGH.&lt;/li&gt;
&lt;li&gt;As long as you’re the only one touching your branch, force-pushing won’t break anybody’s work.&lt;/li&gt;
&lt;li&gt;When you have to update your pull request because of conflicts with &lt;code&gt;main&lt;/code&gt;, you can rebase your branch instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This helps you practice and might help your team to see the benefits.&lt;/p&gt;
&lt;p&gt;Finally, I chose the name Utopic Git History (UGH) to remind us of two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can be very obnoxious to insist on the workflow (hence the ugh sound), especially when reviewing pull requests.&lt;/li&gt;
&lt;li&gt;It is utopic in the sense of being unattainable in practice (for extended periods of time). Take parts of the idea and test them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best way to achieve UGH is to create a good culture first.&lt;/p&gt;
&lt;p&gt;I actually don’t have any project that fully follows the UGH workflow, but I try to follow it with my personal commits, and I use rebase in many repositories. I spent a decent chunk of time helping people to update their workspace after their pull request was rebased (sometimes deleting everything and starting over was the chosen solution). It is not trivial to adopt this strategy for the whole project, but I can certainly say that it helped me learn more about Git.&lt;/p&gt;
&lt;p&gt;Let us know if you (try to) use UGH or similar for your projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/sander-van-rijn-msc/&quot;&gt;&lt;em&gt;Sander van Rijn&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-pablo-rodriguez-sanchez/&quot;&gt;&lt;em&gt;Pablo Rodríguez-Sánchez&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-candace-makeda-moore-md/&quot;&gt;&lt;em&gt;Candace Makeda Moore&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Wed, 25 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;If you love this article and can’t wait to read more about The Utopic Git History, please see &lt;em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/achieving-utopic-git-history-4cc2a1fd3107?sk=88f3dac86d55ac1833f66165bc6634c2&quot;&gt;&lt;em&gt;this follow-up article&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; by Abel.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A quick way to create discord among a group of developers is to discuss Git. More specifically, whether to merge, rebase, or squash. There are many arguments around this, simply because it involves opinions on whether the end result is good or bad. Some of these arguments verge from bad experiences with extreme cases. The most common case that I encounter is the dreadful huge pull request**.&lt;/p&gt;
&lt;p&gt;“Mm… can you review this for me?” — Cthulhu (Generated by DALL-E, modified by me)A very large pull request is one containing changes in many files, possibly with many commits. Even if best practices are followed — which we will discuss here — it is a big endeavor to review such a pull request. If best practices are not followed, then it is a nightmare, and the end result is ugly. Some common issues with the result are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sequential commits that seem unrelated.&lt;/li&gt;
&lt;li&gt;Many commits “fixing” the same thing.&lt;/li&gt;
&lt;li&gt;One huge (probably squashed) commit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s discuss how to avoid this issue, and touch on the merge vs rebase vs squash debate on the way there.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Target audience: This post should be useful for anyone interested in best practices with Git, or intermediate/advanced usage of Git. It also contains opinions on Git rebase and squash, so it might trigger some people.&lt;/p&gt;
&lt;h2 id=&quot;ugh--utopic-git-history&quot;&gt;UGH — Utopic Git History&lt;/h2&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note: UGH should be pronounced with disdain and eye-rolling.&lt;/p&gt;
&lt;p&gt;The main idea behind what I will call UGH workflow is **atomic git commits. **This is not a new subject, you can find a few blog posts about it — in fact, I just found out about the &lt;a href=&quot;https://www.youtube.com/watch?v=_e5oq4JT4_8&quot;&gt;Git Legit&lt;/a&gt; talk by Pauline Vos and I strongly recommend watching it.&lt;/p&gt;
&lt;p&gt;If you haven’t heard of atomic git commits, let me give you a short introduction. The basic idea of an atomic git commit is that it contains the shortest amount of work that does what it is supposed to do. That is, less work would not be enough to do the task, and more work would be going out of scope.&lt;/p&gt;
&lt;p&gt;Pauline describes three features of an atomic git commit, the first is what I just described. I normally like to think of the other two separately because they are good practices that we should follow even if we don’t do atomic git commits: (i) make sure that new commits do not break the code and (ii) have a clear and concise commit message. However, I understand the need to explicitly mention them, so that’s why I just explicitly mentioned them as well.&lt;/p&gt;
&lt;p&gt;If every commit is an atomic commit, then we have a beautiful git history. Every commit passes tests, so we can easily navigate around. Every commit has a non-creeping purpose, so we can cherry-pick them more easily. Every commit is self-contained, so we can revert them trivially. It is almost utopic, but it is actually attainable.&lt;/p&gt;
&lt;p&gt;If a pull request made of atomic git commits passes our way, we can review each commit individually, making our life easier. Then, what is the end result of our three merging strategies (as given by GitHub)?&lt;/p&gt;
&lt;h3 id=&quot;merge-commit&quot;&gt;Merge commit&lt;/h3&gt;
&lt;p&gt;A merge commit will be a new commit with a message like &lt;em&gt;“Merging PR #123 from branch featureX”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Visualization of Git merge with a new commit. (&lt;a href=&quot;https://doi.org/10.5281/zenodo.8032313)Here&quot;&gt;https://doi.org/10.5281/zenodo.8032313)Here&lt;/a&gt; is an example from a real GitHub repository:&lt;/p&gt;
&lt;p&gt;A main branch up top and many branches that were merged with merge commit. Source: GitHub network graph of &lt;a href=&quot;https://github.com/abelsiqueira/perprof-py&quot;&gt;https://github.com/abelsiqueira/perprof-py&lt;/a&gt;.Personally, I don’t think that this extra commit is very useful. Even when all commits in the branch are pristine, passing, and having a great message, we still have this “parallel” development, which does not add any useful information. Furthermore, the merge commits themselves are not atomic.&lt;/p&gt;
&lt;h3 id=&quot;squash&quot;&gt;Squash&lt;/h3&gt;
&lt;p&gt;Squashing is simply creating a single commit with the content of all commits, and rebasing the result.&lt;/p&gt;
&lt;p&gt;Visualization of merging with squash. (&lt;a href=&quot;https://doi.org/10.5281/zenodo.8032313)The&quot;&gt;https://doi.org/10.5281/zenodo.8032313)The&lt;/a&gt; default commit message will change the title of the commit to something like &lt;em&gt;“Title of the pull request (#pr)”&lt;/em&gt;, and then the old commit messages will be aggregated into a single commit message. This is a problem because now we have taken all atomic git commits and thrown their &lt;em&gt;atomicity&lt;/em&gt; away.&lt;/p&gt;
&lt;p&gt;The squash frequently comes into play when the pull request **does not **contain atomic git commits. Then it might be better to squash and have a single commit than a larger mess. If the resulting commit is atomic, then that is great. Otherwise, we have scope creep.&lt;/p&gt;
&lt;h3 id=&quot;rebase-and-dont-squash&quot;&gt;Rebase and don’t squash&lt;/h3&gt;
&lt;p&gt;Rebasing without squashing means rebasing the current branch on top of the current &lt;code&gt;main&lt;/code&gt; and merging with &lt;code&gt;fast-forward&lt;/code&gt;, i.e., not creating any new commit and simply updating &lt;code&gt;main&lt;/code&gt;’s pointer.&lt;/p&gt;
&lt;p&gt;Visualization of Git rebase. (&lt;a href=&quot;https://doi.org/10.5281/zenodo.8032313)Here&quot;&gt;https://doi.org/10.5281/zenodo.8032313)Here&lt;/a&gt; is an example from the same GitHub repository, from a later date:&lt;/p&gt;
&lt;p&gt;Main branch and no other branches. Source: GitHub network graph of &lt;a href=&quot;https://github.com/abelsiqueira/perprof-py&quot;&gt;https://github.com/abelsiqueira/perprof-py&lt;/a&gt;.The end result contains only &lt;code&gt;main&lt;/code&gt;. There is no information that there ever was a feature branch.&lt;/p&gt;
&lt;p&gt;This strategy was shown for last because it is my preference, but also because it is the only one of the three that will consistently keep the commits atomic — assuming that we have achieved a pull request with atomic commits.&lt;/p&gt;
&lt;h2 id=&quot;how-to-achieve-atomic-git-commits&quot;&gt;How to achieve atomic git commits&lt;/h2&gt;
&lt;p&gt;Here are some tips to make pull requests with atomic git commits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If there are too many commits, use &lt;code&gt;git rebase -i&lt;/code&gt; to reorder, fix, squash or edit commits.&lt;/li&gt;
&lt;li&gt;If there is uncommitted work that touches more than one topic, use &lt;code&gt;git add -p&lt;/code&gt; to add the parts that make sense for a single commit.&lt;/li&gt;
&lt;li&gt;If there are commits from different scopes, &lt;code&gt;rebase&lt;/code&gt; into new branches.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;git commit --amend&lt;/code&gt; to fix the current commit.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;git push --force&lt;/code&gt; to update the branch online (the &lt;code&gt;main&lt;/code&gt; branch can be protected so &lt;code&gt;main&lt;/code&gt; is not accidentally rewritten).&lt;/li&gt;
&lt;li&gt;Use a &lt;a href=&quot;http://pre-commit.com&quot;&gt;pre-commit hook&lt;/a&gt; to avoid having to create extra “fix linter” commits.&lt;/li&gt;
&lt;li&gt;Be prescient and write perfect commits — but you knew that already ;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once again I recommend Pauline’s &lt;a href=&quot;https://www.youtube.com/watch?v=_e5oq4JT4_8&quot;&gt;Git Legit&lt;/a&gt; talk for more detailed examples but feel free to leave a comment here if you think of a situation that needs more care.&lt;/p&gt;
&lt;h2 id=&quot;more-utopia-please&quot;&gt;More utopia, please&lt;/h2&gt;
&lt;p&gt;The second part of the UGH workflow is to do the same for branches, and therefore, pull requests. In other words, the pull request must have the least amount of commits necessary to do what it is supposed to do. You can read a blog post about this by &lt;a href=&quot;https://fagnerbrack.com/one-pull-request-one-concern-e84a27dfe9f1&quot;&gt;Fagner Brack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If each commit tells a story, and they are in an order that makes sense, reviewing the pull request is much easier. Even if the pull request is still huge, it can be reviewed one commit at a time.&lt;/p&gt;
&lt;p&gt;When reviewing, or receiving reviews, we should be vigilant of scope creep. The PR should do only what it is supposed to do.&lt;/p&gt;
&lt;h3 id=&quot;but-what-is-the-pr-supposed-to-do&quot;&gt;But what is the PR supposed to do?&lt;/h3&gt;
&lt;p&gt;This is the harder part because it is not just git anymore. There are different approaches to determining what is a PR, but the one I have the most experience with is to relate them with issues. In other words, the issue defines the topic, or scope, of the PR. Following this approach, an atomic definition would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each pull request should close one, and only one issue.&lt;/li&gt;
&lt;li&gt;Each issue should be small enough to not creep into more than one topic.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Clarification: not every issue leads to a pull request, but every pull request requires an issue.&lt;/p&gt;
&lt;p&gt;To achieve this, one has to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Break issues into smaller issues.&lt;/li&gt;
&lt;li&gt;Create new issues for every desired change.&lt;/li&gt;
&lt;li&gt;Merge incomplete issues and close duplicates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The actual size of the issue depends on how the team works, and who creates the issues. Some issues are user stories that involve many tasks. Some are bug reports. Some are tech-debt opportunities. Some are users’ questions.&lt;/p&gt;
&lt;p&gt;Issues that involve many tasks are sometimes called epics. *One way of dealing with epic issues is to create separate issues for each task — see the next section — but you could just as well have a larger pull request with one commit for each task. There is no one-size-fits-all solution.&lt;/p&gt;
&lt;p&gt;I find that it helps a lot to work on an epic issue as a whole, then split it into smaller parts &lt;em&gt;a posteriori&lt;/em&gt;. Then I make separate branches and create pull requests one at a time. One shortcoming of this approach is that if the reviewer makes big suggestions to one pull request, the other branches might be heavily affected.&lt;/p&gt;
&lt;h2 id=&quot;extreme-ugh&quot;&gt;Extreme UGH&lt;/h2&gt;
&lt;p&gt;What if we take these atomic definitions to the extreme?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;One commit per pull request.&lt;/p&gt;
&lt;p&gt;Since the issue is minimal, then it should be fixable with a single commit, right? Otherwise, the issue would not be minimal.&lt;/p&gt;
&lt;p&gt;Why is this extreme?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The reviewer and the developer must share the context. For instance, there might be dependencies between pull requests by the same developer. If the reviewer does not have that clear, then the pull request can actually be harder to understand than a single larger PR.&lt;/li&gt;
&lt;li&gt;It can be hard to know beforehand how to break an epic issue. Sometimes we only know how to break an issue after working on it. But what if we are not the ones responsible for updating the issue? Then we need to create a demand for the issue to be broken and wait until work can be restarted.&lt;/li&gt;
&lt;li&gt;Sometimes the code base is not modular enough. We might need API changes for a different part of the code. Scope creep might be unavoidable due to technical debt. If there is time, though, trying to pay this debt as a separate issue might be better.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Be aware of these limitations. Trying to achieve UGH can lead to loss of friends, or worst, productivity (this is a joke, managers).&lt;/p&gt;
&lt;h2 id=&quot;self-inflicted-ugh&quot;&gt;Self-inflicted UGH&lt;/h2&gt;
&lt;p&gt;A good way of starting using UGH is to follow the workflow on your own, before trying to enforce it on the team.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure that your pull requests are atomic, even if nobody is enforcing UGH.&lt;/li&gt;
&lt;li&gt;As long as you’re the only one touching your branch, force-pushing won’t break anybody’s work.&lt;/li&gt;
&lt;li&gt;When you have to update your pull request because of conflicts with &lt;code&gt;main&lt;/code&gt;, you can rebase your branch instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This helps you practice and might help your team to see the benefits.&lt;/p&gt;
&lt;p&gt;Finally, I chose the name Utopic Git History (UGH) to remind us of two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can be very obnoxious to insist on the workflow (hence the ugh sound), especially when reviewing pull requests.&lt;/li&gt;
&lt;li&gt;It is utopic in the sense of being unattainable in practice (for extended periods of time). Take parts of the idea and test them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The best way to achieve UGH is to create a good culture first.&lt;/p&gt;
&lt;p&gt;I actually don’t have any project that fully follows the UGH workflow, but I try to follow it with my personal commits, and I use rebase in many repositories. I spent a decent chunk of time helping people to update their workspace after their pull request was rebased (sometimes deleting everything and starting over was the chosen solution). It is not trivial to adopt this strategy for the whole project, but I can certainly say that it helped me learn more about Git.&lt;/p&gt;
&lt;p&gt;Let us know if you (try to) use UGH or similar for your projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/sander-van-rijn-msc/&quot;&gt;&lt;em&gt;Sander van Rijn&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-pablo-rodriguez-sanchez/&quot;&gt;&lt;em&gt;Pablo Rodríguez-Sánchez&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-candace-makeda-moore-md/&quot;&gt;&lt;em&gt;Candace Makeda Moore&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><author>Abel Soares Siqueira</author></item><item><title>Achieving Utopic Git History</title><link>https://blog2.esciencecenter.nl/posts/2023-10-19---achieving-utopic-git-history</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-10-19---achieving-utopic-git-history</guid><description>&lt;h2 id=&quot;aka-being-ughly&quot;&gt;AKA being UGHly&lt;/h2&gt;
&lt;p&gt;In a previous blog post, we defined &lt;a href=&quot;https://blog.esciencecenter.nl/the-utopic-git-history-d44b81c09593&quot;&gt;The Utopic Git History&lt;/a&gt; (UGH). To refresh our memory, a simple definition of a UGH is&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Atomic git commits (smallest commit that completes the task)&lt;/li&gt;
&lt;li&gt;Passing tests&lt;/li&gt;
&lt;li&gt;Linear Git history&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In that post, I mentioned that the easiest way to achieve UGH is to squash a self-contained pull request into a single commit. Otherwise, you have to use more advanced git commands to achieve UGH. This blog post deals with that.&lt;/p&gt;
&lt;p&gt;The target audience for this post is Git users who want to learn intermediate and advanced commands that splice, merge, and fix commits. If you need a refresher on some of the concepts used, please take a look at the &lt;a href=&quot;https://blog.esciencecenter.nl/the-utopic-git-history-d44b81c09593&quot;&gt;animations in my previous blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The ideal way of achieving UGH is to write exactly what you have to write, and then commit that. This kind of insight is hard to come by when your task is large, so instead let’s focus on what happens in practice, which involves getting our hands dirty.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Meme. Left image shows dirty hands with a caption “My hands look like this” and right image shows git branches being transformed into linear git history with a caption “So my git history can look like this.”&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_w6RS2UcGCMtyvWSI2Eg7Ow-c5a1c936.CDnJLX_-_Z2uSccu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Getting your hands dirty. Left photo by Jeremy Bishop on Unsplash. Modifications by me.&lt;/p&gt;
&lt;h2 id=&quot;before-committing&quot;&gt;Before committing&lt;/h2&gt;
&lt;p&gt;The first thing that we can control is what to commit. So let’s assume that we got to a point where we have a lot of modifications because task A turned out to be too large and now we’re thinking of splitting it into A1 and A2 (maybe more).&lt;/p&gt;
&lt;p&gt;Here, &lt;code&gt;git add -p&lt;/code&gt; comes into play. &lt;code&gt;git add -p&lt;/code&gt; lets us add &lt;strong&gt;patches&lt;/strong&gt; of code separately. So if our file has modifications for tasks A1 and A2, we can add only the first one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If there is an untracked file that we want to selectively add, it can be included using &lt;code&gt;git add -N FILE&lt;/code&gt;. This will tell git to track the file, but it doesn’t stage it.&lt;/p&gt;
&lt;p&gt;When we run &lt;code&gt;git add -p FILES&lt;/code&gt;, we see something like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;diff &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Something&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Something&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Stage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; this hunk [y,n,q,a,d,s,e,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pressing &lt;code&gt;?&lt;/code&gt; will show the help. There are four commands that matter a lot to us. The first two are y and n, for yes and no. If we say yes, the “hunk” (a piece of code shown in this diff) will be staged. Remember, when we &lt;code&gt;git commit&lt;/code&gt; (no &lt;code&gt;-a&lt;/code&gt; flag), the staged part of the code will be added to the commit. If we say no, then it just moves on to the next hunk.&lt;/p&gt;
&lt;p&gt;The third command is the best: s, for split. If the hunk that we see on the screen is too large, or if it involves parts A1 and A2, then we want to split it. Git will try to find a place to split this code and give you smaller hunks. Then we can decide whether to add or not those new smaller hunks individually.&lt;/p&gt;
&lt;p&gt;Split doesn’t always work, so what we can do instead is use the command e, for edit. Editing will open an editor, so if you don’t like Vim (the default), you can change it with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git config &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--local core.editor &quot;code --wait&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the command above, &lt;code&gt;code --wait&lt;/code&gt; will open VSCode. Change it to your preference. Also, you can configure it globally using &lt;code&gt;--global&lt;/code&gt; instead of &lt;code&gt;--local&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After running &lt;code&gt;git add -p&lt;/code&gt; and selecting the command e, we will get to the editor with the same diff open and some additional information.&lt;/p&gt;
&lt;p&gt;The first column of the hunk can be empty, to indicate that the code doesn’t change, &lt;code&gt;#&lt;/code&gt; to indicate a comment that will be ignored by git add, a &lt;code&gt;-&lt;/code&gt; to indicate that the line should be removed, and a &lt;code&gt;+&lt;/code&gt; to indicate a new line replacing the old one.&lt;/p&gt;
&lt;p&gt;Now, we can manually decide on each individual addition. Let’s look at an example:&lt;/p&gt;
&lt;p&gt;Our initial code is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, our task A1 is to rename y to p, and task A2 is to change all additions to subtractions.&lt;/p&gt;
&lt;p&gt;The resulting code after doing both tasks is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The diff, which we will see when we enter edit mode, is the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Manual hunk edit mode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clearly, tasks A1 and A2 are mixed and can’t be split. So instead, we manually change the diff. Since we want only A1 applied, we change the diff to&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change &lt;code&gt;-w = x + 1&lt;/code&gt; to &lt;code&gt;[space]w = x + 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove line &lt;code&gt;+w = x - 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Move the two + lines one line up&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;+z = x - p&lt;/code&gt; to &lt;code&gt;+z = x + p&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please notice that the lines starting with a minus sign can’t be modified, because they must match with the current code. If you want to make modifications to a line that has a minus, look for the corresponding plus and change that instead. If there is no corresponding plus, it means that the line is simply being removed, so you can add a line with a plus yourself.&lt;/p&gt;
&lt;p&gt;Now, if we look at your git status, we will see the same file appearing in and out of the staged section. We can use &lt;code&gt;git diff --staged&lt;/code&gt; to check the result.&lt;/p&gt;
&lt;h2 id=&quot;oops-too-late-one-commit-with-multiple-tasks&quot;&gt;Oops, too late (one commit with multiple tasks)&lt;/h2&gt;
&lt;p&gt;Let’s say that we have one commit with multiple tasks, i.e., one commit that should be split into more than one.&lt;/p&gt;
&lt;p&gt;For instance, we might have spent 10 minutes meticulously editing what should be staged using the &lt;code&gt;git add -p&lt;/code&gt; command, when by mistake we use &lt;code&gt;git commit -a&lt;/code&gt; and add every unstaged modification in the commit as well, wasting all this work. Completely hypothetical, mind you.&lt;/p&gt;
&lt;p&gt;There is a quick way to “fix” this which is to run &lt;code&gt;git reset HEAD~1&lt;/code&gt;. This will remove the commit and go back to the modified state. To be clear, we don’t lose the modifications made in the commit, as they will be back into the modified state, but we lose the previously staged information in those 10 minutes of work.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;git reset HEAD~1&lt;/code&gt; command assumes that the latest commit is the one that we are fixing. If that is not the case, check the next session.&lt;/p&gt;
&lt;p&gt;As a rule, &lt;strong&gt;always back up your branch&lt;/strong&gt; whenever you run reset and rebase until you are confident that you can get yourself out of tricky situations. Backup, in this case, means creating a new branch, e.g., &lt;code&gt;git branch backup-some-name&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;too-many-commits&quot;&gt;Too many commits&lt;/h2&gt;
&lt;p&gt;Let’s say that we ended up making too many commits. For instance, we were trying to follow the idea above, but noticed some bugs that should be part of task A1, and ended up creating another commit to fix that. Or that we realized that we introduced a bug that had no test when doing A2.&lt;/p&gt;
&lt;p&gt;As an example, consider the following initial state of a file &lt;code&gt;main.py&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return w&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the following git history:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hash00: Older stuff &lt;em&gt;← Where we are right now&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;hash01: Rename variable y to p&lt;/li&gt;
&lt;li&gt;hash02: Change + to -&lt;/li&gt;
&lt;li&gt;hash03: Rename y to p and change + to — in function &lt;code&gt;bar&lt;/code&gt; also&lt;/li&gt;
&lt;li&gt;hash04: Fix linting issue (add spaces around operators)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;hash01&lt;/code&gt; and &lt;code&gt;hash02&lt;/code&gt; commits are the ones we did in the previous sections. The &lt;code&gt;hash03&lt;/code&gt; commit is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the &lt;code&gt;hash04&lt;/code&gt; commit is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;     p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This git history is not great. We still only have two tasks (A1 and A2), but 4 commits. What we want to do is redistribute the work done in these 4 commits into 2 commits. For that, we use &lt;code&gt;git rebase -i&lt;/code&gt;, i.e., interactive rebase.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: There is an alternative to rebasing here, which is to run &lt;code&gt;reset hash00&lt;/code&gt;, so that we remove all the commits but none of the modifications. From there we will have to manually add the changes using &lt;code&gt;git add -p&lt;/code&gt; and then make individual commits. I prefer the rebase strategy. What are your thoughts about these two strategies?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The interactive rebase command allows us to reorder and squash commits, change the commit messages, and stop during rebasing to make additional changes (such as splitting older commits).&lt;/p&gt;
&lt;p&gt;The first thing that we need to do is find that git history. If you use a visual tool, you can just look at the graph. Otherwise, we can issue the command&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git log &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--graph --oneline&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will produce a graph of the commits, one per line, which should be easy to read. It should be something like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash04&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (feat_br) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash03&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash00&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (main) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Older&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This assumes that we branched out of &lt;code&gt;main&lt;/code&gt; into a branch called &lt;code&gt;feat_br&lt;/code&gt;. Now, to start rebasing, we can issue&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i main feat_br&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, it is just the normal rebase command, but now we add the &lt;code&gt;-i&lt;/code&gt; flag to have more options on how to rebase.&lt;/p&gt;
&lt;p&gt;This command should open an editor with the list of commits preceded by a keyword &lt;code&gt;pick&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash04 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the commit at &lt;code&gt;main&lt;/code&gt; is not included, as expected.&lt;/p&gt;
&lt;p&gt;What we can do now is change the order of these commits as we see fit and change the keyword to the action that we want. Notice that the order of the commits is top-to-bottom.&lt;/p&gt;
&lt;p&gt;The main options are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pick: Use this commit. It will be applied, and the message will be used.&lt;/li&gt;
&lt;li&gt;drop: Don’t use the commit. It will be lost.&lt;/li&gt;
&lt;li&gt;reword: Use this commit, but open the editor to modify the commit message.&lt;/li&gt;
&lt;li&gt;squash: Merge the contents of this commit in the previous commit and then open the editor for editing the commit message. By default, it appends the commit messages of squashed commits.&lt;/li&gt;
&lt;li&gt;fixup: Like squash, merge the contents into the previous commit, but ignore the message.&lt;/li&gt;
&lt;li&gt;edit: Use this commit and the message, but after the commit is done, stop so we can make edits.&lt;/li&gt;
&lt;li&gt;break: Use by itself in a new line. It will drop us in the terminal to do whatever we want.&lt;/li&gt;
&lt;li&gt;exec: Use by itself followed by a command. It will run the command, and if there is an error, drops us in the terminal to do whatever we want.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whenever we are dropped in the terminal during rebase, we can always issue &lt;code&gt;git rebase --abort&lt;/code&gt; to stop the rebase completely and go back to where we were.&lt;/p&gt;
&lt;p&gt;If we were dropped in the terminal because there is a problem, for instance, a conflict, then we must fix it.&lt;/p&gt;
&lt;p&gt;After fixing whatever caused us to be dropped into the terminal (check with &lt;code&gt;git status&lt;/code&gt; ) we have to use &lt;code&gt;git rebase --continue&lt;/code&gt; to continue rebasing.&lt;/p&gt;
&lt;p&gt;Going back to our example, the first thing that we’ll do is split the &lt;code&gt;hash03&lt;/code&gt; commit. To do that, we simply change we &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;edit&lt;/code&gt;, save and close.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;edit hash03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash04 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will drop us in the terminal with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Stopped&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at hash03&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;You&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; can amend the commit now, with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git commit &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--amend &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Once&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; you are satisfied with your changes, run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git rebase &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--continue&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we will use &lt;code&gt;reset&lt;/code&gt; to undo this single commit and add only the change for task A1.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git reset &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HEAD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git add &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make the first commit diff look like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the second looks like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;     p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can run &lt;code&gt;git rebase --continue&lt;/code&gt; and &lt;code&gt;git log --graph --oneline&lt;/code&gt; again to obtain:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; newh03&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (feat_br) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; newh02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; newh01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash00&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (main) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Older&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the hashes changed only after we effectively rebased.&lt;/p&gt;
&lt;p&gt;Now, we will use &lt;code&gt;git rebase -i main feat_br&lt;/code&gt; again, but this time we will move things around and change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;fixup&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We start with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick newh01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick newh02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick newh03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And change to&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fixup newh01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fixup newh02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fixup newh03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will apply the first commit and then fix it, leaving only a single commit. Then, it will apply the second commit and fix it twice. None of these changes led to conflicts.&lt;/p&gt;
&lt;p&gt;At the end of this process, our log is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; more02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (feat_br) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; more01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash00&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (main) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Older&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, we have achieved UGH for this branch.&lt;/p&gt;
&lt;h2 id=&quot;splitting-a-branch-into-many-branches&quot;&gt;Splitting a branch into many branches&lt;/h2&gt;
&lt;p&gt;Now that we have two commits, one for each task, it makes sense to actually have two branches: one for each commit.&lt;/p&gt;
&lt;p&gt;Since the commits are atomic, this is actually very easy to do &lt;strong&gt;unless&lt;/strong&gt; the branches depend on each other.&lt;/p&gt;
&lt;p&gt;The first task is just the first commit in our case, so we only need to give it a branch name:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git branch feature_taskA more01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, we are creating a branch called &lt;code&gt;feature_taskA&lt;/code&gt; at the commit with hash &lt;code&gt;more01&lt;/code&gt;. Push this branch&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git push &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;u origin feature_taskA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It can be reviewed and rebased.&lt;/p&gt;
&lt;p&gt;Now, let’s split into two situations.&lt;/p&gt;
&lt;h3 id=&quot;splitting-independent-branches&quot;&gt;Splitting independent branches&lt;/h3&gt;
&lt;p&gt;If the commits are independent, we just have so now where they start and rebase rooted there.&lt;/p&gt;
&lt;p&gt;Normally, we are rooted in main, as in our example above. So we can issue&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--onto=main feature_taskA feat_br&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we are saying “Take all commits after &lt;code&gt;feature_taskA&lt;/code&gt; (exclusive) that are part of branch &lt;code&gt;feat_br&lt;/code&gt;, and reapply them on top of the branch &lt;code&gt;main&lt;/code&gt;.” We can use a hash instead of &lt;code&gt;main&lt;/code&gt;, if necessary.&lt;/p&gt;
&lt;p&gt;This can lead to conflicts, even if there is no real dependency between the commits. If the conflicts are significant, then it is better to treat them as dependents. The conflicts that appear here will reappear when we try to merge these two branches into main.&lt;/p&gt;
&lt;h3 id=&quot;splitting-dependent-branches&quot;&gt;Splitting dependent branches&lt;/h3&gt;
&lt;p&gt;If the branches are dependent, then we should actually wait until the first part is merged before rebasing.&lt;/p&gt;
&lt;p&gt;When the first part is merged (let’s assume with GitHub’s rebase), then we now have a new &lt;code&gt;main&lt;/code&gt;, with other commit hashes. In that case, we can simply issue a rebase and the commits that already appeared on the merged branch will be skipped, by default.&lt;/p&gt;
&lt;p&gt;However, this depends on configuration values, so it is safer to just use exactly the same commands as before, but don’t forget to update your main branch.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git fetch &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git merge &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--ff-only upstream/main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--onto=main feature_taskA feat_br&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, the only difference between the independent and dependent cases is &lt;strong&gt;when&lt;/strong&gt; to rebase. If the branches are independent, you can split and push both, since they can be reviewed and merged independently. If the branches are dependent, then we wait until the first branch is merged and rebase after updating main.&lt;/p&gt;
&lt;h2 id=&quot;remote-changes&quot;&gt;Remote changes&lt;/h2&gt;
&lt;p&gt;The last thing to discuss is the changes that could be happening in the remotes while we’re making changes.&lt;/p&gt;
&lt;p&gt;Let’s assume in this section that we have two remotes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;upstream&lt;/code&gt;: Points to the main repo, e.g., the organization’s repo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;origin&lt;/code&gt;: Points to our fork.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First of all, my preferred way to work is to make sure that my atomic commit is up to date with the remote branch. So first of all, I fetch everything, update &lt;code&gt;main&lt;/code&gt; with the fast-forward option, and &lt;strong&gt;branch from main&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git fetch &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git merge &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--ff-only upstream/main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the merge had conflicts, it means that we made commits to &lt;code&gt;main&lt;/code&gt;, and we shouldn’t. We fix this by creating the branch now and resetting main:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git branch featureX &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; just creates, does not switch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git reset &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--hard upstream/main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, after working on branch &lt;code&gt;featureX&lt;/code&gt;, we check for updates on &lt;code&gt;main &lt;/code&gt; again, using &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;merge --ff-only&lt;/code&gt;. If there were any changes to main, we rebase after pushing:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase main featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We might have conflicts, but since our branch is atomic, they should be few and far between.&lt;/p&gt;
&lt;p&gt;After rebasing, we push:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git push &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;u origin featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let’s say that we had to make changes because of the review. After making our changes, we use interactive rebase to make sure that the commits are atomic again. Our branch will not be in sync with the remote branch anymore, because the commits have changed (either in content or in hash).&lt;/p&gt;
&lt;p&gt;That means that we now have to force-push our branch:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git push &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--force featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should be enough to update the pull request.&lt;/p&gt;
&lt;h3 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h3&gt;
&lt;p&gt;These commands should help you handle most git situations. They are not easy to master, so I hope that this post serves as a quick way to remember what each command does. Let us know what other Git needs you have.&lt;/p&gt;
&lt;p&gt;Be UGHly, my friend.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-barbara-veede/&quot;&gt;&lt;em&gt;Barbara Vreede&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-pablo-rodriguez-sanchez/&quot;&gt;&lt;em&gt;Pablo Rodríguez-Sánchez&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 19 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;aka-being-ughly&quot;&gt;AKA being UGHly&lt;/h2&gt;
&lt;p&gt;In a previous blog post, we defined &lt;a href=&quot;https://blog.esciencecenter.nl/the-utopic-git-history-d44b81c09593&quot;&gt;The Utopic Git History&lt;/a&gt; (UGH). To refresh our memory, a simple definition of a UGH is&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Atomic git commits (smallest commit that completes the task)&lt;/li&gt;
&lt;li&gt;Passing tests&lt;/li&gt;
&lt;li&gt;Linear Git history&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In that post, I mentioned that the easiest way to achieve UGH is to squash a self-contained pull request into a single commit. Otherwise, you have to use more advanced git commands to achieve UGH. This blog post deals with that.&lt;/p&gt;
&lt;p&gt;The target audience for this post is Git users who want to learn intermediate and advanced commands that splice, merge, and fix commits. If you need a refresher on some of the concepts used, please take a look at the &lt;a href=&quot;https://blog.esciencecenter.nl/the-utopic-git-history-d44b81c09593&quot;&gt;animations in my previous blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The ideal way of achieving UGH is to write exactly what you have to write, and then commit that. This kind of insight is hard to come by when your task is large, so instead let’s focus on what happens in practice, which involves getting our hands dirty.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Meme. Left image shows dirty hands with a caption “My hands look like this” and right image shows git branches being transformed into linear git history with a caption “So my git history can look like this.”&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_w6RS2UcGCMtyvWSI2Eg7Ow-c5a1c936.CDnJLX_-_Z2uSccu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Getting your hands dirty. Left photo by Jeremy Bishop on Unsplash. Modifications by me.&lt;/p&gt;
&lt;h2 id=&quot;before-committing&quot;&gt;Before committing&lt;/h2&gt;
&lt;p&gt;The first thing that we can control is what to commit. So let’s assume that we got to a point where we have a lot of modifications because task A turned out to be too large and now we’re thinking of splitting it into A1 and A2 (maybe more).&lt;/p&gt;
&lt;p&gt;Here, &lt;code&gt;git add -p&lt;/code&gt; comes into play. &lt;code&gt;git add -p&lt;/code&gt; lets us add &lt;strong&gt;patches&lt;/strong&gt; of code separately. So if our file has modifications for tasks A1 and A2, we can add only the first one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If there is an untracked file that we want to selectively add, it can be included using &lt;code&gt;git add -N FILE&lt;/code&gt;. This will tell git to track the file, but it doesn’t stage it.&lt;/p&gt;
&lt;p&gt;When we run &lt;code&gt;git add -p FILES&lt;/code&gt;, we see something like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;diff &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Something&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Something&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Stage&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; this hunk [y,n,q,a,d,s,e,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pressing &lt;code&gt;?&lt;/code&gt; will show the help. There are four commands that matter a lot to us. The first two are y and n, for yes and no. If we say yes, the “hunk” (a piece of code shown in this diff) will be staged. Remember, when we &lt;code&gt;git commit&lt;/code&gt; (no &lt;code&gt;-a&lt;/code&gt; flag), the staged part of the code will be added to the commit. If we say no, then it just moves on to the next hunk.&lt;/p&gt;
&lt;p&gt;The third command is the best: s, for split. If the hunk that we see on the screen is too large, or if it involves parts A1 and A2, then we want to split it. Git will try to find a place to split this code and give you smaller hunks. Then we can decide whether to add or not those new smaller hunks individually.&lt;/p&gt;
&lt;p&gt;Split doesn’t always work, so what we can do instead is use the command e, for edit. Editing will open an editor, so if you don’t like Vim (the default), you can change it with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git config &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--local core.editor &quot;code --wait&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the command above, &lt;code&gt;code --wait&lt;/code&gt; will open VSCode. Change it to your preference. Also, you can configure it globally using &lt;code&gt;--global&lt;/code&gt; instead of &lt;code&gt;--local&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After running &lt;code&gt;git add -p&lt;/code&gt; and selecting the command e, we will get to the editor with the same diff open and some additional information.&lt;/p&gt;
&lt;p&gt;The first column of the hunk can be empty, to indicate that the code doesn’t change, &lt;code&gt;#&lt;/code&gt; to indicate a comment that will be ignored by git add, a &lt;code&gt;-&lt;/code&gt; to indicate that the line should be removed, and a &lt;code&gt;+&lt;/code&gt; to indicate a new line replacing the old one.&lt;/p&gt;
&lt;p&gt;Now, we can manually decide on each individual addition. Let’s look at an example:&lt;/p&gt;
&lt;p&gt;Our initial code is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, our task A1 is to rename y to p, and task A2 is to change all additions to subtractions.&lt;/p&gt;
&lt;p&gt;The resulting code after doing both tasks is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The diff, which we will see when we enter edit mode, is the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Manual hunk edit mode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Clearly, tasks A1 and A2 are mixed and can’t be split. So instead, we manually change the diff. Since we want only A1 applied, we change the diff to&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change &lt;code&gt;-w = x + 1&lt;/code&gt; to &lt;code&gt;[space]w = x + 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove line &lt;code&gt;+w = x - 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Move the two + lines one line up&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;+z = x - p&lt;/code&gt; to &lt;code&gt;+z = x + p&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please notice that the lines starting with a minus sign can’t be modified, because they must match with the current code. If you want to make modifications to a line that has a minus, look for the corresponding plus and change that instead. If there is no corresponding plus, it means that the line is simply being removed, so you can add a line with a plus yourself.&lt;/p&gt;
&lt;p&gt;Now, if we look at your git status, we will see the same file appearing in and out of the staged section. We can use &lt;code&gt;git diff --staged&lt;/code&gt; to check the result.&lt;/p&gt;
&lt;h2 id=&quot;oops-too-late-one-commit-with-multiple-tasks&quot;&gt;Oops, too late (one commit with multiple tasks)&lt;/h2&gt;
&lt;p&gt;Let’s say that we have one commit with multiple tasks, i.e., one commit that should be split into more than one.&lt;/p&gt;
&lt;p&gt;For instance, we might have spent 10 minutes meticulously editing what should be staged using the &lt;code&gt;git add -p&lt;/code&gt; command, when by mistake we use &lt;code&gt;git commit -a&lt;/code&gt; and add every unstaged modification in the commit as well, wasting all this work. Completely hypothetical, mind you.&lt;/p&gt;
&lt;p&gt;There is a quick way to “fix” this which is to run &lt;code&gt;git reset HEAD~1&lt;/code&gt;. This will remove the commit and go back to the modified state. To be clear, we don’t lose the modifications made in the commit, as they will be back into the modified state, but we lose the previously staged information in those 10 minutes of work.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;git reset HEAD~1&lt;/code&gt; command assumes that the latest commit is the one that we are fixing. If that is not the case, check the next session.&lt;/p&gt;
&lt;p&gt;As a rule, &lt;strong&gt;always back up your branch&lt;/strong&gt; whenever you run reset and rebase until you are confident that you can get yourself out of tricky situations. Backup, in this case, means creating a new branch, e.g., &lt;code&gt;git branch backup-some-name&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;too-many-commits&quot;&gt;Too many commits&lt;/h2&gt;
&lt;p&gt;Let’s say that we ended up making too many commits. For instance, we were trying to follow the idea above, but noticed some bugs that should be part of task A1, and ended up creating another commit to fix that. Or that we realized that we introduced a bug that had no test when doing A2.&lt;/p&gt;
&lt;p&gt;As an example, consider the following initial state of a file &lt;code&gt;main.py&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    z &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    w &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return w&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the following git history:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;hash00: Older stuff &lt;em&gt;← Where we are right now&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;hash01: Rename variable y to p&lt;/li&gt;
&lt;li&gt;hash02: Change + to -&lt;/li&gt;
&lt;li&gt;hash03: Rename y to p and change + to — in function &lt;code&gt;bar&lt;/code&gt; also&lt;/li&gt;
&lt;li&gt;hash04: Fix linting issue (add spaces around operators)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;hash01&lt;/code&gt; and &lt;code&gt;hash02&lt;/code&gt; commits are the ones we did in the previous sections. The &lt;code&gt;hash03&lt;/code&gt; commit is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the &lt;code&gt;hash04&lt;/code&gt; commit is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;     p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This git history is not great. We still only have two tasks (A1 and A2), but 4 commits. What we want to do is redistribute the work done in these 4 commits into 2 commits. For that, we use &lt;code&gt;git rebase -i&lt;/code&gt;, i.e., interactive rebase.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: There is an alternative to rebasing here, which is to run &lt;code&gt;reset hash00&lt;/code&gt;, so that we remove all the commits but none of the modifications. From there we will have to manually add the changes using &lt;code&gt;git add -p&lt;/code&gt; and then make individual commits. I prefer the rebase strategy. What are your thoughts about these two strategies?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The interactive rebase command allows us to reorder and squash commits, change the commit messages, and stop during rebasing to make additional changes (such as splitting older commits).&lt;/p&gt;
&lt;p&gt;The first thing that we need to do is find that git history. If you use a visual tool, you can just look at the graph. Otherwise, we can issue the command&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git log &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--graph --oneline&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will produce a graph of the commits, one per line, which should be easy to read. It should be something like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash04&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (feat_br) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash03&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash00&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (main) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Older&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This assumes that we branched out of &lt;code&gt;main&lt;/code&gt; into a branch called &lt;code&gt;feat_br&lt;/code&gt;. Now, to start rebasing, we can issue&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i main feat_br&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, it is just the normal rebase command, but now we add the &lt;code&gt;-i&lt;/code&gt; flag to have more options on how to rebase.&lt;/p&gt;
&lt;p&gt;This command should open an editor with the list of commits preceded by a keyword &lt;code&gt;pick&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash04 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the commit at &lt;code&gt;main&lt;/code&gt; is not included, as expected.&lt;/p&gt;
&lt;p&gt;What we can do now is change the order of these commits as we see fit and change the keyword to the action that we want. Notice that the order of the commits is top-to-bottom.&lt;/p&gt;
&lt;p&gt;The main options are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pick: Use this commit. It will be applied, and the message will be used.&lt;/li&gt;
&lt;li&gt;drop: Don’t use the commit. It will be lost.&lt;/li&gt;
&lt;li&gt;reword: Use this commit, but open the editor to modify the commit message.&lt;/li&gt;
&lt;li&gt;squash: Merge the contents of this commit in the previous commit and then open the editor for editing the commit message. By default, it appends the commit messages of squashed commits.&lt;/li&gt;
&lt;li&gt;fixup: Like squash, merge the contents into the previous commit, but ignore the message.&lt;/li&gt;
&lt;li&gt;edit: Use this commit and the message, but after the commit is done, stop so we can make edits.&lt;/li&gt;
&lt;li&gt;break: Use by itself in a new line. It will drop us in the terminal to do whatever we want.&lt;/li&gt;
&lt;li&gt;exec: Use by itself followed by a command. It will run the command, and if there is an error, drops us in the terminal to do whatever we want.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whenever we are dropped in the terminal during rebase, we can always issue &lt;code&gt;git rebase --abort&lt;/code&gt; to stop the rebase completely and go back to where we were.&lt;/p&gt;
&lt;p&gt;If we were dropped in the terminal because there is a problem, for instance, a conflict, then we must fix it.&lt;/p&gt;
&lt;p&gt;After fixing whatever caused us to be dropped into the terminal (check with &lt;code&gt;git status&lt;/code&gt; ) we have to use &lt;code&gt;git rebase --continue&lt;/code&gt; to continue rebasing.&lt;/p&gt;
&lt;p&gt;Going back to our example, the first thing that we’ll do is split the &lt;code&gt;hash03&lt;/code&gt; commit. To do that, we simply change we &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;edit&lt;/code&gt;, save and close.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;edit hash03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash04 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will drop us in the terminal with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Stopped&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at hash03&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p and change &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function bar also&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;You&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; can amend the commit now, with&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git commit &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--amend &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Once&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; you are satisfied with your changes, run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git rebase &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--continue&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we will use &lt;code&gt;reset&lt;/code&gt; to undo this single commit and add only the change for task A1.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git reset &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HEAD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git add &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make the first commit diff look like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the second looks like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def bar&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;     p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return p &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can run &lt;code&gt;git rebase --continue&lt;/code&gt; and &lt;code&gt;git log --graph --oneline&lt;/code&gt; again to obtain:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; newh03&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (feat_br) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; newh02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; newh01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash00&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (main) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Older&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the hashes changed only after we effectively rebased.&lt;/p&gt;
&lt;p&gt;Now, we will use &lt;code&gt;git rebase -i main feat_br&lt;/code&gt; again, but this time we will move things around and change &lt;code&gt;pick&lt;/code&gt; to &lt;code&gt;fixup&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We start with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick newh01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick newh02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick newh03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And change to&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fixup newh01 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pick hash02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fixup newh02 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fixing&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; task &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;A2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fixup newh03 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fix&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; linting issue (add spaces around operators)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will apply the first commit and then fix it, leaving only a single commit. Then, it will apply the second commit and fix it twice. None of these changes led to conflicts.&lt;/p&gt;
&lt;p&gt;At the end of this process, our log is&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; more02&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (feat_br) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Change&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; more01&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y to p&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hash00&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (main) &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Older&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stuff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, we have achieved UGH for this branch.&lt;/p&gt;
&lt;h2 id=&quot;splitting-a-branch-into-many-branches&quot;&gt;Splitting a branch into many branches&lt;/h2&gt;
&lt;p&gt;Now that we have two commits, one for each task, it makes sense to actually have two branches: one for each commit.&lt;/p&gt;
&lt;p&gt;Since the commits are atomic, this is actually very easy to do &lt;strong&gt;unless&lt;/strong&gt; the branches depend on each other.&lt;/p&gt;
&lt;p&gt;The first task is just the first commit in our case, so we only need to give it a branch name:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git branch feature_taskA more01&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, we are creating a branch called &lt;code&gt;feature_taskA&lt;/code&gt; at the commit with hash &lt;code&gt;more01&lt;/code&gt;. Push this branch&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git push &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;u origin feature_taskA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It can be reviewed and rebased.&lt;/p&gt;
&lt;p&gt;Now, let’s split into two situations.&lt;/p&gt;
&lt;h3 id=&quot;splitting-independent-branches&quot;&gt;Splitting independent branches&lt;/h3&gt;
&lt;p&gt;If the commits are independent, we just have so now where they start and rebase rooted there.&lt;/p&gt;
&lt;p&gt;Normally, we are rooted in main, as in our example above. So we can issue&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--onto=main feature_taskA feat_br&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, we are saying “Take all commits after &lt;code&gt;feature_taskA&lt;/code&gt; (exclusive) that are part of branch &lt;code&gt;feat_br&lt;/code&gt;, and reapply them on top of the branch &lt;code&gt;main&lt;/code&gt;.” We can use a hash instead of &lt;code&gt;main&lt;/code&gt;, if necessary.&lt;/p&gt;
&lt;p&gt;This can lead to conflicts, even if there is no real dependency between the commits. If the conflicts are significant, then it is better to treat them as dependents. The conflicts that appear here will reappear when we try to merge these two branches into main.&lt;/p&gt;
&lt;h3 id=&quot;splitting-dependent-branches&quot;&gt;Splitting dependent branches&lt;/h3&gt;
&lt;p&gt;If the branches are dependent, then we should actually wait until the first part is merged before rebasing.&lt;/p&gt;
&lt;p&gt;When the first part is merged (let’s assume with GitHub’s rebase), then we now have a new &lt;code&gt;main&lt;/code&gt;, with other commit hashes. In that case, we can simply issue a rebase and the commits that already appeared on the merged branch will be skipped, by default.&lt;/p&gt;
&lt;p&gt;However, this depends on configuration values, so it is safer to just use exactly the same commands as before, but don’t forget to update your main branch.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git fetch &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git merge &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--ff-only upstream/main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--onto=main feature_taskA feat_br&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In other words, the only difference between the independent and dependent cases is &lt;strong&gt;when&lt;/strong&gt; to rebase. If the branches are independent, you can split and push both, since they can be reviewed and merged independently. If the branches are dependent, then we wait until the first branch is merged and rebase after updating main.&lt;/p&gt;
&lt;h2 id=&quot;remote-changes&quot;&gt;Remote changes&lt;/h2&gt;
&lt;p&gt;The last thing to discuss is the changes that could be happening in the remotes while we’re making changes.&lt;/p&gt;
&lt;p&gt;Let’s assume in this section that we have two remotes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;upstream&lt;/code&gt;: Points to the main repo, e.g., the organization’s repo.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;origin&lt;/code&gt;: Points to our fork.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First of all, my preferred way to work is to make sure that my atomic commit is up to date with the remote branch. So first of all, I fetch everything, update &lt;code&gt;main&lt;/code&gt; with the fast-forward option, and &lt;strong&gt;branch from main&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git fetch &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--all&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git merge &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--ff-only upstream/main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the merge had conflicts, it means that we made commits to &lt;code&gt;main&lt;/code&gt;, and we shouldn’t. We fix this by creating the branch now and resetting main:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git switch main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git branch featureX &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; just creates, does not switch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git reset &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--hard upstream/main&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, after working on branch &lt;code&gt;featureX&lt;/code&gt;, we check for updates on &lt;code&gt;main &lt;/code&gt; again, using &lt;code&gt;fetch&lt;/code&gt; and &lt;code&gt;merge --ff-only&lt;/code&gt;. If there were any changes to main, we rebase after pushing:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git rebase main featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We might have conflicts, but since our branch is atomic, they should be few and far between.&lt;/p&gt;
&lt;p&gt;After rebasing, we push:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git push &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;u origin featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let’s say that we had to make changes because of the review. After making our changes, we use interactive rebase to make sure that the commits are atomic again. Our branch will not be in sync with the remote branch anymore, because the commits have changed (either in content or in hash).&lt;/p&gt;
&lt;p&gt;That means that we now have to force-push our branch:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git push &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--force featureX&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should be enough to update the pull request.&lt;/p&gt;
&lt;h3 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h3&gt;
&lt;p&gt;These commands should help you handle most git situations. They are not easy to master, so I hope that this post serves as a quick way to remember what each command does. Let us know what other Git needs you have.&lt;/p&gt;
&lt;p&gt;Be UGHly, my friend.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-barbara-veede/&quot;&gt;&lt;em&gt;Barbara Vreede&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-pablo-rodriguez-sanchez/&quot;&gt;&lt;em&gt;Pablo Rodríguez-Sánchez&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_w6RS2UcGCMtyvWSI2Eg7Ow-c5a1c936.CDnJLX_-.gif" medium="image"/><author>Abel Soares Siqueira</author></item><item><title>the orange3 data mining platform as a research tool</title><link>https://blog2.esciencecenter.nl/posts/2023-10-12---the-orange3-data-mining-platform-as-a-research-tool</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-10-12---the-orange3-data-mining-platform-as-a-research-tool</guid><description>&lt;h2 id=&quot;why-arent-more-ssh-researchers-using-and-extending-the-platform&quot;&gt;Why aren’t more SSH researchers using and extending the platform?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://orangedatamining.com/&quot;&gt;Orange&lt;/a&gt; is an open-source &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; -based &lt;a href=&quot;https://www.britannica.com/technology/data-structure&quot;&gt;data mining&lt;/a&gt; application with a graphical user interface (GUI). It allows people with no knowledge of programming to apply Machine Learning as well as advanced data processing, analysis, and visualization using a point-and-click, drag-and-drop interface. Those who have seen &lt;a href=&quot;https://scratch.mit.edu/&quot;&gt;Scratch&lt;/a&gt; will be familiar with this mode of interaction, although Orange is more advanced and is used for data mining, rather than educational programming. The following screenshot shows what a typical Orange &lt;a href=&quot;https://orangedatamining.com/workflows/&quot;&gt;workflow&lt;/a&gt; looks like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Screenshot of the Orange3 interface. To the left of screen is the list of loaded add-ons (Toolboxes for data mining). To the right of screen is an example data mining workflow I created consisting of three Orange widgets: one to load data, one to display it in a table format and one for visualising it.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;793&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_P63Kn6BcFaxp2mzdYM-KGw-3d971242.BA8M75pr_Z1sj8eG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of an example data mining workflow in Orange3&lt;/p&gt;
&lt;p&gt;The three small circles labeled ‘File’, ‘Data Table’, and ‘Scatter Plot’ in the image above, are called Orange &lt;a href=&quot;https://docs.biolab.si/orange/2/widgets/rst/index.html&quot;&gt;widgets&lt;/a&gt;. They are the basic building blocks of a data analysis workflow (or pipeline) in Orange. Each widget is a software unit that performs some sort of data processing, analysis, or visualization and potentially has a set of inputs and outputs. You can connect the outputs of some widgets to the inputs of others to create a chain of processing and analysis operations. A great feature of Orange is its extensibility. There are loads of custom plugins for Orange (called &lt;em&gt;add-ons&lt;/em&gt;) developed by researchers and the Orange user community. Add-ons usually comprise multiple widgets. Two mature and extensively used Orange add-ons are &lt;a href=&quot;https://orange3-text.readthedocs.io/en/latest/&quot;&gt;Orange-Text&lt;/a&gt; and &lt;a href=&quot;https://orange3-network.readthedocs.io/en/latest/&quot;&gt;Network&lt;/a&gt; which are used for &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_theory&quot;&gt;network analysis&lt;/a&gt; respectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Story Navigator: a custom Orange add-on I am developing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I am currently in the process of developing an add-on as part of a project with researchers at the &lt;a href=&quot;https://www.utwente.nl/&quot;&gt;University of Twente&lt;/a&gt; in the Netherlands. The add-on is called the &lt;a href=&quot;https://github.com/navigating-stories/orange-story-navigator&quot;&gt;Story Navigator&lt;/a&gt;. The aim of the Story Navigator is to enable computer-aided analysis of written stories for students and researchers who study &lt;a href=&quot;https://en.wikipedia.org/wiki/Narrative_psychology&quot;&gt;narrative psychology&lt;/a&gt;. The add-on has several widgets to analyse different aspects of a story. It uses a combination of &lt;a href=&quot;https://encyclopediaofmath.org/wiki/Natural_language_processing&quot;&gt;natural language processing&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt;, and general data analysis techniques to implement theories in narrative psychology, such as &lt;a href=&quot;https://natureofwriting.com/courses/introduction-to-rhetoric/lessons/burkes-pentad/&quot;&gt;Burke’s pentad&lt;/a&gt;. Here’s a screen:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;695&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_bzPwFl1nsKeO-G9zDQzSpg-a1858653.Av62JrBZ_ZNscwQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the Story Navigator add-on (not yet released) for Orange3.&lt;/p&gt;
&lt;p&gt;The add-on works by first importing textual stories into the workflow using the existing &lt;a href=&quot;https://orangedatamining.com/widget-catalog/text-mining/importdocuments/&quot;&gt;“Import Documents”&lt;/a&gt; widget from the Orange-Text add-on. Thereafter the researcher can choose a widget from the add-on for analysing some aspects of the imported stories. The actor analysis widget, for example, highlights potential characters in the stories; shows which kinds of actions (verbs) the characters are associated with; and calculates different measures for how central specific characters are to the stories.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;958&quot; height=&quot;578&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_JXuPlOl9CDyxWFD10paxgA-03e51f84.DYhSNI_J_Z2fQd8z.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Quantitative story analysis widgets from the Story Navigator add-on for Orange3.&lt;/p&gt;
&lt;p&gt;While it did take some time to develop the widgets for this add-on, what surprised me is that it took me only about two hours, from scratch, with no prior knowledge of Orange, to develop my first widget that showed up in the Orange3 interface when I started it up. Granted, the widget did not do anything except display. But the return on my two-hour investment was that I could now free up my creativity to develop whatever functionality I wanted in the widget, without having to create my own GUI. In doing so, I got to take advantage of a myriad of benefits including being able to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make my add-on available for anyone to use regardless of their programming knowledge&lt;/li&gt;
&lt;li&gt;Receive development and usage feedback from an existing Orange community about my add-on (without having to further promote the add-on or build another community myself from scratch)&lt;/li&gt;
&lt;li&gt;Demo my plugin to anyone, thanks to the GUI&lt;/li&gt;
&lt;li&gt;Share data analyses made with my add-on with other Orange users — enabling reproducibility (currently &lt;a href=&quot;https://www.nature.com/articles/d41586-019-00067-3&quot;&gt;undergoing a crisis&lt;/a&gt; in science)&lt;/li&gt;
&lt;li&gt;Forget about writing installation instructions — they’re already &lt;a href=&quot;https://orangedatamining.com/blog/2012/11/30/the-easy-way-to-install-add-ons/&quot;&gt;here&lt;/a&gt;!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Despite what some readers might think at this point, I am not an Orange evangelist. In fact, I am not swooning over the capabilities and potential of Orange specifically. Orange does have competing platforms that try to do similar things such as &lt;a href=&quot;https://www.knime.com/&quot;&gt;KNIME&lt;/a&gt; and &lt;a href=&quot;https://www.cs.waikato.ac.nz/ml/weka/&quot;&gt;WEKA&lt;/a&gt; which are both &lt;a href=&quot;https://www.java.com/en/&quot;&gt;Java&lt;/a&gt; -based and therefore inherit some concerns due to &lt;a href=&quot;https://www.tiobe.com/tiobe-index/&quot;&gt;Java’s declining popularity&lt;/a&gt;. Orange itself also has some clear disadvantages, not least of which are the &lt;a href=&quot;https://orangedatamining.com/blog/2012/01/03/parallel-orange/&quot;&gt;scalability issues&lt;/a&gt; and the &lt;a href=&quot;https://orange3-example-addon.readthedocs.io/en/latest/&quot;&gt;add-on development documentation&lt;/a&gt; (the latter is not very accessible for less experienced developers).&lt;/p&gt;
&lt;p&gt;But the point I am trying to make is that I am mostly just inspired by the philosophy behind platforms like these: people coming together to develop and share an extensible “workbench-style” software platform with a user-friendly interface. When I refer to software I don’t mean software that has a highly niche purpose, but software that aims to be an ever-evolving toolbox with the potential to address a multitude of research problems. Where your own creativity is the only limit in terms of contributing to it. Where the knowledge barriers to be able to contribute to it are super low, and where there are no qualifying criteria for those who can experience and benefit from the contributions.&lt;/p&gt;
&lt;p&gt;Orange was developed at the &lt;a href=&quot;https://fri.uni-lj.si/en/laboratory/biolab&quot;&gt;Laboratory for Bioinformatics&lt;/a&gt; at the University of Ljubljana. It makes sense then that most of its user base uses it for data mining in &lt;a href=&quot;https://www.britannica.com/science/bioinformatics&quot;&gt;bioinformatics&lt;/a&gt; (see for instance &lt;a href=&quot;https://www.mdpi.com/2076-3417/11/5/2218&quot;&gt;this study&lt;/a&gt; using Orange for early diagnosis of diabetes). But Orange itself is not at all designed to be domain-specific. Its add-ons and widgets are designed for domain-agnostic data mining (&lt;a href=&quot;https://www.mdpi.com/2076-3417/10/11/3894&quot;&gt;here’s a study&lt;/a&gt; using Orange to predict student performance in higher education). This begs the question, why aren’t more researchers in the Social Sciences and Humanities using it, extending it, or building similar platforms?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What the popular video game&lt;/strong&gt; &lt;a href=&quot;https://elderscrolls.bethesda.net/en/&quot;&gt;&lt;strong&gt;Elder Scrolls&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;has to do with Orange&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bethesda.net/dashboard&quot;&gt;Bethesda Softworks&lt;/a&gt; is a US-based video game development company that is famous for its many franchises, one of which is “ &lt;a href=&quot;https://elderscrolls.bethesda.net/en/&quot;&gt;Elder Scrolls&lt;/a&gt; ”. The games in this franchise are “ &lt;a href=&quot;https://en.wikipedia.org/wiki/Role-playing_game&quot;&gt;RPGs&lt;/a&gt; ” that put the player in control of a character from a fictional fantasy world with the goal to… wait for it… save the world from destruction (if you’re new to the term RPGs imagine a video game based on &lt;a href=&quot;https://www.hbo.com/game-of-thrones&quot;&gt;Game of Thrones&lt;/a&gt; and you’ll get the gist). In 2002, Bethesda released its third installment of Elder Scrolls, called “ &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Elder_Scrolls_III:_Morrowind&quot;&gt;Morrowind&lt;/a&gt; ”. The super interesting part is that they also released software called the &lt;a href=&quot;https://cs.elderscrolls.com/index.php?title=Main_Page&quot;&gt;Elder Scrolls Construction Set&lt;/a&gt; alongside the game. This software allowed players to make customizations to their own copy of the game. They could do things such as create new clothing, buildings, and other items; create their own character voices; make new quests, and customize the color of the sky. These modifications (&lt;em&gt;mods&lt;/em&gt; as they are now commonly referred to) vary in terms of how much software literacy is required in order to build them, but many of them require no more knowledge than being able to install a program and click a few buttons.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;978&quot; height=&quot;513&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_7pZdxrP9AKjQ3F7p-911a47a7.D7mMaqOF_ZoyG2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fancy introducing Spiderman-suited creatures crawling around a medieval town into your video-gaming experience? Well, someone has already created a mod for this in Skyrim.&lt;/p&gt;
&lt;p&gt;Twenty years later, and Bethesda has become known and celebrated for giving its customers the freedom to customize their gaming experience. &lt;a href=&quot;https://www.nexusmods.com/&quot;&gt;Nexusmods&lt;/a&gt; is one of the prominent hubs for hosting large collections of player-created mods for games by Bethesda and other major video game companies. I quote some jaw-dropping statistics from this site here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We host 477,145 mods for 2,342 games from 118,005 authors serving 41,902,274 members with 8,184,840,124 downloads to date.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In academia, terms like “outputs”, “impact”, “community building” and “community engagement” are often bandied about as performance goals and metrics for work. However, despite their purported importance, these terms are hard to define and measure. But when I look at those numbers, I feel like we don’t need unambiguous definitions for those terms in order to verify that the mod concept ticks all those boxes and then some.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;507&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SayaBHWxNn7HCpmaU0YmQA-a7da4685.D8UAVMwc_Z1a8U89.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Nexusmods demonstrates that the mod concept is a winner.&lt;/p&gt;
&lt;p&gt;“Okay Kody, what does this all have to do with Orange?”, you may ask. Well, in some ways there are parallels in this story to the concept of Orange as a software platform.&lt;/p&gt;
&lt;p&gt;First, there is a &lt;em&gt;product that many people enjoy&lt;/em&gt; (or find useful). In Bethesda’s case, it is the “vanilla” Elder Scrolls games. In Orange’s case, it is a data mining platform which is a generic tool that is useful regardless of the research domain and data. The GUI aspect of Orange also opens it up to a much larger user base (not just a small group of researchers with development experience working in a niche field).&lt;/p&gt;
&lt;p&gt;Second, there is the &lt;em&gt;enabling of customization.&lt;/em&gt; In Bethesda’s case, it is the provision of customization software such as the &lt;a href=&quot;https://store.steampowered.com/app/1946180/Skyrim_Special_Edition_Creation_Kit/&quot;&gt;Skyrim Creation Kit&lt;/a&gt;; in the case of Orange, it is the release of the code under an open-source license with reusable example code and plugin-writing tutorials.&lt;/p&gt;
&lt;p&gt;Thirdly, and what I find to be the most critical, is &lt;em&gt;making it easy to customize.&lt;/em&gt; In Bethesda’s case, they have made user-friendly software that does not require extremely specialized skills to use. Almost anyone can create a mod. In Orange’s case, you still need to know how to program to develop add-ons. But you don’t need advanced knowledge of the GUI frameworks that Orange uses — &lt;a href=&quot;https://en.wikipedia.org/wiki/Qt_(software)&quot;&gt;Qt&lt;/a&gt; and &lt;a href=&quot;https://wiki.python.org/moin/PyQt&quot;&gt;PyQt&lt;/a&gt;. In other words, if you know how to create any kind of computational script or software in Python, you can easily create an Orange widget to “house” or “wrap” its functionality. Furthermore, others, regardless of their technical nous, will be able to use it and “chain” your widget with other software in an Orange workflow.&lt;/p&gt;
&lt;p&gt;What I have experienced and want to emphasize, is that plugging your software into existing platforms like Orange (especially ones that have a nice GUI) can increase its visibility and usage, over publishing it solely in a code repository. Decently designed GUIs help users to more quickly understand what your software does which goes a long way to maximizing its value. Platforms like Orange provide a mechanism by which developers can take advantage of these GUI benefits “for free” (well, not really for free, but with &lt;em&gt;much&lt;/em&gt; less time investment than building and designing GUIs from scratch). It frees them up to use their creativity to solve research problems through widget development; it exposes their software to a much wider audience; and it allows users to interact with their software in a more intuitive way.&lt;/p&gt;
&lt;p&gt;In short, platforms like Orange can be extremely useful both for researchers who want to quickly apply computational analyses in the SSH fields (without writing code) and for developers who want to increase the usability, visibility, and sustainability of their software. While it does, to some extent, tie the success of your software to the success of Orange, you are not “putting all your eggs in one basket”. Due to the modularity and already-in-place Python package structure of Orange add-ons and widgets, you can very easily strip the GUI out of your code and release your work as a stand-alone package, or migrate it to another platform.&lt;/p&gt;
&lt;p&gt;If you are interested, my colleague &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-ji-qi/&quot;&gt;Ji Qi&lt;/a&gt; has written a &lt;a href=&quot;https://medium.com/escience-center/how-easy-it-can-be-to-whip-up-your-own-orange3-widget-a-chatbot-adventure-with-huggingchat-ded982ac0ef4&quot;&gt;post&lt;/a&gt; about how to get started with Orange add-on development — be sure to check it out!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take home messages&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Orange is an open-source extensible data mining platform that is usable by people with little to no technical experience. If you are a researcher in SSH consider using it for your research. If it doesn’t have a feature you need, &lt;a href=&quot;https://github.com/biolab/orange3/issues&quot;&gt;ask the developers if they can add it as a default feature to Orange&lt;/a&gt;. If they can’t add it, and if you or a colleague has Python experience, consider &lt;a href=&quot;http://jiblogpost/&quot;&gt;creating a custom add-on&lt;/a&gt;. It is surprisingly quick and easy to create one if you know a bit of Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1903.06039.pdf&quot;&gt;Research software sustainability is a challenge&lt;/a&gt;. Building and maintaining communities around the development of research software is hard. Don’t let your software become JAG (&lt;strong&gt;J&lt;/strong&gt; ust- &lt;strong&gt;A&lt;/strong&gt; nother- &lt;strong&gt;G&lt;/strong&gt; ithub repo). Take inspiration for how to avoid this from platforms like Orange. This does not mean that you need to create a graphical user interface for your software. It means: &lt;em&gt;find a home for your software&lt;/em&gt; or &lt;em&gt;find an existing toolbox in which to integrate your software, before creating your own toolbox&lt;/em&gt;. Integrating into existing platforms or packages will probably increase its usage and visibility over publishing as a stand-alone item.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #1:&lt;/strong&gt; From the start, consider building software that solves &lt;em&gt;generic&lt;/em&gt; problems in your field. i.e., problems that are shared by others in the field as well, rather than for highly specialized use cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #2:&lt;/strong&gt; Make your software easy to use by as many &lt;em&gt;types&lt;/em&gt; of people as possible. Not just for experienced developers. Also, ensure that someone can rapidly understand what your software does.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #3:&lt;/strong&gt; Make it easy for as many people as possible to customize and extend your software.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Thu, 12 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;why-arent-more-ssh-researchers-using-and-extending-the-platform&quot;&gt;Why aren’t more SSH researchers using and extending the platform?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://orangedatamining.com/&quot;&gt;Orange&lt;/a&gt; is an open-source &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; -based &lt;a href=&quot;https://www.britannica.com/technology/data-structure&quot;&gt;data mining&lt;/a&gt; application with a graphical user interface (GUI). It allows people with no knowledge of programming to apply Machine Learning as well as advanced data processing, analysis, and visualization using a point-and-click, drag-and-drop interface. Those who have seen &lt;a href=&quot;https://scratch.mit.edu/&quot;&gt;Scratch&lt;/a&gt; will be familiar with this mode of interaction, although Orange is more advanced and is used for data mining, rather than educational programming. The following screenshot shows what a typical Orange &lt;a href=&quot;https://orangedatamining.com/workflows/&quot;&gt;workflow&lt;/a&gt; looks like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Screenshot of the Orange3 interface. To the left of screen is the list of loaded add-ons (Toolboxes for data mining). To the right of screen is an example data mining workflow I created consisting of three Orange widgets: one to load data, one to display it in a table format and one for visualising it.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;793&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_P63Kn6BcFaxp2mzdYM-KGw-3d971242.BA8M75pr_Z1sj8eG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of an example data mining workflow in Orange3&lt;/p&gt;
&lt;p&gt;The three small circles labeled ‘File’, ‘Data Table’, and ‘Scatter Plot’ in the image above, are called Orange &lt;a href=&quot;https://docs.biolab.si/orange/2/widgets/rst/index.html&quot;&gt;widgets&lt;/a&gt;. They are the basic building blocks of a data analysis workflow (or pipeline) in Orange. Each widget is a software unit that performs some sort of data processing, analysis, or visualization and potentially has a set of inputs and outputs. You can connect the outputs of some widgets to the inputs of others to create a chain of processing and analysis operations. A great feature of Orange is its extensibility. There are loads of custom plugins for Orange (called &lt;em&gt;add-ons&lt;/em&gt;) developed by researchers and the Orange user community. Add-ons usually comprise multiple widgets. Two mature and extensively used Orange add-ons are &lt;a href=&quot;https://orange3-text.readthedocs.io/en/latest/&quot;&gt;Orange-Text&lt;/a&gt; and &lt;a href=&quot;https://orange3-network.readthedocs.io/en/latest/&quot;&gt;Network&lt;/a&gt; which are used for &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Network_theory&quot;&gt;network analysis&lt;/a&gt; respectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Story Navigator: a custom Orange add-on I am developing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I am currently in the process of developing an add-on as part of a project with researchers at the &lt;a href=&quot;https://www.utwente.nl/&quot;&gt;University of Twente&lt;/a&gt; in the Netherlands. The add-on is called the &lt;a href=&quot;https://github.com/navigating-stories/orange-story-navigator&quot;&gt;Story Navigator&lt;/a&gt;. The aim of the Story Navigator is to enable computer-aided analysis of written stories for students and researchers who study &lt;a href=&quot;https://en.wikipedia.org/wiki/Narrative_psychology&quot;&gt;narrative psychology&lt;/a&gt;. The add-on has several widgets to analyse different aspects of a story. It uses a combination of &lt;a href=&quot;https://encyclopediaofmath.org/wiki/Natural_language_processing&quot;&gt;natural language processing&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Text_mining&quot;&gt;text mining&lt;/a&gt;, and general data analysis techniques to implement theories in narrative psychology, such as &lt;a href=&quot;https://natureofwriting.com/courses/introduction-to-rhetoric/lessons/burkes-pentad/&quot;&gt;Burke’s pentad&lt;/a&gt;. Here’s a screen:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;695&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_bzPwFl1nsKeO-G9zDQzSpg-a1858653.Av62JrBZ_ZNscwQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the Story Navigator add-on (not yet released) for Orange3.&lt;/p&gt;
&lt;p&gt;The add-on works by first importing textual stories into the workflow using the existing &lt;a href=&quot;https://orangedatamining.com/widget-catalog/text-mining/importdocuments/&quot;&gt;“Import Documents”&lt;/a&gt; widget from the Orange-Text add-on. Thereafter the researcher can choose a widget from the add-on for analysing some aspects of the imported stories. The actor analysis widget, for example, highlights potential characters in the stories; shows which kinds of actions (verbs) the characters are associated with; and calculates different measures for how central specific characters are to the stories.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;958&quot; height=&quot;578&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_JXuPlOl9CDyxWFD10paxgA-03e51f84.DYhSNI_J_Z2fQd8z.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Quantitative story analysis widgets from the Story Navigator add-on for Orange3.&lt;/p&gt;
&lt;p&gt;While it did take some time to develop the widgets for this add-on, what surprised me is that it took me only about two hours, from scratch, with no prior knowledge of Orange, to develop my first widget that showed up in the Orange3 interface when I started it up. Granted, the widget did not do anything except display. But the return on my two-hour investment was that I could now free up my creativity to develop whatever functionality I wanted in the widget, without having to create my own GUI. In doing so, I got to take advantage of a myriad of benefits including being able to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make my add-on available for anyone to use regardless of their programming knowledge&lt;/li&gt;
&lt;li&gt;Receive development and usage feedback from an existing Orange community about my add-on (without having to further promote the add-on or build another community myself from scratch)&lt;/li&gt;
&lt;li&gt;Demo my plugin to anyone, thanks to the GUI&lt;/li&gt;
&lt;li&gt;Share data analyses made with my add-on with other Orange users — enabling reproducibility (currently &lt;a href=&quot;https://www.nature.com/articles/d41586-019-00067-3&quot;&gt;undergoing a crisis&lt;/a&gt; in science)&lt;/li&gt;
&lt;li&gt;Forget about writing installation instructions — they’re already &lt;a href=&quot;https://orangedatamining.com/blog/2012/11/30/the-easy-way-to-install-add-ons/&quot;&gt;here&lt;/a&gt;!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Despite what some readers might think at this point, I am not an Orange evangelist. In fact, I am not swooning over the capabilities and potential of Orange specifically. Orange does have competing platforms that try to do similar things such as &lt;a href=&quot;https://www.knime.com/&quot;&gt;KNIME&lt;/a&gt; and &lt;a href=&quot;https://www.cs.waikato.ac.nz/ml/weka/&quot;&gt;WEKA&lt;/a&gt; which are both &lt;a href=&quot;https://www.java.com/en/&quot;&gt;Java&lt;/a&gt; -based and therefore inherit some concerns due to &lt;a href=&quot;https://www.tiobe.com/tiobe-index/&quot;&gt;Java’s declining popularity&lt;/a&gt;. Orange itself also has some clear disadvantages, not least of which are the &lt;a href=&quot;https://orangedatamining.com/blog/2012/01/03/parallel-orange/&quot;&gt;scalability issues&lt;/a&gt; and the &lt;a href=&quot;https://orange3-example-addon.readthedocs.io/en/latest/&quot;&gt;add-on development documentation&lt;/a&gt; (the latter is not very accessible for less experienced developers).&lt;/p&gt;
&lt;p&gt;But the point I am trying to make is that I am mostly just inspired by the philosophy behind platforms like these: people coming together to develop and share an extensible “workbench-style” software platform with a user-friendly interface. When I refer to software I don’t mean software that has a highly niche purpose, but software that aims to be an ever-evolving toolbox with the potential to address a multitude of research problems. Where your own creativity is the only limit in terms of contributing to it. Where the knowledge barriers to be able to contribute to it are super low, and where there are no qualifying criteria for those who can experience and benefit from the contributions.&lt;/p&gt;
&lt;p&gt;Orange was developed at the &lt;a href=&quot;https://fri.uni-lj.si/en/laboratory/biolab&quot;&gt;Laboratory for Bioinformatics&lt;/a&gt; at the University of Ljubljana. It makes sense then that most of its user base uses it for data mining in &lt;a href=&quot;https://www.britannica.com/science/bioinformatics&quot;&gt;bioinformatics&lt;/a&gt; (see for instance &lt;a href=&quot;https://www.mdpi.com/2076-3417/11/5/2218&quot;&gt;this study&lt;/a&gt; using Orange for early diagnosis of diabetes). But Orange itself is not at all designed to be domain-specific. Its add-ons and widgets are designed for domain-agnostic data mining (&lt;a href=&quot;https://www.mdpi.com/2076-3417/10/11/3894&quot;&gt;here’s a study&lt;/a&gt; using Orange to predict student performance in higher education). This begs the question, why aren’t more researchers in the Social Sciences and Humanities using it, extending it, or building similar platforms?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What the popular video game&lt;/strong&gt; &lt;a href=&quot;https://elderscrolls.bethesda.net/en/&quot;&gt;&lt;strong&gt;Elder Scrolls&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;has to do with Orange&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://bethesda.net/dashboard&quot;&gt;Bethesda Softworks&lt;/a&gt; is a US-based video game development company that is famous for its many franchises, one of which is “ &lt;a href=&quot;https://elderscrolls.bethesda.net/en/&quot;&gt;Elder Scrolls&lt;/a&gt; ”. The games in this franchise are “ &lt;a href=&quot;https://en.wikipedia.org/wiki/Role-playing_game&quot;&gt;RPGs&lt;/a&gt; ” that put the player in control of a character from a fictional fantasy world with the goal to… wait for it… save the world from destruction (if you’re new to the term RPGs imagine a video game based on &lt;a href=&quot;https://www.hbo.com/game-of-thrones&quot;&gt;Game of Thrones&lt;/a&gt; and you’ll get the gist). In 2002, Bethesda released its third installment of Elder Scrolls, called “ &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Elder_Scrolls_III:_Morrowind&quot;&gt;Morrowind&lt;/a&gt; ”. The super interesting part is that they also released software called the &lt;a href=&quot;https://cs.elderscrolls.com/index.php?title=Main_Page&quot;&gt;Elder Scrolls Construction Set&lt;/a&gt; alongside the game. This software allowed players to make customizations to their own copy of the game. They could do things such as create new clothing, buildings, and other items; create their own character voices; make new quests, and customize the color of the sky. These modifications (&lt;em&gt;mods&lt;/em&gt; as they are now commonly referred to) vary in terms of how much software literacy is required in order to build them, but many of them require no more knowledge than being able to install a program and click a few buttons.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;978&quot; height=&quot;513&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_7pZdxrP9AKjQ3F7p-911a47a7.D7mMaqOF_ZoyG2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fancy introducing Spiderman-suited creatures crawling around a medieval town into your video-gaming experience? Well, someone has already created a mod for this in Skyrim.&lt;/p&gt;
&lt;p&gt;Twenty years later, and Bethesda has become known and celebrated for giving its customers the freedom to customize their gaming experience. &lt;a href=&quot;https://www.nexusmods.com/&quot;&gt;Nexusmods&lt;/a&gt; is one of the prominent hubs for hosting large collections of player-created mods for games by Bethesda and other major video game companies. I quote some jaw-dropping statistics from this site here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We host 477,145 mods for 2,342 games from 118,005 authors serving 41,902,274 members with 8,184,840,124 downloads to date.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In academia, terms like “outputs”, “impact”, “community building” and “community engagement” are often bandied about as performance goals and metrics for work. However, despite their purported importance, these terms are hard to define and measure. But when I look at those numbers, I feel like we don’t need unambiguous definitions for those terms in order to verify that the mod concept ticks all those boxes and then some.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;507&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SayaBHWxNn7HCpmaU0YmQA-a7da4685.D8UAVMwc_Z1a8U89.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Nexusmods demonstrates that the mod concept is a winner.&lt;/p&gt;
&lt;p&gt;“Okay Kody, what does this all have to do with Orange?”, you may ask. Well, in some ways there are parallels in this story to the concept of Orange as a software platform.&lt;/p&gt;
&lt;p&gt;First, there is a &lt;em&gt;product that many people enjoy&lt;/em&gt; (or find useful). In Bethesda’s case, it is the “vanilla” Elder Scrolls games. In Orange’s case, it is a data mining platform which is a generic tool that is useful regardless of the research domain and data. The GUI aspect of Orange also opens it up to a much larger user base (not just a small group of researchers with development experience working in a niche field).&lt;/p&gt;
&lt;p&gt;Second, there is the &lt;em&gt;enabling of customization.&lt;/em&gt; In Bethesda’s case, it is the provision of customization software such as the &lt;a href=&quot;https://store.steampowered.com/app/1946180/Skyrim_Special_Edition_Creation_Kit/&quot;&gt;Skyrim Creation Kit&lt;/a&gt;; in the case of Orange, it is the release of the code under an open-source license with reusable example code and plugin-writing tutorials.&lt;/p&gt;
&lt;p&gt;Thirdly, and what I find to be the most critical, is &lt;em&gt;making it easy to customize.&lt;/em&gt; In Bethesda’s case, they have made user-friendly software that does not require extremely specialized skills to use. Almost anyone can create a mod. In Orange’s case, you still need to know how to program to develop add-ons. But you don’t need advanced knowledge of the GUI frameworks that Orange uses — &lt;a href=&quot;https://en.wikipedia.org/wiki/Qt_(software)&quot;&gt;Qt&lt;/a&gt; and &lt;a href=&quot;https://wiki.python.org/moin/PyQt&quot;&gt;PyQt&lt;/a&gt;. In other words, if you know how to create any kind of computational script or software in Python, you can easily create an Orange widget to “house” or “wrap” its functionality. Furthermore, others, regardless of their technical nous, will be able to use it and “chain” your widget with other software in an Orange workflow.&lt;/p&gt;
&lt;p&gt;What I have experienced and want to emphasize, is that plugging your software into existing platforms like Orange (especially ones that have a nice GUI) can increase its visibility and usage, over publishing it solely in a code repository. Decently designed GUIs help users to more quickly understand what your software does which goes a long way to maximizing its value. Platforms like Orange provide a mechanism by which developers can take advantage of these GUI benefits “for free” (well, not really for free, but with &lt;em&gt;much&lt;/em&gt; less time investment than building and designing GUIs from scratch). It frees them up to use their creativity to solve research problems through widget development; it exposes their software to a much wider audience; and it allows users to interact with their software in a more intuitive way.&lt;/p&gt;
&lt;p&gt;In short, platforms like Orange can be extremely useful both for researchers who want to quickly apply computational analyses in the SSH fields (without writing code) and for developers who want to increase the usability, visibility, and sustainability of their software. While it does, to some extent, tie the success of your software to the success of Orange, you are not “putting all your eggs in one basket”. Due to the modularity and already-in-place Python package structure of Orange add-ons and widgets, you can very easily strip the GUI out of your code and release your work as a stand-alone package, or migrate it to another platform.&lt;/p&gt;
&lt;p&gt;If you are interested, my colleague &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-ji-qi/&quot;&gt;Ji Qi&lt;/a&gt; has written a &lt;a href=&quot;https://medium.com/escience-center/how-easy-it-can-be-to-whip-up-your-own-orange3-widget-a-chatbot-adventure-with-huggingchat-ded982ac0ef4&quot;&gt;post&lt;/a&gt; about how to get started with Orange add-on development — be sure to check it out!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take home messages&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Orange is an open-source extensible data mining platform that is usable by people with little to no technical experience. If you are a researcher in SSH consider using it for your research. If it doesn’t have a feature you need, &lt;a href=&quot;https://github.com/biolab/orange3/issues&quot;&gt;ask the developers if they can add it as a default feature to Orange&lt;/a&gt;. If they can’t add it, and if you or a colleague has Python experience, consider &lt;a href=&quot;http://jiblogpost/&quot;&gt;creating a custom add-on&lt;/a&gt;. It is surprisingly quick and easy to create one if you know a bit of Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/pdf/1903.06039.pdf&quot;&gt;Research software sustainability is a challenge&lt;/a&gt;. Building and maintaining communities around the development of research software is hard. Don’t let your software become JAG (&lt;strong&gt;J&lt;/strong&gt; ust- &lt;strong&gt;A&lt;/strong&gt; nother- &lt;strong&gt;G&lt;/strong&gt; ithub repo). Take inspiration for how to avoid this from platforms like Orange. This does not mean that you need to create a graphical user interface for your software. It means: &lt;em&gt;find a home for your software&lt;/em&gt; or &lt;em&gt;find an existing toolbox in which to integrate your software, before creating your own toolbox&lt;/em&gt;. Integrating into existing platforms or packages will probably increase its usage and visibility over publishing as a stand-alone item.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #1:&lt;/strong&gt; From the start, consider building software that solves &lt;em&gt;generic&lt;/em&gt; problems in your field. i.e., problems that are shared by others in the field as well, rather than for highly specialized use cases.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #2:&lt;/strong&gt; Make your software easy to use by as many &lt;em&gt;types&lt;/em&gt; of people as possible. Not just for experienced developers. Also, ensure that someone can rapidly understand what your software does.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inspiration point #3:&lt;/strong&gt; Make it easy for as many people as possible to customize and extend your software.&lt;/li&gt;
&lt;/ol&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_P63Kn6BcFaxp2mzdYM-KGw-3d971242.BA8M75pr.png" medium="image"/><author>Kody Moodley</author></item><item><title>Analysis-ready climate data with ESMValCore</title><link>https://blog2.esciencecenter.nl/posts/2023-10-05---analysis-ready-climate-data-with-esmvalcore</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-10-05---analysis-ready-climate-data-with-esmvalcore</guid><description>&lt;h2 id=&quot;the-easy-ipcc-blog-done-differently&quot;&gt;&lt;strong&gt;The “Easy IPCC” blog done differently&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Co-authored by &lt;a href=&quot;https://www.esciencecenter.nl/team/bouwe-andela-msc/&quot;&gt;Bouwe Andela&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://medium.com/pangeo/easy-ipcc-part-1-multi-model-datatree-469b87cf9114&quot;&gt;recent blog post&lt;/a&gt;, Tom Nicholas presented a nice walkthrough of reproducing a famous IPCC figure with &lt;code&gt;[xarray-datatree](https://xarray-datatree.readthedocs.io/en/latest/)&lt;/code&gt;. Here, we attempt to achieve the same with ESMValCore — the workflow engine that powers the more widely known &lt;a href=&quot;http://docs.esmvaltool.org/&quot;&gt;ESMValTool&lt;/a&gt;. Both xarray-datatree and ESMValCore facilitate the analysis of large climate datasets, but our approach is quite different. For example, xarray-datatree tries to facilitate any hierarchical file structure (more generic), whereas ESMValCore focuses on facilitating CMIP, or CMIP-like data only (more specific, thus tailored). Seeing them side by side is food for thought.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;770&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-75688b5f.B_CK0meh_Z1NGFQd.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;“&lt;/em&gt;&lt;a href=&quot;https://github.com/zarr-developers/zarr-illustrations-falk-2022/blob/main/1200dpi/kits-deluge-1200dpi.png&quot;&gt;&lt;em&gt;Adam uploads&lt;/em&gt;&lt;/a&gt;*” by &lt;em&gt;&lt;a href=&quot;https://twitter.com/DrHenningFalk&quot;&gt;&lt;em&gt;Henning Falk&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, ©2022 &lt;em&gt;&lt;a href=&quot;https://numfocus.org/&quot;&gt;&lt;em&gt;NumFOCUS&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, is used under a &lt;em&gt;&lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/&quot;&gt;&lt;em&gt;CC BY 4.0&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; license.*In case you are not familiar: &lt;a href=&quot;https://research-software-directory.org/software/esmvaltool&quot;&gt;ESMValTool&lt;/a&gt; is a software project that was designed by and for climate scientists to evaluate CMIP data in a standardized and reproducible manner (check out a recent blog &lt;a href=&quot;https://blog2.esciencecenter.nl/esmvaltool-recipes-for-solid-climate-science-da5b33814f69?sk=c6510256a10d2a35e7e9a723ec4ae0fb&quot;&gt;here&lt;/a&gt;). Several years ago, the project was split in two parts: &lt;a href=&quot;https://research-software-directory.org/software/esmvalcore&quot;&gt;ESMValCore&lt;/a&gt; implements the core functionality, whereas ESMValTool is essentially a big collection of “recipes” to reproduce a wide range of CMIP analytics — including some of the IPCC figures. While ESMValCore has matured as a reliable foundation for the ESMValTool, recent additions also make it attractive as a lightweight alternative to its hefty sibling.&lt;/p&gt;
&lt;p&gt;To give you an impression of ESMValCore’s look and feel, we start with a complete code block that exactly reproduces Tom’s figure. In the remainder of this post, we’ll dive into the details: the dataset interface, automatic ESGF downloads, CMOR checks and fixes, and exporting as recipe, meanwhile touching upon some of the similarities and differences with xarray-datatree. At the end of the blogpost we’ll build an ESMValTool recipe that reproduces the same figure with all available models and ensemble members.&lt;/p&gt;
&lt;p&gt;import cf_units
import matplotlib.pyplot as plt
from iris import quickplot&lt;/p&gt;
&lt;p&gt;from esmvalcore.config import CFG
from esmvalcore.dataset import Dataset
from esmvalcore.preprocessor import annual_statistics, anomalies, area_statistics&lt;/p&gt;
&lt;h1 id=&quot;settings-for-automatic-esgf-search&quot;&gt;Settings for automatic ESGF search&lt;/h1&gt;
&lt;p&gt;CFG[‘search_esgf’] = ‘when_missing’&lt;/p&gt;
&lt;h1 id=&quot;declare-common-dataset-facets&quot;&gt;Declare common dataset facets&lt;/h1&gt;
&lt;p&gt;template = Dataset(
short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp= &apos;&lt;em&gt;&apos;, # We’ll fill this below
dataset=&apos;&lt;/em&gt;&apos;,  # We’ll fill this below
ensemble=‘r4i1p1f1’,
grid=‘gn’,
)&lt;/p&gt;
&lt;h1 id=&quot;substitute-data-sources-and-experiments&quot;&gt;Substitute data sources and experiments&lt;/h1&gt;
&lt;p&gt;datasets = []
for dataset_id in [“CESM2”, “MPI-ESM1-2-LR”, “IPSL-CM6A-LR”]:
for experiment_id in [‘ssp126’, ‘ssp585’]:
dataset = template.copy(dataset=dataset_id, exp=[‘historical’, experiment_id])
dataset.add_supplementary(short_name=‘areacello’, mip=‘Ofx’, exp=‘historical’)
dataset.augment_facets()
datasets.append(dataset)&lt;/p&gt;
&lt;h1 id=&quot;set-the-reference-period-for-anomalies&quot;&gt;Set the reference period for anomalies&lt;/h1&gt;
&lt;p&gt;reference_period = {
“start_year”: 1950, “start_month”: 1, “start_day”: 1,
“end_year”: 1979, “end_month”: 12, “end_day”: 31,
}&lt;/p&gt;
&lt;h1 id=&quot;download-pre-process-and-plot-the-cubes&quot;&gt;(Down)load, pre-process, and plot the cubes&lt;/h1&gt;
&lt;p&gt;for dataset in datasets:
cube = dataset.load()
cube = area_statistics(cube, operator=‘mean’)
cube = anomalies(cube, reference=reference_period, period=‘month’)  # notice ‘month’
cube = annual_statistics(cube, operator=‘mean’)
cube.convert_units(‘degrees_C’)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Make sure all datasets use the same calendar for plotting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tcoord = cube.coord(&apos;time&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tcoord.units = cf_units.Unit(tcoord.units.origin, calendar=&apos;gregorian&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Plot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;quickplot.plot(cube, label=f&quot;{dataset[&apos;dataset&apos;]} - {dataset[&apos;exp&apos;]}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;show-the-plot&quot;&gt;Show the plot&lt;/h1&gt;
&lt;p&gt;plt.legend()
plt.show()
&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;554&quot; height=&quot;453&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-02171093.CmC3M12p_3bLXz.webp&quot; srcset=&quot;&quot;&gt;
The famous IPCC figure from Tom’s blogpost reproduced with ESMValCore.Cool! This looks exactly like the figure in Tom’s post 🎉. With roughly the same amount of code. If you haven’t read Tom’s post, this figure shows the historical and projected rise in sea-surface temperature from different climate models and future emission scenario’s.&lt;/p&gt;
&lt;h3 id=&quot;key-takeaway-&quot;&gt;Key takeaway **🔑&lt;/h3&gt;
&lt;p&gt;If there is one thing to note from this little script, it is how “scientifically meaningful” it is. For example, we never got to see actual files. We simply defined our datasets with meaningful &lt;em&gt;facets&lt;/em&gt;, as described in the CMIP &lt;a href=&quot;https://github.com/WCRP-CMIP/CMIP6_CVs&quot;&gt;controlled vocabulary&lt;/a&gt;. In the background, ESMValCore located the corresponding files on ESGF, downloaded them to our local environment (if we didn’t have them yet), loaded them into memory, checked adherence to the CMOR conventions, and applied fixes for known issues. But those are technical details, not science.&lt;/p&gt;
&lt;p&gt;ESMValCore, in the spirit of ESMValTool, focuses very much on &lt;em&gt;what&lt;/em&gt; to do, instead of &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-inner-workings-️&quot;&gt;**The inner workings **⚙️&lt;/h2&gt;
&lt;p&gt;It’s worth dissecting *how *ESMValCore does things, though. Firstly because you’ll need some understanding to wield it effectively. But mostly because we scientists are often trying to solve the same problems, so it’s interesting to see how ESMValCore tackles some of these issues so you don’t have to.&lt;/p&gt;
&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;p&gt;ESMValCore works with a configuration file. This is where you store information about, for example, how your data is organized on disk. The defaults are pretty good, we only had to enable automatic downloads. Let’s have a look at some of the other settings.&lt;/p&gt;
&lt;p&gt;print({key: CFG[key] **       for key in [‘download_dir’, ‘drs’, ‘output_dir’, ‘rootpath’]
}){
‘download_dir’: PosixPath(‘/home/peter/climate_data’),
‘drs’: {‘CMIP3’: ‘ESGF’, ‘CMIP5’: ‘ESGF’, ‘CMIP6’: ‘ESGF’, ‘CORDEX’: ‘ESGF’, ‘obs4MIPs’: ‘ESGF’},
‘output_dir’: PosixPath(‘/home/peter/esmvaltool_output’),
‘rootpath’: {‘default’: [PosixPath(‘/home/peter/climate_data’)]}
}The default configuration specifies that data will be downloaded to a folder called &lt;code&gt;climate data&lt;/code&gt; in my home directory. The &lt;code&gt;rootpath&lt;/code&gt; setting specifies all folders where ESMValCore should look for data, and it is set to the same default. Finally, ESMValCore defines a dedicated folder to store output. Every ESMValTool run or session will get its own subdirectory in there.&lt;/p&gt;
&lt;p&gt;The key point here is that you don’t have to worry about data management. You can configure some folders if you want to, but even that is not strictly necessary. If you’re working on dedicated climate data infrastructure such as Jasmin or DKRZ, you can also configure ESMValCore to use the Data Reference Syntax (DRS, the filenames + folder structure) used on these machines.&lt;/p&gt;
&lt;h3 id=&quot;data-discovery-&quot;&gt;Data discovery **🔍&lt;/h3&gt;
&lt;p&gt;Let’s have a closer look at the dataset definition. What happened, for example, when we called &lt;code&gt;augment_facets&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;dataset = Dataset(**    short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp=‘historical’,
dataset=‘CESM2’,
ensemble=‘r4i1p1f1’,
grid=‘gn’,
)
dataset.augment_facets()
print(dataset)Dataset:
{‘dataset’: ‘CESM2’,
‘project’: ‘CMIP6’,
‘mip’: ‘Omon’,
‘short_name’: ‘tos’,
‘activity’: ‘CMIP’,
‘ensemble’: ‘r4i1p1f1’,
‘exp’: ‘historical’,
‘frequency’: ‘mon’,
‘grid’: ‘gn’,
‘institute’: [‘NCAR’],
‘long_name’: ‘Sea Surface Temperature’,
‘modeling_realm’: [‘ocean’],
‘original_short_name’: ‘tos’,
‘standard_name’: ‘sea_surface_temperature’,
‘units’: ‘degC’}
session: ‘session-405b0393-0e28-4dae-836e-0d5961e3d30b_20230609_084132’ESMValCore auto-completed our &lt;code&gt;Dataset&lt;/code&gt; based on the information it got from the &lt;a href=&quot;https://github.com/PCMDI/cmip6-cmor-tables&quot;&gt;CMOR tables&lt;/a&gt;. With this specification, ESMValCore can automatically search both your local filesystem and the ESGF for available copies of the dataset. Let’s make things a bit more interesting, and look for all available ensemble members. The &lt;code&gt;from_files()&lt;/code&gt; method is used to build a list of available dataset based on the search fields.&lt;/p&gt;
&lt;p&gt;CFG[‘search_esgf’] = ‘always’
dataset_search = Dataset(
short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp=‘historical’,
dataset=‘CESM2’,
ensemble=’*’,
grid=‘gn’,
)
ensemble_datasets = list(dataset_search.from_files())&lt;/p&gt;
&lt;p&gt;print([ds[‘ensemble’] for dataset in ensemble_datasets])[
‘r10i1p1f1’,
‘r11i1p1f1’,
‘r1i1p1f1’,
‘r2i1p1f1’,
‘r3i1p1f1’,
‘r4i1p1f1’,
‘r5i1p1f1’,
‘r6i1p1f1’,
‘r7i1p1f1’,
‘r8i1p1f1’,
‘r9i1p1f1’
]Apparently there’s 11 ensemble members available for this model.&lt;/p&gt;
&lt;p&gt;The wildcard search functionality ( &lt;code&gt;&apos;*&apos;&lt;/code&gt; ) is incredibly useful, as there are often inconsistencies in availability between datasets. Asking for ensemble member 1 through 11 may work for CESM2 today, but not for another model, or it may be different tomorrow.&lt;/p&gt;
&lt;p&gt;What if we wanted to plot all *available data?&lt;/p&gt;
&lt;p&gt;CFG[‘search_esgf’] = ‘always’
dataset_search= Dataset(
short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp=[‘historical’, ‘ssp585’],
dataset=&apos;&lt;em&gt;&apos;,
ensemble=&apos;&lt;/em&gt;&apos;,
institute=’*’,
grid=‘gn’,
)
all_of_cmip = list(dataset_search.from_files())
print(len(all_of_cmip))821That’s a lot of datasets! We’ll save that for the end of the post.&lt;/p&gt;
&lt;h3 id=&quot;adding-supplementary-information&quot;&gt;Adding supplementary information**&lt;/h3&gt;
&lt;p&gt;To arrive at global mean temperature, we needed to calculate an area-weighted average. The data for ocean temperature comes at the native model grid, which is irregular and the grid cell area is not easily obtained. To address exactly this issue, the CF conventions include a specification of &lt;a href=&quot;http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/build/ch07s02.html&quot;&gt;cell measures&lt;/a&gt;. ESMValCore supports this functionality and makes it easy to add cell measures to a dataset. In our case, we need the variable called &lt;code&gt;areacello&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;discard-augmented-facets-as-they-will-be-different-for-areacellodataset--datasetdatasetminimal_facets&quot;&gt;Discard augmented facets as they will be different for areacello**dataset = Dataset(**dataset.minimal_facets)&lt;/h1&gt;
&lt;h1 id=&quot;add-areacello-as-supplementary-dataset&quot;&gt;Add areacello as supplementary dataset&lt;/h1&gt;
&lt;p&gt;dataset.add_supplementary(short_name=‘areacello’, mip=‘Ofx’)&lt;/p&gt;
&lt;h1 id=&quot;autocomplete-and-inspect&quot;&gt;Autocomplete and inspect&lt;/h1&gt;
&lt;p&gt;dataset.augment_facets()
print(dataset.summary())Dataset:
{‘dataset’: ‘CESM2’,
‘project’: ‘CMIP6’,
‘mip’: ‘Omon’,
‘short_name’: ‘tos’,
‘activity’: ‘CMIP’,
‘ensemble’: ‘r4i1p1f1’,
‘exp’: ‘historical’,
‘frequency’: ‘mon’,
‘grid’: ‘gn’,
‘institute’: [‘NCAR’],
‘long_name’: ‘Sea Surface Temperature’,
‘modeling_realm’: [‘ocean’],
‘original_short_name’: ‘tos’,
‘standard_name’: ‘sea_surface_temperature’,
‘units’: ‘degC’}
supplementaries:
{‘dataset’: ‘CESM2’,
‘project’: ‘CMIP6’,
‘mip’: ‘Ofx’,
‘short_name’: ‘areacello’,
‘activity’: ‘CMIP’,
‘ensemble’: ‘r4i1p1f1’,
‘exp’: ‘historical’,
‘frequency’: ‘fx’,
‘grid’: ‘gn’,
‘institute’: [‘NCAR’],
‘long_name’: ‘Grid-Cell Area for Ocean Variables’,
‘modeling_realm’: [‘ocean’],
‘original_short_name’: ‘areacello’,
‘standard_name’: ‘cell_area’,
‘units’: ‘m2’}
session: ‘session-ccace7d0-dc3b-4e03-87ea-2716aa127618_20230609_085322’These ancillary datasets are not always consistently available for each variant of a dataset. ESMValCore includes some convenience functionality that tries to find a matching variable if the exact match is not available. For example, it may take the grid cell area from another ensemble member. In this case, it looks like we have an exact match.&lt;/p&gt;
&lt;h3 id=&quot;data-downloading&quot;&gt;Data (down)loading**&lt;/h3&gt;
&lt;p&gt;We now arrive at the part of the script that calls &lt;code&gt;dataset.load()&lt;/code&gt;. In the background, ESMValCore automatically located the files on ESGF and downloaded them for us. Let’s illustrate this.&lt;/p&gt;
&lt;h1 id=&quot;before-loadprintdatasetfiles&quot;&gt;Before load**print(dataset.files)[&lt;/h1&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r4i1p1f1/Omon/tos/gn/v20190308/tos_Omon_CESM2_historical_r4i1p1f1_gn_&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;185001-201412.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’,
‘esgf3.dkrz.de’]
]# After load (and re-defining the dataset to trigger a new search)
print(dataset.files)[LocalFile(‘/home/peter/climate_data/CMIP6/CMIP/NCAR/CESM2/historical/r4i1p1f1/Omon/tos/gn/v20190308/tos_Omon_CESM2_historical_r4i1p1f1_gn_185001-201412.nc’)]Notice that there were copies of this file available on 5 different ESGF nodes. ESMValCore automatically selects the fastest available server and stored the dataset according to the standard CMOR data reference syntax.&lt;/p&gt;
&lt;p&gt;For our example dataset, all the data is apparently contained within one file. However, it’s not always like this. If we look, for example, at another ensemble member, we can see that it is stored in chunks of 50 years:&lt;/p&gt;
&lt;p&gt;print(ensemble_datasets[1].files)[ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_185001-189912.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’],
ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_190001-194912.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’],
ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_195001-199912.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’],
ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_200001-201412.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’]]In this case, ESMValCore automatically concatenates the data for us.&lt;/p&gt;
&lt;p&gt;You may have noticed that we assigned the result of the &lt;code&gt;load&lt;/code&gt; method to a new variable called &lt;code&gt;cube&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;cube = dataset.load()Under the hood, ESMValCore uses &lt;code&gt;[iris](https://scitools-iris.readthedocs.io)&lt;/code&gt; to represent data cubes. Compared to &lt;code&gt;xarray&lt;/code&gt;, &lt;code&gt;iris&lt;/code&gt; is more strict on checking adherence to CF conventions. This can make it harder to work with, but it also acts as a safeguard against unexpected behaviour.&lt;/p&gt;
&lt;p&gt;Where Tom used &lt;a href=&quot;https://cmip6-preprocessing.readthedocs.io&quot;&gt;xMIP&lt;/a&gt;, ESMValCore comes with builtin checks and if there are any (known) issues with the datasets, it automatically fixes them. Also, it automatically loads all supplementary datasets. Notice how the cell area is present as a cell measure.&lt;/p&gt;
&lt;p&gt;print(cube)sea_surface_temperature / (degC)          (time: 1980; cell index along second dimension: 384; cell index along first dimension: 320)
Dimension coordinates:
time                                   x                                        -                          -
cell index along second dimension      -                                        x                          -
cell index along first dimension       -                                        -                          x
Auxiliary coordinates:
latitude                               -                                        x                          x
longitude                              -                                        x                          x
Cell measures:
cell_area                              -                                        x                          x
Cell methods:
mean where sea                    area
mean                              time
Attributes:
Conventions                       ‘CF-1.7 CMIP-6.2’
activity_id                       ‘CMIP’
branch_method                     ‘standard’
branch_time_in_child              0
branch_time_in_parent             -492385
case_id                           ‘18’
cesm_casename                     ‘b.e21.BHIST.f09_g17.CMIP6-historical.004’
contact                           ‘&lt;a href=&quot;mailto:cesm_cmip6@ucar.edu&quot;&gt;cesm_cmip6@ucar.edu&lt;/a&gt;’
data_specs_version                ‘01.00.29’
description                       ‘This may differ from “surface temperature” in regions of sea ice or floating …’
experiment                        ‘all-forcing simulation of the recent past’
experiment_id                     ‘historical’
external_variables                ‘areacello’
forcing_index                     1
frequency                         ‘mon’
further_info_url                  ‘&lt;a href=&quot;https://furtherinfo.es-doc.org/CMIP6.NCAR.CESM2.historical.none.r4i1p1&quot;&gt;https://furtherinfo.es-doc.org/CMIP6.NCAR.CESM2.historical.none.r4i1p1&lt;/a&gt; …’
grid                              ‘native gx1v7 displaced pole grid (384x320 latxlon)’
grid_label                        ‘gn’
id                                ‘tos’
initialization_index              1
institution                       ‘National Center for Atmospheric Research, Climate and Global Dynamics Laboratory, …’
institution_id                    ‘NCAR’
license                           ‘CMIP6 model data produced by &amp;#x3C;The National Center for Atmospheric Research&gt; …’
mipTable                          ‘Omon’
mip_era                           ‘CMIP6’
model_doi_url                     ‘&lt;a href=&quot;https://doi.org/10.5065/D67H1H0V&quot;&gt;https://doi.org/10.5065/D67H1H0V&lt;/a&gt;’
nominal_resolution                ‘100 km’
out_name                          ‘tos’
parent_activity_id                ‘CMIP’
parent_experiment_id              ‘piControl’
parent_mip_era                    ‘CMIP6’
parent_source_id                  ‘CESM2’
parent_time_units                 ‘days since 1850-1-1 00:00:00’
parent_variant_label              ‘r1i1p1f1’
physics_index                     1
product                           ‘model-output’
prov                              ‘Omon ((isd.003))’
realization_index                 4
realm                             ‘ocean’
source                            ‘CESM2 (2017): atmosphere: CAM6 (0.9x1.25 finite volume grid; 288 x 192 …’
source_id                         ‘CESM2’
source_type                       ‘AOGCM BGC’
sub_experiment                    ‘none’
sub_experiment_id                 ‘none’
table_id                          ‘Omon’
time                              ‘time’
time_label                        ‘time-mean’
time_title                        ‘Temporal mean’
title                             ‘Sea Surface Temperature’
type                              ‘real’
variable_id                       ‘tos’
variant_info                      ‘CMIP6 20th century experiments (1850-2014) with CAM6, interactive land …’
variant_label                     ‘r4i1p1f1’&lt;/p&gt;
&lt;h3 id=&quot;pre-processing-️&quot;&gt;Pre-processing **🛠️&lt;/h3&gt;
&lt;p&gt;ESMValCore comes with a &lt;a href=&quot;https://docs.esmvaltool.org/projects/ESMValCore/en/latest/api/esmvalcore.preprocessor.html&quot;&gt;large suite&lt;/a&gt; of built-in preprocessing functions. These functions have been designed as scientifically sound default implementations for frequently performed operations. An important idea underpinning ESMValCore (&amp;#x26;Tool)’s philosophy is that standardization facilitates comparison between, and reproducibility of, our data analysis workflows. Moreover, by bundling our efforts we can develop high quality preprocessor functions more effectively. In that spirit it would be good to see how xMIP could be integrated with ESMValCore’s CMOR checks and fixes.&lt;/p&gt;
&lt;p&gt;We won’t go into detail on each of the preprocessing functions applied above, as they’re fairly self-explanatory. One thing to highlight though, is that in our calculation of anomalies, we deviated a little bit from Tom’s method. He subtracted the overall average of 1950–1980; we used monthly means over that period. It’s not really necessary here, but it facilitates comparing changes in summer temperature, for example 😎.&lt;/p&gt;
&lt;p&gt;cube = area_statistics(cube, operator=‘mean’)**cube = anomalies(cube, reference=reference_period, period=‘month’)
cube = annual_statistics(cube, operator=‘mean’)
cube.convert_units(‘degrees_C’)&lt;/p&gt;
&lt;h3 id=&quot;custom-code&quot;&gt;Custom code**&lt;/h3&gt;
&lt;p&gt;Up to this point, everything we’ve done was “pure” ESMValCore. However, in every data analysis workflow, there comes a point where you want to do custom things. In the traditional context of ESMValTool, such custom code would be added as a “diagnostic script”. In the context of this notebook, we can simply start working with the cube in whatever way we like.&lt;/p&gt;
&lt;p&gt;This can be a good moment to thank iris for its services, and continue with xarray if you prefer. For example:&lt;/p&gt;
&lt;p&gt;import xarray as xr**da = xr.DataArray.from_iris(cube)
da.plot()
print(da)&amp;#x3C;xarray.DataArray ‘tos’ (time: 165)&gt;
dask.array&amp;#x3C;filled, shape=(165,), dtype=float32, chunksize=(1,), chunktype=numpy.ndarray&gt;
Coordinates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;time     (time) object 1850-07-02 13:00:00.000001 … 2014-07-02 12:00:00
nlon     int64 …
nlat     int64 …
lat      float64 …
lon      float64 …
year     (time) int64 …
Attributes: (12/57)
standard_name:          sea_surface_temperature
long_name:              Sea Surface Temperature
units:                  degrees_C
Conventions:            CF-1.7 CMIP-6.2
activity_id:            CMIP
case_id:                18
…                     …
time:                   time
time_label:             time-mean
time_title:             Temporal mean
title:                  Sea Surface Temperature
type:                   real
cell_methods:           area: mean where sea time: mean longitude: latitu…
&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;595&quot; height=&quot;453&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-7d340529.qacNBbLZ_Z1kY9o1.webp&quot; srcset=&quot;&quot;&gt;
The change in sea-surface temperature as plotted by xarray’s builtin plot method.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;reproducibility-convert-to-recipe&quot;&gt;Reproducibility: convert to recipe**&lt;/h2&gt;
&lt;p&gt;Traditionally, ESMValTool was designed to work with recipes: static, human-readable files that declare a worfklow from start to finish. This comes back to what we said earlier about describing &lt;em&gt;what&lt;/em&gt; to do instead of &lt;em&gt;how&lt;/em&gt;. ESMValCore helps us to start building a recipe. With the following code, we can generate the &lt;code&gt;datasets&lt;/code&gt; and &lt;code&gt;diagnostics&lt;/code&gt; sections of the recipe:&lt;/p&gt;
&lt;p&gt;from esmvalcore.dataset import datasets_to_recipe**import yaml&lt;/p&gt;
&lt;p&gt;for dataset in ensemble_datasets:
dataset.facets[‘diagnostic’] = ‘easy_ipcc’
print(yaml.safe_dump(datasets_to_recipe(datasets)))datasets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dataset: CESM2
ensemble: r4i1p1f1
institute: NCAR&lt;/li&gt;
&lt;li&gt;dataset: IPSL-CM6A-LR
ensemble: r4i1p1f1
institute: IPSL&lt;/li&gt;
&lt;li&gt;dataset: MPI-ESM1-2-LR
ensemble: r4i1p1f1
institute: MPI-M&lt;/li&gt;
&lt;li&gt;dataset: TaiESM1
ensemble: r1i1p1f1
institute: AS-RCEC&lt;/li&gt;
&lt;li&gt;dataset: AWI-CM-1-1-MR
ensemble: r(1:5)i1p1f1
institute: AWI&lt;/li&gt;
&lt;li&gt;dataset: AWI-ESM-1-1-LR
ensemble: r1i1p1f1
institute: AWI&lt;/li&gt;
&lt;li&gt;dataset: BCC-CSM2-MR
ensemble: r(1:3)i1p1f1
institute: BCC
…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;diagnostics:
easy_ipcc:
variables:
tos:
exp:
- historical
- ssp585
grid: gn
mip: Omon
project: CMIP6You still have to add the preprocessors and some metadata (a short description etc.). We envision a workflow where you use ESMValCore interactively for most of your exploratory work, and then port it to a recipe for sharing and reproducibility.&lt;/p&gt;
&lt;p&gt;To complete this post, we’ve gone ahead and extended the recipe above to include all the available CMIP6 data and make a nice plot. As you might expect, this required more labour due to dataset issues for which no fixes were available, and a bit of extra tinkering to make the figure look more like the IPCC version. You can find the corresponding recipe and diagnostic script &lt;a href=&quot;https://github.com/ESMValGroup/ESMValTool/pull/3356&quot;&gt;here&lt;/a&gt;. Be careful with running it, though! This recipe will try to download almost twenty-thousand files… Running this on the German climate compute service, we get the following figure:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-3815e0c2.CnP8Bhji_ZGVqem.webp&quot; srcset=&quot;&quot;&gt;
This image includes all available models &amp;#x26; ensemble members.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary**&lt;/h2&gt;
&lt;p&gt;ESMValCore is great addition to any climate analysis toolbox. Its key strengths are its its approach to streamlining workflows to achieve scientific rigor and reproducibility, and its tight integration with the ESGF and CMOR standards.&lt;/p&gt;
&lt;p&gt;If you regularly work with CMIP data, sometimes struggle to retrieve data from ESGF, frequently encounter incompatible datasets, or want to make your workflows available to others, you should definitely give it a shot.&lt;/p&gt;</description><pubDate>Thu, 05 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-easy-ipcc-blog-done-differently&quot;&gt;&lt;strong&gt;The “Easy IPCC” blog done differently&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Co-authored by &lt;a href=&quot;https://www.esciencecenter.nl/team/bouwe-andela-msc/&quot;&gt;Bouwe Andela&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://medium.com/pangeo/easy-ipcc-part-1-multi-model-datatree-469b87cf9114&quot;&gt;recent blog post&lt;/a&gt;, Tom Nicholas presented a nice walkthrough of reproducing a famous IPCC figure with &lt;code&gt;[xarray-datatree](https://xarray-datatree.readthedocs.io/en/latest/)&lt;/code&gt;. Here, we attempt to achieve the same with ESMValCore — the workflow engine that powers the more widely known &lt;a href=&quot;http://docs.esmvaltool.org/&quot;&gt;ESMValTool&lt;/a&gt;. Both xarray-datatree and ESMValCore facilitate the analysis of large climate datasets, but our approach is quite different. For example, xarray-datatree tries to facilitate any hierarchical file structure (more generic), whereas ESMValCore focuses on facilitating CMIP, or CMIP-like data only (more specific, thus tailored). Seeing them side by side is food for thought.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;770&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-75688b5f.B_CK0meh_Z1NGFQd.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;“&lt;/em&gt;&lt;a href=&quot;https://github.com/zarr-developers/zarr-illustrations-falk-2022/blob/main/1200dpi/kits-deluge-1200dpi.png&quot;&gt;&lt;em&gt;Adam uploads&lt;/em&gt;&lt;/a&gt;*” by &lt;em&gt;&lt;a href=&quot;https://twitter.com/DrHenningFalk&quot;&gt;&lt;em&gt;Henning Falk&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, ©2022 &lt;em&gt;&lt;a href=&quot;https://numfocus.org/&quot;&gt;&lt;em&gt;NumFOCUS&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, is used under a &lt;em&gt;&lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/&quot;&gt;&lt;em&gt;CC BY 4.0&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; license.*In case you are not familiar: &lt;a href=&quot;https://research-software-directory.org/software/esmvaltool&quot;&gt;ESMValTool&lt;/a&gt; is a software project that was designed by and for climate scientists to evaluate CMIP data in a standardized and reproducible manner (check out a recent blog &lt;a href=&quot;https://blog2.esciencecenter.nl/esmvaltool-recipes-for-solid-climate-science-da5b33814f69?sk=c6510256a10d2a35e7e9a723ec4ae0fb&quot;&gt;here&lt;/a&gt;). Several years ago, the project was split in two parts: &lt;a href=&quot;https://research-software-directory.org/software/esmvalcore&quot;&gt;ESMValCore&lt;/a&gt; implements the core functionality, whereas ESMValTool is essentially a big collection of “recipes” to reproduce a wide range of CMIP analytics — including some of the IPCC figures. While ESMValCore has matured as a reliable foundation for the ESMValTool, recent additions also make it attractive as a lightweight alternative to its hefty sibling.&lt;/p&gt;
&lt;p&gt;To give you an impression of ESMValCore’s look and feel, we start with a complete code block that exactly reproduces Tom’s figure. In the remainder of this post, we’ll dive into the details: the dataset interface, automatic ESGF downloads, CMOR checks and fixes, and exporting as recipe, meanwhile touching upon some of the similarities and differences with xarray-datatree. At the end of the blogpost we’ll build an ESMValTool recipe that reproduces the same figure with all available models and ensemble members.&lt;/p&gt;
&lt;p&gt;import cf_units
import matplotlib.pyplot as plt
from iris import quickplot&lt;/p&gt;
&lt;p&gt;from esmvalcore.config import CFG
from esmvalcore.dataset import Dataset
from esmvalcore.preprocessor import annual_statistics, anomalies, area_statistics&lt;/p&gt;
&lt;h1 id=&quot;settings-for-automatic-esgf-search&quot;&gt;Settings for automatic ESGF search&lt;/h1&gt;
&lt;p&gt;CFG[‘search_esgf’] = ‘when_missing’&lt;/p&gt;
&lt;h1 id=&quot;declare-common-dataset-facets&quot;&gt;Declare common dataset facets&lt;/h1&gt;
&lt;p&gt;template = Dataset(
short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp= &apos;&lt;em&gt;&apos;, # We’ll fill this below
dataset=&apos;&lt;/em&gt;&apos;,  # We’ll fill this below
ensemble=‘r4i1p1f1’,
grid=‘gn’,
)&lt;/p&gt;
&lt;h1 id=&quot;substitute-data-sources-and-experiments&quot;&gt;Substitute data sources and experiments&lt;/h1&gt;
&lt;p&gt;datasets = []
for dataset_id in [“CESM2”, “MPI-ESM1-2-LR”, “IPSL-CM6A-LR”]:
for experiment_id in [‘ssp126’, ‘ssp585’]:
dataset = template.copy(dataset=dataset_id, exp=[‘historical’, experiment_id])
dataset.add_supplementary(short_name=‘areacello’, mip=‘Ofx’, exp=‘historical’)
dataset.augment_facets()
datasets.append(dataset)&lt;/p&gt;
&lt;h1 id=&quot;set-the-reference-period-for-anomalies&quot;&gt;Set the reference period for anomalies&lt;/h1&gt;
&lt;p&gt;reference_period = {
“start_year”: 1950, “start_month”: 1, “start_day”: 1,
“end_year”: 1979, “end_month”: 12, “end_day”: 31,
}&lt;/p&gt;
&lt;h1 id=&quot;download-pre-process-and-plot-the-cubes&quot;&gt;(Down)load, pre-process, and plot the cubes&lt;/h1&gt;
&lt;p&gt;for dataset in datasets:
cube = dataset.load()
cube = area_statistics(cube, operator=‘mean’)
cube = anomalies(cube, reference=reference_period, period=‘month’)  # notice ‘month’
cube = annual_statistics(cube, operator=‘mean’)
cube.convert_units(‘degrees_C’)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Make sure all datasets use the same calendar for plotting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tcoord = cube.coord(&apos;time&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;tcoord.units = cf_units.Unit(tcoord.units.origin, calendar=&apos;gregorian&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Plot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;quickplot.plot(cube, label=f&quot;{dataset[&apos;dataset&apos;]} - {dataset[&apos;exp&apos;]}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;show-the-plot&quot;&gt;Show the plot&lt;/h1&gt;
&lt;p&gt;plt.legend()
plt.show()
&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;554&quot; height=&quot;453&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-02171093.CmC3M12p_3bLXz.webp&quot; srcset=&quot;&quot;&gt;
The famous IPCC figure from Tom’s blogpost reproduced with ESMValCore.Cool! This looks exactly like the figure in Tom’s post 🎉. With roughly the same amount of code. If you haven’t read Tom’s post, this figure shows the historical and projected rise in sea-surface temperature from different climate models and future emission scenario’s.&lt;/p&gt;
&lt;h3 id=&quot;key-takeaway-&quot;&gt;Key takeaway **🔑&lt;/h3&gt;
&lt;p&gt;If there is one thing to note from this little script, it is how “scientifically meaningful” it is. For example, we never got to see actual files. We simply defined our datasets with meaningful &lt;em&gt;facets&lt;/em&gt;, as described in the CMIP &lt;a href=&quot;https://github.com/WCRP-CMIP/CMIP6_CVs&quot;&gt;controlled vocabulary&lt;/a&gt;. In the background, ESMValCore located the corresponding files on ESGF, downloaded them to our local environment (if we didn’t have them yet), loaded them into memory, checked adherence to the CMOR conventions, and applied fixes for known issues. But those are technical details, not science.&lt;/p&gt;
&lt;p&gt;ESMValCore, in the spirit of ESMValTool, focuses very much on &lt;em&gt;what&lt;/em&gt; to do, instead of &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-inner-workings-️&quot;&gt;**The inner workings **⚙️&lt;/h2&gt;
&lt;p&gt;It’s worth dissecting *how *ESMValCore does things, though. Firstly because you’ll need some understanding to wield it effectively. But mostly because we scientists are often trying to solve the same problems, so it’s interesting to see how ESMValCore tackles some of these issues so you don’t have to.&lt;/p&gt;
&lt;h3 id=&quot;configuration&quot;&gt;Configuration&lt;/h3&gt;
&lt;p&gt;ESMValCore works with a configuration file. This is where you store information about, for example, how your data is organized on disk. The defaults are pretty good, we only had to enable automatic downloads. Let’s have a look at some of the other settings.&lt;/p&gt;
&lt;p&gt;print({key: CFG[key] **       for key in [‘download_dir’, ‘drs’, ‘output_dir’, ‘rootpath’]
}){
‘download_dir’: PosixPath(‘/home/peter/climate_data’),
‘drs’: {‘CMIP3’: ‘ESGF’, ‘CMIP5’: ‘ESGF’, ‘CMIP6’: ‘ESGF’, ‘CORDEX’: ‘ESGF’, ‘obs4MIPs’: ‘ESGF’},
‘output_dir’: PosixPath(‘/home/peter/esmvaltool_output’),
‘rootpath’: {‘default’: [PosixPath(‘/home/peter/climate_data’)]}
}The default configuration specifies that data will be downloaded to a folder called &lt;code&gt;climate data&lt;/code&gt; in my home directory. The &lt;code&gt;rootpath&lt;/code&gt; setting specifies all folders where ESMValCore should look for data, and it is set to the same default. Finally, ESMValCore defines a dedicated folder to store output. Every ESMValTool run or session will get its own subdirectory in there.&lt;/p&gt;
&lt;p&gt;The key point here is that you don’t have to worry about data management. You can configure some folders if you want to, but even that is not strictly necessary. If you’re working on dedicated climate data infrastructure such as Jasmin or DKRZ, you can also configure ESMValCore to use the Data Reference Syntax (DRS, the filenames + folder structure) used on these machines.&lt;/p&gt;
&lt;h3 id=&quot;data-discovery-&quot;&gt;Data discovery **🔍&lt;/h3&gt;
&lt;p&gt;Let’s have a closer look at the dataset definition. What happened, for example, when we called &lt;code&gt;augment_facets&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;dataset = Dataset(**    short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp=‘historical’,
dataset=‘CESM2’,
ensemble=‘r4i1p1f1’,
grid=‘gn’,
)
dataset.augment_facets()
print(dataset)Dataset:
{‘dataset’: ‘CESM2’,
‘project’: ‘CMIP6’,
‘mip’: ‘Omon’,
‘short_name’: ‘tos’,
‘activity’: ‘CMIP’,
‘ensemble’: ‘r4i1p1f1’,
‘exp’: ‘historical’,
‘frequency’: ‘mon’,
‘grid’: ‘gn’,
‘institute’: [‘NCAR’],
‘long_name’: ‘Sea Surface Temperature’,
‘modeling_realm’: [‘ocean’],
‘original_short_name’: ‘tos’,
‘standard_name’: ‘sea_surface_temperature’,
‘units’: ‘degC’}
session: ‘session-405b0393-0e28-4dae-836e-0d5961e3d30b_20230609_084132’ESMValCore auto-completed our &lt;code&gt;Dataset&lt;/code&gt; based on the information it got from the &lt;a href=&quot;https://github.com/PCMDI/cmip6-cmor-tables&quot;&gt;CMOR tables&lt;/a&gt;. With this specification, ESMValCore can automatically search both your local filesystem and the ESGF for available copies of the dataset. Let’s make things a bit more interesting, and look for all available ensemble members. The &lt;code&gt;from_files()&lt;/code&gt; method is used to build a list of available dataset based on the search fields.&lt;/p&gt;
&lt;p&gt;CFG[‘search_esgf’] = ‘always’
dataset_search = Dataset(
short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp=‘historical’,
dataset=‘CESM2’,
ensemble=’*’,
grid=‘gn’,
)
ensemble_datasets = list(dataset_search.from_files())&lt;/p&gt;
&lt;p&gt;print([ds[‘ensemble’] for dataset in ensemble_datasets])[
‘r10i1p1f1’,
‘r11i1p1f1’,
‘r1i1p1f1’,
‘r2i1p1f1’,
‘r3i1p1f1’,
‘r4i1p1f1’,
‘r5i1p1f1’,
‘r6i1p1f1’,
‘r7i1p1f1’,
‘r8i1p1f1’,
‘r9i1p1f1’
]Apparently there’s 11 ensemble members available for this model.&lt;/p&gt;
&lt;p&gt;The wildcard search functionality ( &lt;code&gt;&apos;*&apos;&lt;/code&gt; ) is incredibly useful, as there are often inconsistencies in availability between datasets. Asking for ensemble member 1 through 11 may work for CESM2 today, but not for another model, or it may be different tomorrow.&lt;/p&gt;
&lt;p&gt;What if we wanted to plot all *available data?&lt;/p&gt;
&lt;p&gt;CFG[‘search_esgf’] = ‘always’
dataset_search= Dataset(
short_name=‘tos’,
mip=‘Omon’,
project=‘CMIP6’,
exp=[‘historical’, ‘ssp585’],
dataset=&apos;&lt;em&gt;&apos;,
ensemble=&apos;&lt;/em&gt;&apos;,
institute=’*’,
grid=‘gn’,
)
all_of_cmip = list(dataset_search.from_files())
print(len(all_of_cmip))821That’s a lot of datasets! We’ll save that for the end of the post.&lt;/p&gt;
&lt;h3 id=&quot;adding-supplementary-information&quot;&gt;Adding supplementary information**&lt;/h3&gt;
&lt;p&gt;To arrive at global mean temperature, we needed to calculate an area-weighted average. The data for ocean temperature comes at the native model grid, which is irregular and the grid cell area is not easily obtained. To address exactly this issue, the CF conventions include a specification of &lt;a href=&quot;http://cfconventions.org/Data/cf-conventions/cf-conventions-1.7/build/ch07s02.html&quot;&gt;cell measures&lt;/a&gt;. ESMValCore supports this functionality and makes it easy to add cell measures to a dataset. In our case, we need the variable called &lt;code&gt;areacello&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&quot;discard-augmented-facets-as-they-will-be-different-for-areacellodataset--datasetdatasetminimal_facets&quot;&gt;Discard augmented facets as they will be different for areacello**dataset = Dataset(**dataset.minimal_facets)&lt;/h1&gt;
&lt;h1 id=&quot;add-areacello-as-supplementary-dataset&quot;&gt;Add areacello as supplementary dataset&lt;/h1&gt;
&lt;p&gt;dataset.add_supplementary(short_name=‘areacello’, mip=‘Ofx’)&lt;/p&gt;
&lt;h1 id=&quot;autocomplete-and-inspect&quot;&gt;Autocomplete and inspect&lt;/h1&gt;
&lt;p&gt;dataset.augment_facets()
print(dataset.summary())Dataset:
{‘dataset’: ‘CESM2’,
‘project’: ‘CMIP6’,
‘mip’: ‘Omon’,
‘short_name’: ‘tos’,
‘activity’: ‘CMIP’,
‘ensemble’: ‘r4i1p1f1’,
‘exp’: ‘historical’,
‘frequency’: ‘mon’,
‘grid’: ‘gn’,
‘institute’: [‘NCAR’],
‘long_name’: ‘Sea Surface Temperature’,
‘modeling_realm’: [‘ocean’],
‘original_short_name’: ‘tos’,
‘standard_name’: ‘sea_surface_temperature’,
‘units’: ‘degC’}
supplementaries:
{‘dataset’: ‘CESM2’,
‘project’: ‘CMIP6’,
‘mip’: ‘Ofx’,
‘short_name’: ‘areacello’,
‘activity’: ‘CMIP’,
‘ensemble’: ‘r4i1p1f1’,
‘exp’: ‘historical’,
‘frequency’: ‘fx’,
‘grid’: ‘gn’,
‘institute’: [‘NCAR’],
‘long_name’: ‘Grid-Cell Area for Ocean Variables’,
‘modeling_realm’: [‘ocean’],
‘original_short_name’: ‘areacello’,
‘standard_name’: ‘cell_area’,
‘units’: ‘m2’}
session: ‘session-ccace7d0-dc3b-4e03-87ea-2716aa127618_20230609_085322’These ancillary datasets are not always consistently available for each variant of a dataset. ESMValCore includes some convenience functionality that tries to find a matching variable if the exact match is not available. For example, it may take the grid cell area from another ensemble member. In this case, it looks like we have an exact match.&lt;/p&gt;
&lt;h3 id=&quot;data-downloading&quot;&gt;Data (down)loading**&lt;/h3&gt;
&lt;p&gt;We now arrive at the part of the script that calls &lt;code&gt;dataset.load()&lt;/code&gt;. In the background, ESMValCore automatically located the files on ESGF and downloaded them for us. Let’s illustrate this.&lt;/p&gt;
&lt;h1 id=&quot;before-loadprintdatasetfiles&quot;&gt;Before load**print(dataset.files)[&lt;/h1&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r4i1p1f1/Omon/tos/gn/v20190308/tos_Omon_CESM2_historical_r4i1p1f1_gn_&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;185001-201412.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’,
‘esgf3.dkrz.de’]
]# After load (and re-defining the dataset to trigger a new search)
print(dataset.files)[LocalFile(‘/home/peter/climate_data/CMIP6/CMIP/NCAR/CESM2/historical/r4i1p1f1/Omon/tos/gn/v20190308/tos_Omon_CESM2_historical_r4i1p1f1_gn_185001-201412.nc’)]Notice that there were copies of this file available on 5 different ESGF nodes. ESMValCore automatically selects the fastest available server and stored the dataset according to the standard CMOR data reference syntax.&lt;/p&gt;
&lt;p&gt;For our example dataset, all the data is apparently contained within one file. However, it’s not always like this. If we look, for example, at another ensemble member, we can see that it is stored in chunks of 50 years:&lt;/p&gt;
&lt;p&gt;print(ensemble_datasets[1].files)[ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_185001-189912.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’],
ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_190001-194912.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’],
ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_195001-199912.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’],
ESGFFile:CMIP6/CMIP/NCAR/CESM2/historical/r10i1p1f1/Omon/tos/gn/v20190313/tos_Omon_CESM2_historical_r10i1p1f1_gn_200001-201412.nc on hosts [‘aims3.llnl.gov’, ‘esgf-data.ucar.edu’, ‘esgf-data04.diasjp.net’, ‘esgf.ceda.ac.uk’, ‘esgf3.dkrz.de’]]In this case, ESMValCore automatically concatenates the data for us.&lt;/p&gt;
&lt;p&gt;You may have noticed that we assigned the result of the &lt;code&gt;load&lt;/code&gt; method to a new variable called &lt;code&gt;cube&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;cube = dataset.load()Under the hood, ESMValCore uses &lt;code&gt;[iris](https://scitools-iris.readthedocs.io)&lt;/code&gt; to represent data cubes. Compared to &lt;code&gt;xarray&lt;/code&gt;, &lt;code&gt;iris&lt;/code&gt; is more strict on checking adherence to CF conventions. This can make it harder to work with, but it also acts as a safeguard against unexpected behaviour.&lt;/p&gt;
&lt;p&gt;Where Tom used &lt;a href=&quot;https://cmip6-preprocessing.readthedocs.io&quot;&gt;xMIP&lt;/a&gt;, ESMValCore comes with builtin checks and if there are any (known) issues with the datasets, it automatically fixes them. Also, it automatically loads all supplementary datasets. Notice how the cell area is present as a cell measure.&lt;/p&gt;
&lt;p&gt;print(cube)sea_surface_temperature / (degC)          (time: 1980; cell index along second dimension: 384; cell index along first dimension: 320)
Dimension coordinates:
time                                   x                                        -                          -
cell index along second dimension      -                                        x                          -
cell index along first dimension       -                                        -                          x
Auxiliary coordinates:
latitude                               -                                        x                          x
longitude                              -                                        x                          x
Cell measures:
cell_area                              -                                        x                          x
Cell methods:
mean where sea                    area
mean                              time
Attributes:
Conventions                       ‘CF-1.7 CMIP-6.2’
activity_id                       ‘CMIP’
branch_method                     ‘standard’
branch_time_in_child              0
branch_time_in_parent             -492385
case_id                           ‘18’
cesm_casename                     ‘b.e21.BHIST.f09_g17.CMIP6-historical.004’
contact                           ‘&lt;a href=&quot;mailto:cesm_cmip6@ucar.edu&quot;&gt;cesm_cmip6@ucar.edu&lt;/a&gt;’
data_specs_version                ‘01.00.29’
description                       ‘This may differ from “surface temperature” in regions of sea ice or floating …’
experiment                        ‘all-forcing simulation of the recent past’
experiment_id                     ‘historical’
external_variables                ‘areacello’
forcing_index                     1
frequency                         ‘mon’
further_info_url                  ‘&lt;a href=&quot;https://furtherinfo.es-doc.org/CMIP6.NCAR.CESM2.historical.none.r4i1p1&quot;&gt;https://furtherinfo.es-doc.org/CMIP6.NCAR.CESM2.historical.none.r4i1p1&lt;/a&gt; …’
grid                              ‘native gx1v7 displaced pole grid (384x320 latxlon)’
grid_label                        ‘gn’
id                                ‘tos’
initialization_index              1
institution                       ‘National Center for Atmospheric Research, Climate and Global Dynamics Laboratory, …’
institution_id                    ‘NCAR’
license                           ‘CMIP6 model data produced by &amp;#x3C;The National Center for Atmospheric Research&gt; …’
mipTable                          ‘Omon’
mip_era                           ‘CMIP6’
model_doi_url                     ‘&lt;a href=&quot;https://doi.org/10.5065/D67H1H0V&quot;&gt;https://doi.org/10.5065/D67H1H0V&lt;/a&gt;’
nominal_resolution                ‘100 km’
out_name                          ‘tos’
parent_activity_id                ‘CMIP’
parent_experiment_id              ‘piControl’
parent_mip_era                    ‘CMIP6’
parent_source_id                  ‘CESM2’
parent_time_units                 ‘days since 1850-1-1 00:00:00’
parent_variant_label              ‘r1i1p1f1’
physics_index                     1
product                           ‘model-output’
prov                              ‘Omon ((isd.003))’
realization_index                 4
realm                             ‘ocean’
source                            ‘CESM2 (2017): atmosphere: CAM6 (0.9x1.25 finite volume grid; 288 x 192 …’
source_id                         ‘CESM2’
source_type                       ‘AOGCM BGC’
sub_experiment                    ‘none’
sub_experiment_id                 ‘none’
table_id                          ‘Omon’
time                              ‘time’
time_label                        ‘time-mean’
time_title                        ‘Temporal mean’
title                             ‘Sea Surface Temperature’
type                              ‘real’
variable_id                       ‘tos’
variant_info                      ‘CMIP6 20th century experiments (1850-2014) with CAM6, interactive land …’
variant_label                     ‘r4i1p1f1’&lt;/p&gt;
&lt;h3 id=&quot;pre-processing-️&quot;&gt;Pre-processing **🛠️&lt;/h3&gt;
&lt;p&gt;ESMValCore comes with a &lt;a href=&quot;https://docs.esmvaltool.org/projects/ESMValCore/en/latest/api/esmvalcore.preprocessor.html&quot;&gt;large suite&lt;/a&gt; of built-in preprocessing functions. These functions have been designed as scientifically sound default implementations for frequently performed operations. An important idea underpinning ESMValCore (&amp;#x26;Tool)’s philosophy is that standardization facilitates comparison between, and reproducibility of, our data analysis workflows. Moreover, by bundling our efforts we can develop high quality preprocessor functions more effectively. In that spirit it would be good to see how xMIP could be integrated with ESMValCore’s CMOR checks and fixes.&lt;/p&gt;
&lt;p&gt;We won’t go into detail on each of the preprocessing functions applied above, as they’re fairly self-explanatory. One thing to highlight though, is that in our calculation of anomalies, we deviated a little bit from Tom’s method. He subtracted the overall average of 1950–1980; we used monthly means over that period. It’s not really necessary here, but it facilitates comparing changes in summer temperature, for example 😎.&lt;/p&gt;
&lt;p&gt;cube = area_statistics(cube, operator=‘mean’)**cube = anomalies(cube, reference=reference_period, period=‘month’)
cube = annual_statistics(cube, operator=‘mean’)
cube.convert_units(‘degrees_C’)&lt;/p&gt;
&lt;h3 id=&quot;custom-code&quot;&gt;Custom code**&lt;/h3&gt;
&lt;p&gt;Up to this point, everything we’ve done was “pure” ESMValCore. However, in every data analysis workflow, there comes a point where you want to do custom things. In the traditional context of ESMValTool, such custom code would be added as a “diagnostic script”. In the context of this notebook, we can simply start working with the cube in whatever way we like.&lt;/p&gt;
&lt;p&gt;This can be a good moment to thank iris for its services, and continue with xarray if you prefer. For example:&lt;/p&gt;
&lt;p&gt;import xarray as xr**da = xr.DataArray.from_iris(cube)
da.plot()
print(da)&amp;#x3C;xarray.DataArray ‘tos’ (time: 165)&gt;
dask.array&amp;#x3C;filled, shape=(165,), dtype=float32, chunksize=(1,), chunktype=numpy.ndarray&gt;
Coordinates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;time     (time) object 1850-07-02 13:00:00.000001 … 2014-07-02 12:00:00
nlon     int64 …
nlat     int64 …
lat      float64 …
lon      float64 …
year     (time) int64 …
Attributes: (12/57)
standard_name:          sea_surface_temperature
long_name:              Sea Surface Temperature
units:                  degrees_C
Conventions:            CF-1.7 CMIP-6.2
activity_id:            CMIP
case_id:                18
…                     …
time:                   time
time_label:             time-mean
time_title:             Temporal mean
title:                  Sea Surface Temperature
type:                   real
cell_methods:           area: mean where sea time: mean longitude: latitu…
&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;595&quot; height=&quot;453&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-7d340529.qacNBbLZ_Z1kY9o1.webp&quot; srcset=&quot;&quot;&gt;
The change in sea-surface temperature as plotted by xarray’s builtin plot method.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;reproducibility-convert-to-recipe&quot;&gt;Reproducibility: convert to recipe**&lt;/h2&gt;
&lt;p&gt;Traditionally, ESMValTool was designed to work with recipes: static, human-readable files that declare a worfklow from start to finish. This comes back to what we said earlier about describing &lt;em&gt;what&lt;/em&gt; to do instead of &lt;em&gt;how&lt;/em&gt;. ESMValCore helps us to start building a recipe. With the following code, we can generate the &lt;code&gt;datasets&lt;/code&gt; and &lt;code&gt;diagnostics&lt;/code&gt; sections of the recipe:&lt;/p&gt;
&lt;p&gt;from esmvalcore.dataset import datasets_to_recipe**import yaml&lt;/p&gt;
&lt;p&gt;for dataset in ensemble_datasets:
dataset.facets[‘diagnostic’] = ‘easy_ipcc’
print(yaml.safe_dump(datasets_to_recipe(datasets)))datasets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dataset: CESM2
ensemble: r4i1p1f1
institute: NCAR&lt;/li&gt;
&lt;li&gt;dataset: IPSL-CM6A-LR
ensemble: r4i1p1f1
institute: IPSL&lt;/li&gt;
&lt;li&gt;dataset: MPI-ESM1-2-LR
ensemble: r4i1p1f1
institute: MPI-M&lt;/li&gt;
&lt;li&gt;dataset: TaiESM1
ensemble: r1i1p1f1
institute: AS-RCEC&lt;/li&gt;
&lt;li&gt;dataset: AWI-CM-1-1-MR
ensemble: r(1:5)i1p1f1
institute: AWI&lt;/li&gt;
&lt;li&gt;dataset: AWI-ESM-1-1-LR
ensemble: r1i1p1f1
institute: AWI&lt;/li&gt;
&lt;li&gt;dataset: BCC-CSM2-MR
ensemble: r(1:3)i1p1f1
institute: BCC
…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;diagnostics:
easy_ipcc:
variables:
tos:
exp:
- historical
- ssp585
grid: gn
mip: Omon
project: CMIP6You still have to add the preprocessors and some metadata (a short description etc.). We envision a workflow where you use ESMValCore interactively for most of your exploratory work, and then port it to a recipe for sharing and reproducibility.&lt;/p&gt;
&lt;p&gt;To complete this post, we’ve gone ahead and extended the recipe above to include all the available CMIP6 data and make a nice plot. As you might expect, this required more labour due to dataset issues for which no fixes were available, and a bit of extra tinkering to make the figure look more like the IPCC version. You can find the corresponding recipe and diagnostic script &lt;a href=&quot;https://github.com/ESMValGroup/ESMValTool/pull/3356&quot;&gt;here&lt;/a&gt;. Be careful with running it, though! This recipe will try to download almost twenty-thousand files… Running this on the German climate compute service, we get the following figure:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Analysis-ready climate data with ESMValCore&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-3815e0c2.CnP8Bhji_ZGVqem.webp&quot; srcset=&quot;&quot;&gt;
This image includes all available models &amp;#x26; ensemble members.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary**&lt;/h2&gt;
&lt;p&gt;ESMValCore is great addition to any climate analysis toolbox. Its key strengths are its its approach to streamlining workflows to achieve scientific rigor and reproducibility, and its tight integration with the ESGF and CMOR standards.&lt;/p&gt;
&lt;p&gt;If you regularly work with CMIP data, sometimes struggle to retrieve data from ESGF, frequently encounter incompatible datasets, or want to make your workflows available to others, you should definitely give it a shot.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/analysis-ready-climate-data-with-esmvalc-75688b5f.B_CK0meh.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Do you have 50.000 annotators?</title><link>https://blog2.esciencecenter.nl/posts/2023-09-21---do-you-have-50000-annotators</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-09-21---do-you-have-50000-annotators</guid><description>&lt;h1 id=&quot;do-you-have-50000-annotators&quot;&gt;&lt;strong&gt;Do you have 50.000 annotators?&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;*Written by eScience Center Fellow, *&lt;a href=&quot;https://www.esciencecenter.nl/fellows/daniela-gawehns/&quot;&gt;&lt;em&gt;Daniela Gawehns&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Do you have 50.000 annotators?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/do-you-have-50000-annotators-9925b35a.DQcEXpIh_Z6PdAr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://www.shutterstock.com/image-photo/business-people-diverse-brainstorm-meeting-concept-388995775&quot;&gt;Shutterstock&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During ICT.open 2023, I organized a workshop for 40 computer scientists on reproducibility in computer science. This is a short summary of the main results and how I experienced the workshop as a moderator.&lt;/p&gt;
&lt;p&gt;The workshop was part of &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;my fellowship project&lt;/a&gt; at the eScience Center to find out how people in the computer sciences understand reproducibility. The idea behind the project is that communities of researchers differ in how they understand the term reproducibility. Before providing tools, guidance or incentives on how to make research outputs more reproducible, we need to figure out what people understand as reproducible research.&lt;/p&gt;
&lt;p&gt;What happened?**&lt;/p&gt;
&lt;p&gt;First, participants were invited to think in small groups about four ways to make their research less (sic!) reproducible (while still making a career in science). Afterward, the groups moved to another flip chart to expand on their predecessor’s ideas. Again, the prompt was to make their work as least reproducible as possible.&lt;/p&gt;
&lt;p&gt;Participants were then invited to walk through the room, look at the posters, and pick a few ideas that they found most impactful in their own subfield of Computer Science. They labeled those ideas with post-it notes. During the last exercise, participants discussed in larger groups four different aspects of non-reproducible science: “Use overcomplicated theory”, “Use proprietary data/software”, “Require expensive tech” and “Do not share code/data”.&lt;/p&gt;
&lt;p&gt;Thinking about the opposite of what you set out to achieve was counterintuitive for some participants, while others said “This is easy, I just describe all of my frustrations. Research that I encounter in my daily work is in large parts non-reproducible”. I didn’t give a definition of what Reproducibility means or how the term is defined for the purpose of the workshop at the beginning. This was intentional, as I was hoping to gather as many ideas as possible, without influencing people’s understanding of reproducible research. As a researcher with a background in the social sciences who has discussed reproducibility of research mainly with open science enthusiasts from the social sciences, I found it important to keep as much of my previous understanding of reproducibility outside the workshop room.&lt;/p&gt;
&lt;p&gt;This workshop provided a glimpse into what computer scientists feel is important in achieving reproducibility and how this might differ from other areas of research. The use of expensive computing power or annotations is not often mentioned when I talk to psychologists, for example. I was surprised how often participants mentioned overly complicated theory as a barrier to reproducibility. Using version control to keep track of changes in code was only mentioned in passing. It didn’t seem to be on participants’ minds, while this is something I keep on hearing about in my own Open Science bubble.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What did I learn?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Giving participants a lot of freedom by keeping definitions to a minimum allows participants to share their understanding. It can also lead to frustrations from people who like to set a framework for themselves before starting creative work. Inviting everyone to participate and share their ideas is a key ingredient to running a workshop where all participants are happy with the outcomes.&lt;/li&gt;
&lt;li&gt;Asking people to describe their field of research leads to answers that are difficult to use and interpret. Answers like “Human Centered Interaction/ Data and Visual Analytics“ make it hard to categorize responses into just one subcategory (in this case Human Computer Interaction or Data Science). Another question is how to split Data Science, AI and ML. Especially if people describe their work as “AI/ML” or other combinations.&lt;/li&gt;
&lt;li&gt;There was a lot more input we didn’t have time to explore. For the second part of the workshop, we picked four topics to further focus on. Other barriers to reproducibility that were mentioned by participants, but couldn’t be discussed further include: “Poorly conceptualized Desk Research”, “System Design without clear Problem description”, “Don’t explain the Evaluation, Say “well-established procedures” “, “50.000 Annotators Needed”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This workshop, as well as a few interviews with Computer Scientists at Leiden University, informed a survey that will be sent out in September 2023 to computer scientists working in the Netherlands. Recruitment for that survey will happen via the research schools SIKS and ASCI, social media and word of mouth. &lt;a href=&quot;https://danielagawehns.github.io/&quot;&gt;Please let me know&lt;/a&gt; if you know of a good way to reach a diverse group of survey respondents from the computer sciences.&lt;/p&gt;
&lt;p&gt;The proceedings of the &lt;a href=&quot;https://dl.acm.org/doi/proceedings/10.1145/3589806&quot;&gt;ACM REP conference&lt;/a&gt; are a good starting point for anyone interested in the topic of reproducible computer science. You can find a collection of materials in several community calls on the topic of reproducibility in Computer Science &lt;a href=&quot;https://reproducibility.acm.org/blog/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A transcript of the flip charts created during the workshop can be found &lt;a href=&quot;https://docs.google.com/document/d/1QdL4YY6RUzJkz3juMM_HDuwzrSNGNBbX1hXbgm39OtQ/edit?usp=sharing&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 21 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;do-you-have-50000-annotators&quot;&gt;&lt;strong&gt;Do you have 50.000 annotators?&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;*Written by eScience Center Fellow, *&lt;a href=&quot;https://www.esciencecenter.nl/fellows/daniela-gawehns/&quot;&gt;&lt;em&gt;Daniela Gawehns&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Do you have 50.000 annotators?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/do-you-have-50000-annotators-9925b35a.DQcEXpIh_Z6PdAr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://www.shutterstock.com/image-photo/business-people-diverse-brainstorm-meeting-concept-388995775&quot;&gt;Shutterstock&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;During ICT.open 2023, I organized a workshop for 40 computer scientists on reproducibility in computer science. This is a short summary of the main results and how I experienced the workshop as a moderator.&lt;/p&gt;
&lt;p&gt;The workshop was part of &lt;a href=&quot;https://www.esciencecenter.nl/fellowship-programme/&quot;&gt;my fellowship project&lt;/a&gt; at the eScience Center to find out how people in the computer sciences understand reproducibility. The idea behind the project is that communities of researchers differ in how they understand the term reproducibility. Before providing tools, guidance or incentives on how to make research outputs more reproducible, we need to figure out what people understand as reproducible research.&lt;/p&gt;
&lt;p&gt;What happened?**&lt;/p&gt;
&lt;p&gt;First, participants were invited to think in small groups about four ways to make their research less (sic!) reproducible (while still making a career in science). Afterward, the groups moved to another flip chart to expand on their predecessor’s ideas. Again, the prompt was to make their work as least reproducible as possible.&lt;/p&gt;
&lt;p&gt;Participants were then invited to walk through the room, look at the posters, and pick a few ideas that they found most impactful in their own subfield of Computer Science. They labeled those ideas with post-it notes. During the last exercise, participants discussed in larger groups four different aspects of non-reproducible science: “Use overcomplicated theory”, “Use proprietary data/software”, “Require expensive tech” and “Do not share code/data”.&lt;/p&gt;
&lt;p&gt;Thinking about the opposite of what you set out to achieve was counterintuitive for some participants, while others said “This is easy, I just describe all of my frustrations. Research that I encounter in my daily work is in large parts non-reproducible”. I didn’t give a definition of what Reproducibility means or how the term is defined for the purpose of the workshop at the beginning. This was intentional, as I was hoping to gather as many ideas as possible, without influencing people’s understanding of reproducible research. As a researcher with a background in the social sciences who has discussed reproducibility of research mainly with open science enthusiasts from the social sciences, I found it important to keep as much of my previous understanding of reproducibility outside the workshop room.&lt;/p&gt;
&lt;p&gt;This workshop provided a glimpse into what computer scientists feel is important in achieving reproducibility and how this might differ from other areas of research. The use of expensive computing power or annotations is not often mentioned when I talk to psychologists, for example. I was surprised how often participants mentioned overly complicated theory as a barrier to reproducibility. Using version control to keep track of changes in code was only mentioned in passing. It didn’t seem to be on participants’ minds, while this is something I keep on hearing about in my own Open Science bubble.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What did I learn?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Giving participants a lot of freedom by keeping definitions to a minimum allows participants to share their understanding. It can also lead to frustrations from people who like to set a framework for themselves before starting creative work. Inviting everyone to participate and share their ideas is a key ingredient to running a workshop where all participants are happy with the outcomes.&lt;/li&gt;
&lt;li&gt;Asking people to describe their field of research leads to answers that are difficult to use and interpret. Answers like “Human Centered Interaction/ Data and Visual Analytics“ make it hard to categorize responses into just one subcategory (in this case Human Computer Interaction or Data Science). Another question is how to split Data Science, AI and ML. Especially if people describe their work as “AI/ML” or other combinations.&lt;/li&gt;
&lt;li&gt;There was a lot more input we didn’t have time to explore. For the second part of the workshop, we picked four topics to further focus on. Other barriers to reproducibility that were mentioned by participants, but couldn’t be discussed further include: “Poorly conceptualized Desk Research”, “System Design without clear Problem description”, “Don’t explain the Evaluation, Say “well-established procedures” “, “50.000 Annotators Needed”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This workshop, as well as a few interviews with Computer Scientists at Leiden University, informed a survey that will be sent out in September 2023 to computer scientists working in the Netherlands. Recruitment for that survey will happen via the research schools SIKS and ASCI, social media and word of mouth. &lt;a href=&quot;https://danielagawehns.github.io/&quot;&gt;Please let me know&lt;/a&gt; if you know of a good way to reach a diverse group of survey respondents from the computer sciences.&lt;/p&gt;
&lt;p&gt;The proceedings of the &lt;a href=&quot;https://dl.acm.org/doi/proceedings/10.1145/3589806&quot;&gt;ACM REP conference&lt;/a&gt; are a good starting point for anyone interested in the topic of reproducible computer science. You can find a collection of materials in several community calls on the topic of reproducibility in Computer Science &lt;a href=&quot;https://reproducibility.acm.org/blog/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A transcript of the flip charts created during the workshop can be found &lt;a href=&quot;https://docs.google.com/document/d/1QdL4YY6RUzJkz3juMM_HDuwzrSNGNBbX1hXbgm39OtQ/edit?usp=sharing&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/do-you-have-50000-annotators-9925b35a.DQcEXpIh.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>ESMValTool: Recipes for solid climate science</title><link>https://blog2.esciencecenter.nl/posts/2023-09-11---esmvaltool-recipes-for-solid-climate-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-09-11---esmvaltool-recipes-for-solid-climate-science</guid><description>&lt;h1 id=&quot;esmvaltool-recipes-for-solid-climate-science&quot;&gt;&lt;strong&gt;ESMValTool: Recipes for solid climate science&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;*This story was coauthored by &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-peter-kalverla/&quot;&gt;&lt;em&gt;Peter Kalverla&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and *&lt;a href=&quot;https://www.esciencecenter.nl/team/bouwe-andela-msc/&quot;&gt;&lt;em&gt;Bouwe Andela&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Like an artisan chef can improvise a delicious meal, so too can a scientist create new insights from raw data and exploratory analysis. But to run a successful restaurant with personnel and a consistent menu, our chef resorts to writing down his recipes. Similarly, we scientists must make an effort if we want our results to be consistent and widely reusable.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-9ecc0726.TI0_OHJi_2ekT7l.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@novokayn?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Pylyp Sukhenko&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;This is where &lt;a href=&quot;https://esmvaltool.org/&quot;&gt;ESMValTool &lt;/a&gt;comes into play. Designed to ease and automate the analysis of large ensembles of climate model outputs, ESMValTool defines a clear and plain scientific [“recipe” format](&lt;a href=&quot;https://docs.esmvaltool.org/projects/ESMVal&quot;&gt;https://docs.esmvaltool.org/projects/ESMVal&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Core/en/latest/recipe/overview.html). This not only helps to make workflows scientifically robust, but also provides a way to easily share and build upon each others’ work. Even if you’re not a climate scientist, there are valuable lessons to draw from ESMValTool’s approach to FAIR and open science.&lt;/p&gt;
&lt;p&gt;In this blogpost, we’ll explore four aspects of ESMValTool that may be worth your while. Starting with its take on analysis-ready data and its rich suite of pre-processor functions, we’ll set the stage for a broader discussion on how standardization helps making research easy and FAIR and the crucial role of a community in setting itself up for success.&lt;/p&gt;
&lt;h2 id=&quot;analysis-ready-cmip-data&quot;&gt;Analysis-ready (CMIP) data**&lt;/h2&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Strictly speaking, most of the functionality described here is part of ESMValCore. ESMValCore is the engine, if you will, that executes ESMValTool recipes under the hood. ESMValTool, then, is a big collection of recipes. To the user of ESMValTool, this distinction is irrelevant, but we’ll use the terms interchangeably to be as accurate as possible. For a description of ESMValCore as a standalone utility, see the companion blogpost.&lt;/p&gt;
&lt;p&gt;ESMValTool was originally designed for the analysis of CMIP data: output of many climate models assembled in a series of “Coupled Model Intercomparison Projects”. The CMIP &lt;a href=&quot;https://wcrp-cmip.github.io/WGCM_Infrastructure_Panel/CMIP6/data_request.html&quot;&gt;data request&lt;/a&gt; specifies standards that the data should adhere to. Known as the &lt;a href=&quot;https://pcmdi.llnl.gov/software/cmorTable/index.html&quot;&gt;CMOR standards&lt;/a&gt;, after the “Climate Model Output Rewriter” software, they describe things like variable names, units, coordinates (with their direction), and also file name conventions. These standards make it much easier to compare output from different climate models, and they are the foundation on which ESMValTool &amp;#x26; Core were built.&lt;/p&gt;
&lt;p&gt;For example, the file name conventions make it possible to specify a dataset like so:&lt;/p&gt;
&lt;p&gt;Dataset(**    short_name = ‘tos’,
mip = ‘Omon’,
project = ‘CMIP6’,
exp = ‘historical’,
dataset = ‘CESM2’,
ensemble = ‘r4i1p1f1’,
grid = ‘gn’
)and ESMValCore is able to locate it, both on your local computer or on &lt;a href=&quot;https://esgf.llnl.gov/&quot;&gt;ESGF&lt;/a&gt;, the shared infrastructure where all of the CMIP data are collected. ESMValCore can automatically download data from ESGF, provided that the data is present there.&lt;/p&gt;
&lt;p&gt;Pause a moment to let this sink in: ESMValCore eliminates hardcoded paths in your scripts, or rather, recipes. This is key to making them interoperable.&lt;/p&gt;
&lt;p&gt;If you’ve worked with CMIP data yourself, you’ll probably know that, despite the strict protocol, small dataset issues are commonplace. That’s why ESMValCore executes an additional CMOR check upon data loading. Where possible, it applies automatic fixes for known and trivial issues. This makes working with the data much easier.&lt;/p&gt;
&lt;p&gt;Another common issue with CMIP data is that files may not or no longer be available. ESMValCore makes it easy to perform wildcard searches or ignore missing datasets, saving you the trouble of figuring out which datasets are available or have been retracted since the last time you ran your recipe. Thus, ESMValCore is also a great utility for CMIP data discovery.&lt;/p&gt;
&lt;p&gt;While ESMValTool &amp;#x26; Core were originally developed for CMIP data, it also supports ingestion of other datasets. For example, it can apply “on the fly CMORization” of ERA5 data, and it ships with download and “CMORizer” scripts for many other (observational) datasets. This makes ESMValTool more broadly applicable and moreover, it promotes standardization beyond its original scope.&lt;/p&gt;
&lt;p&gt;To summarize, ESMValTool makes it easy to get to your data. In the next section, we’ll describe how ESMValTool also helps to standardize how you process it (without compromising on versatility).&lt;/p&gt;
&lt;h2 id=&quot;esmvalcores-rich-preprocessor-suite&quot;&gt;ESMValCore’s rich preprocessor suite**&lt;/h2&gt;
&lt;p&gt;Like with a kitchen recipe, after the ingredients come the preparation steps. In ESMValTool &amp;#x26; Core, they are called pre-processors. Common preps for climate data include regridding, area extraction, calculating anomalies and all kinds of statistics.&lt;/p&gt;
&lt;p&gt;ESMValCore has built-in functions for each of these pre-processors, and they can be added to a recipe using a very high-level specification. For example:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;226&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-d3a6c4c4.DFn5tAf4_Z1OGbrR.webp&quot; srcset=&quot;&quot;&gt;
Part of an ESMValTool a recipe listing the pre-processing steps that should be appliedBy reading this snippet, you can probably get a pretty good idea of what this recipe is trying to achieve: the mean (temperature) change over Europe with respect to a reference period. This is a declarative syntax, focusing on &lt;em&gt;what&lt;/em&gt; should be done, instead of &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ideally, with ESMValCore, the standard pre-processors provide a scientifically sound consensus implementation. For example, it uses state-of-the-art regridding with ESMF/ESMPy, and strict CF-compliant statistics from the Iris package. These functions have been designed by domain experts and are openly developed, so anyone can suggest improvements if they feel the current implementation is insufficient. ESMValCore executes these steps in a standard order which makes sense for most applications. However, you can also specify a custom order as this might make sense for some specific use cases.&lt;/p&gt;
&lt;p&gt;In the illustration below, you can see the default order in which the pre-processors are executed. In your recipe, you can simply select those steps that are relevant for your workflow.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;352&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-3ba2f9e1.D73OQFGO_1LykGp.webp&quot; srcset=&quot;&quot;&gt;
The architecture of ESMValTool: recipe specifies which input data is loaded. This data is then ingested and the preprocessor steps specified in the recipe are executed. Finally, pre-processed data is passed onto a diagnostic script to generate the final output.After prepping, your data is (optionally) passed on to a diagnostic script. This is the place where you can do custom things, such as making a figure, or doing a more thorough and case-specific analysis. “Combining the ingredients into a tasty dish”, to stick with the chef’s analogy.&lt;/p&gt;
&lt;p&gt;So far, we’ve seen how ESMValTool tries to streamline those parts of your analysis workflow that can be standardized, and tries to accomodate all specific things you might need or want. In the next section, we’ll see how this helps you make your research more &lt;a href=&quot;https://www.nature.com/articles/s41597-022-01710-x&quot;&gt;FAIR&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fair-and-open-science&quot;&gt;FAIR and open science**&lt;/h2&gt;
&lt;p&gt;ESMValTool is a great example of how open science can work in practice.&lt;/p&gt;
&lt;p&gt;Recently there’s been an increased focus on accessibility, transpancy, and &lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/reproducible-research.html&quot;&gt;reproducibility &lt;/a&gt;in science. We’ve seen the advent of open access publications, the introduction of FAIR &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;standards &lt;/a&gt;for research data management. It’s easy to extrapolate these ideas to other aspects of the research process as well. At the same time, this can be daunting, because it may seem like a lot of extra work that you might not have the time or skills for. So let’s see how ESMValTool helps with these concerns.&lt;/p&gt;
&lt;p&gt;One ideal that’s often associated with open science is reciprocity, which we all know in &lt;a href=&quot;https://genius.com/27629118&quot;&gt;lyrical form&lt;/a&gt; as “never take more than you give”. The idea is that scientific progress benefits from mutual exchange and building upon each other’s work. ESMValTool provides a platform for receiving and giving back. By making available a large suite of recipes that other people have already composed. By establishing a process to contribute your own recipes. By setting a standard format to encode recipes. By integrating existing functionality into a streamlined workflow system. And by facilitating a process of feedback based around users’ contributions, and a forum for discussion. Many of the things that are hard to organize on your own, have already been organized by the ESMValTool community. Thus, you’ll be greeted with a warm welcome instead of a daunting prospect.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-fd3a27a4.DxpAYR-F_Z2nruy3.webp&quot; srcset=&quot;&quot;&gt;
Illustration from the Turing way book dashes.Going more into the specifics of FAIR, we can see how ESMValTool contributes: ESMValTool has great documentation listing all &lt;a href=&quot;https://docs.esmvaltool.org/en/latest/recipes/index.html&quot;&gt;available recipes&lt;/a&gt; and a gallery with outputs. You can also list the available recipes from within the software, or browse the &lt;a href=&quot;https://github.com/ESMValGroup/ESMValTool/tree/main/esmvaltool/recipes&quot;&gt;source code&lt;/a&gt;. So recipes are quite findable, although you could still take it a step further by creating a searchable registry with unique identifiers for each recipe (Note that the package as a whole does have a &lt;a href=&quot;https://doi.org/10.5281/zenodo.3401363&quot;&gt;DOI&lt;/a&gt; for each version).&lt;/p&gt;
&lt;p&gt;ESMValTool recipes are also very accessible. The YAML format is very readable for humans and also by machines; they can be executed. As we’ve seen above recipes are also portable: hardcoded file paths et cetera have been eliminated. For each release of ESMValTool, all recipes are executed to see if they still work, and output is made available.&lt;/p&gt;
&lt;p&gt;To summarize, ESMValTool itself would qualify as “FAIR software. But moreover, ESMValTool recipes also come a long way as “FAIR scientific workflows”. Just like kitchen recipes empower chefs, ESMValTool recipes empower scientists.&lt;/p&gt;
&lt;h2 id=&quot;the-crucial-role-of-community&quot;&gt;&lt;strong&gt;The crucial role of community&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;ESMValTool would not have been where it is now if it wasn’t for the community. The ESMValTool community is a nice and welcoming crowd of scientists and software engineers from various institutes in Europe and beyond. In addition to lively interactions on GitHub there are monthly online meetings that are open to all, and there’s an in-person workshop once or twice a year. Furthermore there are spontaneous gatherings of ESMValTool contributors at other ocassions such as conferences.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;340&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-a4ea8d51.Cx9hSZoT_29CzAr.webp&quot; srcset=&quot;&quot;&gt;
Screenshot of the ESMValTool discussion forum announcing some of the community gatherings.Over the years the ‘core team’ has gained a lot of experience and become more professional, for example when it comes to processes for decision making and user engagement. There are clear guidelines for contributing to the codebase, and people are always willing to help each other out. To support new users, the user engagement team maintains a &lt;a href=&quot;https://tutorial.esmvaltool.org/&quot;&gt;tutorial &lt;/a&gt;that is regularly taught.&lt;/p&gt;
&lt;p&gt;By fostering enjoyable and personal interaction, the community plays a vital role in facilitating the development and long-term sustainability of ESMValTool.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In conclusion, ESMValTool provides a valuable platform for scientists to achieve consistency, reusability, and standardization in their research, owing much of its current success to the dedicated community that surrounds it.&lt;/p&gt;
&lt;p&gt;Are you a climate scientists and do you want to be part of this community? Don’t hesitate to reach out on GitHub or another channel that you see fit. Are you passionate about open science but not necessarily in climate science? Then we hope you could get some nice takeaways from ESMValTools experience and we are always happy to exchange more. In any case, the next time you visit a restaurant, remember to appreciate not only the chef but also the thoughtfully curated menu.&lt;/p&gt;</description><pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;esmvaltool-recipes-for-solid-climate-science&quot;&gt;&lt;strong&gt;ESMValTool: Recipes for solid climate science&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;*This story was coauthored by &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-peter-kalverla/&quot;&gt;&lt;em&gt;Peter Kalverla&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and *&lt;a href=&quot;https://www.esciencecenter.nl/team/bouwe-andela-msc/&quot;&gt;&lt;em&gt;Bouwe Andela&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Like an artisan chef can improvise a delicious meal, so too can a scientist create new insights from raw data and exploratory analysis. But to run a successful restaurant with personnel and a consistent menu, our chef resorts to writing down his recipes. Similarly, we scientists must make an effort if we want our results to be consistent and widely reusable.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-9ecc0726.TI0_OHJi_2ekT7l.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@novokayn?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Pylyp Sukhenko&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;This is where &lt;a href=&quot;https://esmvaltool.org/&quot;&gt;ESMValTool &lt;/a&gt;comes into play. Designed to ease and automate the analysis of large ensembles of climate model outputs, ESMValTool defines a clear and plain scientific [“recipe” format](&lt;a href=&quot;https://docs.esmvaltool.org/projects/ESMVal&quot;&gt;https://docs.esmvaltool.org/projects/ESMVal&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Core/en/latest/recipe/overview.html). This not only helps to make workflows scientifically robust, but also provides a way to easily share and build upon each others’ work. Even if you’re not a climate scientist, there are valuable lessons to draw from ESMValTool’s approach to FAIR and open science.&lt;/p&gt;
&lt;p&gt;In this blogpost, we’ll explore four aspects of ESMValTool that may be worth your while. Starting with its take on analysis-ready data and its rich suite of pre-processor functions, we’ll set the stage for a broader discussion on how standardization helps making research easy and FAIR and the crucial role of a community in setting itself up for success.&lt;/p&gt;
&lt;h2 id=&quot;analysis-ready-cmip-data&quot;&gt;Analysis-ready (CMIP) data**&lt;/h2&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Strictly speaking, most of the functionality described here is part of ESMValCore. ESMValCore is the engine, if you will, that executes ESMValTool recipes under the hood. ESMValTool, then, is a big collection of recipes. To the user of ESMValTool, this distinction is irrelevant, but we’ll use the terms interchangeably to be as accurate as possible. For a description of ESMValCore as a standalone utility, see the companion blogpost.&lt;/p&gt;
&lt;p&gt;ESMValTool was originally designed for the analysis of CMIP data: output of many climate models assembled in a series of “Coupled Model Intercomparison Projects”. The CMIP &lt;a href=&quot;https://wcrp-cmip.github.io/WGCM_Infrastructure_Panel/CMIP6/data_request.html&quot;&gt;data request&lt;/a&gt; specifies standards that the data should adhere to. Known as the &lt;a href=&quot;https://pcmdi.llnl.gov/software/cmorTable/index.html&quot;&gt;CMOR standards&lt;/a&gt;, after the “Climate Model Output Rewriter” software, they describe things like variable names, units, coordinates (with their direction), and also file name conventions. These standards make it much easier to compare output from different climate models, and they are the foundation on which ESMValTool &amp;#x26; Core were built.&lt;/p&gt;
&lt;p&gt;For example, the file name conventions make it possible to specify a dataset like so:&lt;/p&gt;
&lt;p&gt;Dataset(**    short_name = ‘tos’,
mip = ‘Omon’,
project = ‘CMIP6’,
exp = ‘historical’,
dataset = ‘CESM2’,
ensemble = ‘r4i1p1f1’,
grid = ‘gn’
)and ESMValCore is able to locate it, both on your local computer or on &lt;a href=&quot;https://esgf.llnl.gov/&quot;&gt;ESGF&lt;/a&gt;, the shared infrastructure where all of the CMIP data are collected. ESMValCore can automatically download data from ESGF, provided that the data is present there.&lt;/p&gt;
&lt;p&gt;Pause a moment to let this sink in: ESMValCore eliminates hardcoded paths in your scripts, or rather, recipes. This is key to making them interoperable.&lt;/p&gt;
&lt;p&gt;If you’ve worked with CMIP data yourself, you’ll probably know that, despite the strict protocol, small dataset issues are commonplace. That’s why ESMValCore executes an additional CMOR check upon data loading. Where possible, it applies automatic fixes for known and trivial issues. This makes working with the data much easier.&lt;/p&gt;
&lt;p&gt;Another common issue with CMIP data is that files may not or no longer be available. ESMValCore makes it easy to perform wildcard searches or ignore missing datasets, saving you the trouble of figuring out which datasets are available or have been retracted since the last time you ran your recipe. Thus, ESMValCore is also a great utility for CMIP data discovery.&lt;/p&gt;
&lt;p&gt;While ESMValTool &amp;#x26; Core were originally developed for CMIP data, it also supports ingestion of other datasets. For example, it can apply “on the fly CMORization” of ERA5 data, and it ships with download and “CMORizer” scripts for many other (observational) datasets. This makes ESMValTool more broadly applicable and moreover, it promotes standardization beyond its original scope.&lt;/p&gt;
&lt;p&gt;To summarize, ESMValTool makes it easy to get to your data. In the next section, we’ll describe how ESMValTool also helps to standardize how you process it (without compromising on versatility).&lt;/p&gt;
&lt;h2 id=&quot;esmvalcores-rich-preprocessor-suite&quot;&gt;ESMValCore’s rich preprocessor suite**&lt;/h2&gt;
&lt;p&gt;Like with a kitchen recipe, after the ingredients come the preparation steps. In ESMValTool &amp;#x26; Core, they are called pre-processors. Common preps for climate data include regridding, area extraction, calculating anomalies and all kinds of statistics.&lt;/p&gt;
&lt;p&gt;ESMValCore has built-in functions for each of these pre-processors, and they can be added to a recipe using a very high-level specification. For example:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;226&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-d3a6c4c4.DFn5tAf4_Z1OGbrR.webp&quot; srcset=&quot;&quot;&gt;
Part of an ESMValTool a recipe listing the pre-processing steps that should be appliedBy reading this snippet, you can probably get a pretty good idea of what this recipe is trying to achieve: the mean (temperature) change over Europe with respect to a reference period. This is a declarative syntax, focusing on &lt;em&gt;what&lt;/em&gt; should be done, instead of &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ideally, with ESMValCore, the standard pre-processors provide a scientifically sound consensus implementation. For example, it uses state-of-the-art regridding with ESMF/ESMPy, and strict CF-compliant statistics from the Iris package. These functions have been designed by domain experts and are openly developed, so anyone can suggest improvements if they feel the current implementation is insufficient. ESMValCore executes these steps in a standard order which makes sense for most applications. However, you can also specify a custom order as this might make sense for some specific use cases.&lt;/p&gt;
&lt;p&gt;In the illustration below, you can see the default order in which the pre-processors are executed. In your recipe, you can simply select those steps that are relevant for your workflow.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;352&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-3ba2f9e1.D73OQFGO_1LykGp.webp&quot; srcset=&quot;&quot;&gt;
The architecture of ESMValTool: recipe specifies which input data is loaded. This data is then ingested and the preprocessor steps specified in the recipe are executed. Finally, pre-processed data is passed onto a diagnostic script to generate the final output.After prepping, your data is (optionally) passed on to a diagnostic script. This is the place where you can do custom things, such as making a figure, or doing a more thorough and case-specific analysis. “Combining the ingredients into a tasty dish”, to stick with the chef’s analogy.&lt;/p&gt;
&lt;p&gt;So far, we’ve seen how ESMValTool tries to streamline those parts of your analysis workflow that can be standardized, and tries to accomodate all specific things you might need or want. In the next section, we’ll see how this helps you make your research more &lt;a href=&quot;https://www.nature.com/articles/s41597-022-01710-x&quot;&gt;FAIR&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;fair-and-open-science&quot;&gt;FAIR and open science**&lt;/h2&gt;
&lt;p&gt;ESMValTool is a great example of how open science can work in practice.&lt;/p&gt;
&lt;p&gt;Recently there’s been an increased focus on accessibility, transpancy, and &lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/reproducible-research.html&quot;&gt;reproducibility &lt;/a&gt;in science. We’ve seen the advent of open access publications, the introduction of FAIR &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;standards &lt;/a&gt;for research data management. It’s easy to extrapolate these ideas to other aspects of the research process as well. At the same time, this can be daunting, because it may seem like a lot of extra work that you might not have the time or skills for. So let’s see how ESMValTool helps with these concerns.&lt;/p&gt;
&lt;p&gt;One ideal that’s often associated with open science is reciprocity, which we all know in &lt;a href=&quot;https://genius.com/27629118&quot;&gt;lyrical form&lt;/a&gt; as “never take more than you give”. The idea is that scientific progress benefits from mutual exchange and building upon each other’s work. ESMValTool provides a platform for receiving and giving back. By making available a large suite of recipes that other people have already composed. By establishing a process to contribute your own recipes. By setting a standard format to encode recipes. By integrating existing functionality into a streamlined workflow system. And by facilitating a process of feedback based around users’ contributions, and a forum for discussion. Many of the things that are hard to organize on your own, have already been organized by the ESMValTool community. Thus, you’ll be greeted with a warm welcome instead of a daunting prospect.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-fd3a27a4.DxpAYR-F_Z2nruy3.webp&quot; srcset=&quot;&quot;&gt;
Illustration from the Turing way book dashes.Going more into the specifics of FAIR, we can see how ESMValTool contributes: ESMValTool has great documentation listing all &lt;a href=&quot;https://docs.esmvaltool.org/en/latest/recipes/index.html&quot;&gt;available recipes&lt;/a&gt; and a gallery with outputs. You can also list the available recipes from within the software, or browse the &lt;a href=&quot;https://github.com/ESMValGroup/ESMValTool/tree/main/esmvaltool/recipes&quot;&gt;source code&lt;/a&gt;. So recipes are quite findable, although you could still take it a step further by creating a searchable registry with unique identifiers for each recipe (Note that the package as a whole does have a &lt;a href=&quot;https://doi.org/10.5281/zenodo.3401363&quot;&gt;DOI&lt;/a&gt; for each version).&lt;/p&gt;
&lt;p&gt;ESMValTool recipes are also very accessible. The YAML format is very readable for humans and also by machines; they can be executed. As we’ve seen above recipes are also portable: hardcoded file paths et cetera have been eliminated. For each release of ESMValTool, all recipes are executed to see if they still work, and output is made available.&lt;/p&gt;
&lt;p&gt;To summarize, ESMValTool itself would qualify as “FAIR software. But moreover, ESMValTool recipes also come a long way as “FAIR scientific workflows”. Just like kitchen recipes empower chefs, ESMValTool recipes empower scientists.&lt;/p&gt;
&lt;h2 id=&quot;the-crucial-role-of-community&quot;&gt;&lt;strong&gt;The crucial role of community&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;ESMValTool would not have been where it is now if it wasn’t for the community. The ESMValTool community is a nice and welcoming crowd of scientists and software engineers from various institutes in Europe and beyond. In addition to lively interactions on GitHub there are monthly online meetings that are open to all, and there’s an in-person workshop once or twice a year. Furthermore there are spontaneous gatherings of ESMValTool contributors at other ocassions such as conferences.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;ESMValTool: Recipes for solid climate science&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;340&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-a4ea8d51.Cx9hSZoT_29CzAr.webp&quot; srcset=&quot;&quot;&gt;
Screenshot of the ESMValTool discussion forum announcing some of the community gatherings.Over the years the ‘core team’ has gained a lot of experience and become more professional, for example when it comes to processes for decision making and user engagement. There are clear guidelines for contributing to the codebase, and people are always willing to help each other out. To support new users, the user engagement team maintains a &lt;a href=&quot;https://tutorial.esmvaltool.org/&quot;&gt;tutorial &lt;/a&gt;that is regularly taught.&lt;/p&gt;
&lt;p&gt;By fostering enjoyable and personal interaction, the community plays a vital role in facilitating the development and long-term sustainability of ESMValTool.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In conclusion, ESMValTool provides a valuable platform for scientists to achieve consistency, reusability, and standardization in their research, owing much of its current success to the dedicated community that surrounds it.&lt;/p&gt;
&lt;p&gt;Are you a climate scientists and do you want to be part of this community? Don’t hesitate to reach out on GitHub or another channel that you see fit. Are you passionate about open science but not necessarily in climate science? Then we hope you could get some nice takeaways from ESMValTools experience and we are always happy to exchange more. In any case, the next time you visit a restaurant, remember to appreciate not only the chef but also the thoughtfully curated menu.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/esmvaltool-recipes-for-solid-climate-sci-9ecc0726.TI0_OHJi.jpg" medium="image"/><author>Peter Kalverla</author></item><item><title>Coming Soon: Conditional Process Models in JASP</title><link>https://blog2.esciencecenter.nl/posts/2023-08-31---coming-soon-conditional-process-models-in-jasp</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-08-31---coming-soon-conditional-process-models-in-jasp</guid><description>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/malte-luken/&quot;&gt;Malte Lüken&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/thijs-vroegh/&quot;&gt;Thijs Vroegh&lt;/a&gt;, &lt;a href=&quot;https://www.uva.nl/en/profile/d/o/j.b.vandoorn/j.b.vandoorn.html&quot;&gt;Johnny van Doorn&lt;/a&gt;, and &lt;a href=&quot;https://www.uva.nl/en/profile/w/a/e.m.wagenmakers/e.m.wagenmakers.html&quot;&gt;Eric-Jan Wagenmakers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post is also published on the JASP &lt;em&gt;&lt;a href=&quot;https://jasp-stats.org/blog/&quot;&gt;&lt;em&gt;blog&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-28f59e63.BvDjMAD5_Z1hQvP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@humakabakci?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Huma Kabakci&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;
&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-1571ecc2.wAju-tYr_2e1nej.webp&quot; srcset=&quot;&quot;&gt;
Many students, teachers and researchers use the popular &lt;a href=&quot;https://www.processmacro.org/&quot;&gt;PROCESS&lt;/a&gt; macro for SPSS (Hayes, 2022a, 2022b) to estimate conditional process models involving mediation and moderation effects. Recently, however, these models were also criticized because they make causal assumptions, which do not hold in many applied settings (Bullock et al., 2010, Rohrer et al., 2022). The popularity and criticism warrant a new module to make conditional process models easily accessible to the JASP community. Moreover, the module should provide a better understanding of the underlying causal assumptions for users and tools to explicitly test them. The JASP Team and the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; are currently working on such an endeavor, and we give a short teaser in this blog post.&lt;/p&gt;
&lt;h2 id=&quot;estimating-models-as-in-spss&quot;&gt;Estimating Models as in SPSS&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;928&quot; height=&quot;572&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-c574f468.CqYvTdHT_Z1HpGWI.webp&quot; srcset=&quot;&quot;&gt;
The new &lt;em&gt;Process&lt;/em&gt; module has two graphical user interfaces: One interface resembles the interface of the original SPSS macro where users first select a model configuration from a predefined list. In contrast to SPSS, JASP immediately shows the user a graphical representation of the specified model (i.e., a path plot), which facilitates the search for the right model. As the user adds more variables to the model, the graphical representation is updated. The module will provide both conceptual and statistical path plots, where the statistical path plot includes the estimated parameters.&lt;/p&gt;
&lt;h2 id=&quot;building-models-step-by-step&quot;&gt;Building Models Step-by-step&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;928&quot; height=&quot;573&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-da35f929.CqlR2qB3_1bgfQX.webp&quot; srcset=&quot;&quot;&gt;
With a second, complementary interface users can build models step-by-step starting from scratch. They can iteratively add paths (i.e., relations) between selected variables and define how other variables influence each path (e.g., through mediation or moderation). Below, we reproduce predefined Model 5 with two path specifications: We first add a path between Extraversion and Neuroticism (X and Y) and specify Openness as a mediator for this path (M). Then, we add a second path specification between Extraversion and Neuroticism, but this time we include Agreeableness as a moderator for this path (W). Again, every time a path is added or modified, JASP will immediately show the user the corresponding graphical representation of the model to facilitate the model-building process. This approach enables users to build models intuitively and flexibly, avoiding the restrictions of predefined model configurations.&lt;/p&gt;
&lt;h2 id=&quot;addressing-criticisms-of-process-models&quot;&gt;Addressing Criticisms of Process Models&lt;/h2&gt;
&lt;p&gt;Conditional process models make strong causal assumptions about the relationships between variables. A mediation model, for example, states that there is a causal relationship from X to Y, X to M, as well as M to Y. Critics have argued that researchers cannot assume these causal assumptions to hold in most applications, even in experimental settings (Bullock et al., 2010, Rohrer et al., 2022). In the new module, we aim to address some of these arguments by making the causal assumptions more explicit via footnotes and warnings. Importantly, we will also enable users to test the statistical patterns implied by the causal assumptions (i.e., via conditional independence tests; see Rohrer et al., 2022). Users can then conclude which assumptions are violated and modify their model or experimental design accordingly. Because of its step-by-step interface, the module allows users to build more complex models to accommodate the requirements of their application (e.g., by adding confounding variables to different paths). Despite these features, many challenges remain when applying conditional process models, most of which are related to careful experimental design (see Bullock et al., 2010). We aim to draw the users’ attention to these challenges and improve the statistical use of process models in practice.&lt;/p&gt;
&lt;h2 id=&quot;behind-the-project&quot;&gt;Behind the Project&lt;/h2&gt;
&lt;p&gt;This project is a collaboration between the JASP Team and the Netherlands eScience Center. As the national institute for research software, the Netherlands eScience Center awards projects as part of calls for proposals. Instead of monetary funding, it provides in-kind support by Research Software Engineers to create innovative digital solutions. This project was granted as part of the Small-Scale Initiatives Digital Approaches to the Social Sciences call 2022.&lt;/p&gt;
&lt;p&gt;We kindly thank &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;&lt;em&gt;Tom Bakker&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;&lt;em&gt;Lieke de Boer&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; for providing feedback on earlier versions of this post.*&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Bullock, J. G., Green, D. P., &amp;#x26; Ha, S. E. (2010). Yes, but what’s the mechanism? (don’t expect an easy answer). &lt;em&gt;Journal of Personality and Social Psychology, 98&lt;/em&gt;(4), 550–558. &lt;a href=&quot;https://psycnet.apa.org/doi/10.1037/a0018933&quot;&gt;https://doi.org/10.1037/a0018933&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022a). *Introduction to mediation, moderation, and conditional process analysis *(3rd Ed.). New York: The Guilford Press.&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022b). The PROCESS macro for SPSS, SAS, and R (Version 4.2) [Computer software]. &lt;a href=&quot;https://processmacro.org&quot;&gt;https://processmacro.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Rohrer, J. M., Hünermund, P., Arslan, R. C., Elson, M. (2022). That’s a lot to process! Pitfalls of popular path models. &lt;em&gt;Advances in Methods and Practices in Psychological Science, 5&lt;/em&gt;(2). &lt;a href=&quot;https://doi.org/10.1177/25152459221095827&quot;&gt;https://doi.org/10.1177/25152459221095827&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 31 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By &lt;a href=&quot;https://www.esciencecenter.nl/team/malte-luken/&quot;&gt;Malte Lüken&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/thijs-vroegh/&quot;&gt;Thijs Vroegh&lt;/a&gt;, &lt;a href=&quot;https://www.uva.nl/en/profile/d/o/j.b.vandoorn/j.b.vandoorn.html&quot;&gt;Johnny van Doorn&lt;/a&gt;, and &lt;a href=&quot;https://www.uva.nl/en/profile/w/a/e.m.wagenmakers/e.m.wagenmakers.html&quot;&gt;Eric-Jan Wagenmakers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post is also published on the JASP &lt;em&gt;&lt;a href=&quot;https://jasp-stats.org/blog/&quot;&gt;&lt;em&gt;blog&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-28f59e63.BvDjMAD5_Z1hQvP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@humakabakci?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Huma Kabakci&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;
&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-1571ecc2.wAju-tYr_2e1nej.webp&quot; srcset=&quot;&quot;&gt;
Many students, teachers and researchers use the popular &lt;a href=&quot;https://www.processmacro.org/&quot;&gt;PROCESS&lt;/a&gt; macro for SPSS (Hayes, 2022a, 2022b) to estimate conditional process models involving mediation and moderation effects. Recently, however, these models were also criticized because they make causal assumptions, which do not hold in many applied settings (Bullock et al., 2010, Rohrer et al., 2022). The popularity and criticism warrant a new module to make conditional process models easily accessible to the JASP community. Moreover, the module should provide a better understanding of the underlying causal assumptions for users and tools to explicitly test them. The JASP Team and the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; are currently working on such an endeavor, and we give a short teaser in this blog post.&lt;/p&gt;
&lt;h2 id=&quot;estimating-models-as-in-spss&quot;&gt;Estimating Models as in SPSS&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;928&quot; height=&quot;572&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-c574f468.CqYvTdHT_Z1HpGWI.webp&quot; srcset=&quot;&quot;&gt;
The new &lt;em&gt;Process&lt;/em&gt; module has two graphical user interfaces: One interface resembles the interface of the original SPSS macro where users first select a model configuration from a predefined list. In contrast to SPSS, JASP immediately shows the user a graphical representation of the specified model (i.e., a path plot), which facilitates the search for the right model. As the user adds more variables to the model, the graphical representation is updated. The module will provide both conceptual and statistical path plots, where the statistical path plot includes the estimated parameters.&lt;/p&gt;
&lt;h2 id=&quot;building-models-step-by-step&quot;&gt;Building Models Step-by-step&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Coming Soon: Conditional Process Models in JASP&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;928&quot; height=&quot;573&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-da35f929.CqlR2qB3_1bgfQX.webp&quot; srcset=&quot;&quot;&gt;
With a second, complementary interface users can build models step-by-step starting from scratch. They can iteratively add paths (i.e., relations) between selected variables and define how other variables influence each path (e.g., through mediation or moderation). Below, we reproduce predefined Model 5 with two path specifications: We first add a path between Extraversion and Neuroticism (X and Y) and specify Openness as a mediator for this path (M). Then, we add a second path specification between Extraversion and Neuroticism, but this time we include Agreeableness as a moderator for this path (W). Again, every time a path is added or modified, JASP will immediately show the user the corresponding graphical representation of the model to facilitate the model-building process. This approach enables users to build models intuitively and flexibly, avoiding the restrictions of predefined model configurations.&lt;/p&gt;
&lt;h2 id=&quot;addressing-criticisms-of-process-models&quot;&gt;Addressing Criticisms of Process Models&lt;/h2&gt;
&lt;p&gt;Conditional process models make strong causal assumptions about the relationships between variables. A mediation model, for example, states that there is a causal relationship from X to Y, X to M, as well as M to Y. Critics have argued that researchers cannot assume these causal assumptions to hold in most applications, even in experimental settings (Bullock et al., 2010, Rohrer et al., 2022). In the new module, we aim to address some of these arguments by making the causal assumptions more explicit via footnotes and warnings. Importantly, we will also enable users to test the statistical patterns implied by the causal assumptions (i.e., via conditional independence tests; see Rohrer et al., 2022). Users can then conclude which assumptions are violated and modify their model or experimental design accordingly. Because of its step-by-step interface, the module allows users to build more complex models to accommodate the requirements of their application (e.g., by adding confounding variables to different paths). Despite these features, many challenges remain when applying conditional process models, most of which are related to careful experimental design (see Bullock et al., 2010). We aim to draw the users’ attention to these challenges and improve the statistical use of process models in practice.&lt;/p&gt;
&lt;h2 id=&quot;behind-the-project&quot;&gt;Behind the Project&lt;/h2&gt;
&lt;p&gt;This project is a collaboration between the JASP Team and the Netherlands eScience Center. As the national institute for research software, the Netherlands eScience Center awards projects as part of calls for proposals. Instead of monetary funding, it provides in-kind support by Research Software Engineers to create innovative digital solutions. This project was granted as part of the Small-Scale Initiatives Digital Approaches to the Social Sciences call 2022.&lt;/p&gt;
&lt;p&gt;We kindly thank &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;&lt;em&gt;Tom Bakker&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;&lt;em&gt;Lieke de Boer&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; for providing feedback on earlier versions of this post.*&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;Bullock, J. G., Green, D. P., &amp;#x26; Ha, S. E. (2010). Yes, but what’s the mechanism? (don’t expect an easy answer). &lt;em&gt;Journal of Personality and Social Psychology, 98&lt;/em&gt;(4), 550–558. &lt;a href=&quot;https://psycnet.apa.org/doi/10.1037/a0018933&quot;&gt;https://doi.org/10.1037/a0018933&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022a). *Introduction to mediation, moderation, and conditional process analysis *(3rd Ed.). New York: The Guilford Press.&lt;/p&gt;
&lt;p&gt;Hayes, A. F. (2022b). The PROCESS macro for SPSS, SAS, and R (Version 4.2) [Computer software]. &lt;a href=&quot;https://processmacro.org&quot;&gt;https://processmacro.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Rohrer, J. M., Hünermund, P., Arslan, R. C., Elson, M. (2022). That’s a lot to process! Pitfalls of popular path models. &lt;em&gt;Advances in Methods and Practices in Psychological Science, 5&lt;/em&gt;(2). &lt;a href=&quot;https://doi.org/10.1177/25152459221095827&quot;&gt;https://doi.org/10.1177/25152459221095827&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/coming-soon-conditional-process-models-i-28f59e63.BvDjMAD5.jpg" medium="image"/><author>Malte Lüken</author></item><item><title>Why your research deserves to be an R package</title><link>https://blog2.esciencecenter.nl/posts/2023-08-30---why-your-research-deserves-to-be-an-r-package</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-08-30---why-your-research-deserves-to-be-an-r-package</guid><description>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If after reading this post you are motivated to make your own R package, consider joining our upcoming workshop! &lt;em&gt;&lt;a href=&quot;https://www.eventbrite.nl/e/reproducible-research-with-r-packages-tickets-672884123527&quot;&gt;&lt;em&gt;Free tickets are now available&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you are an R user, think about this scenario:&lt;/p&gt;
&lt;p&gt;How often have you reused someone else’s code — a colleague’s workflow, perhaps a script you found as an appendix in a paper? Did it run right away? Was it easy to reuse?&lt;/p&gt;
&lt;p&gt;Now, ask yourself whether you have used someone else’s packaged code. How often have you started your own script with &lt;em&gt;library (packagename)&lt;/em&gt;, and used functions that are not part of base R?&lt;/p&gt;
&lt;p&gt;I am willing to bet quite a lot that the second scenario is an order of magnitude more common than the first. There is a reason for this: packages are made to be reused. Scripts, while technically reusable, are not.&lt;/p&gt;
&lt;p&gt;Let me now ask you about your own work: do you want it to be reused?&lt;/p&gt;
&lt;p&gt;You know what you have to do now, right?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why your research deserves to be an R package&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-bebe4eaf.DCiM-mIO_2mR8fo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@kadh?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Kira auf der Heide&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;but-making-a-package-isnt-that-complicated&quot;&gt;But making a package… isn’t that complicated?&lt;/h3&gt;
&lt;p&gt;An R package distinguishes itself from scripted code in a few ways, but it is much less complex than you may think.&lt;/p&gt;
&lt;p&gt;First of all, when your code is packaged, it is contained in a standardized folder structure. The code itself lives in a designated folder (aptly named ‘R’). In addition, the root of the package contains files with some basic information about your package — like the title, the authors, and the license for future users.&lt;/p&gt;
&lt;p&gt;Secondly, and perhaps most crucially, packaged code consists of functions only. Functions are the units at the centre of a package. They take information as arguments and return an output. For example, I have a function called *multiply. *This function, you guessed it, multiplies the two arguments I give it, and returns the result:&lt;/p&gt;
&lt;p&gt;multiply &amp;#x3C;- function(a, b){
return(a * b)
}After including this function in a package — let’s call it *mypackage — *someone else can now use it without opening and running the entire codebase, but instead by attaching the package and calling the function:&lt;/p&gt;
&lt;p&gt;&gt; library(myPackage)
&gt; multiply(3,4)
[1] 12You have likely written functions before. And you know how folders work. To dot the i’s and cross the t’s, Rstudio is here to help: it contains many built-in functions to make package creation a breeze.&lt;/p&gt;
&lt;h3 id=&quot;your-work-deserves-to-be-reused&quot;&gt;Your work deserves to be reused.&lt;/h3&gt;
&lt;p&gt;Just in case you are now doubting yourself, please don’t. Scripting an analysis is more than just applying existing calculations. The workflow itself is an original thought. Even if you have not, say, designed a new statistical method yourself, the methods you choose, the way you select and handle your data, the visualisations you make — they are your work, and could be reused as a standardised workflow in your field.&lt;/p&gt;
&lt;p&gt;Let’s take an example. Mark*, a linguistics professor, runs frequent analyses on datasets made from taped conversations. He uses R to uncover the unwritten rules of conversation, finding out how people weave their utterances together. With this data, he creates &lt;a href=&quot;https://ideophone.org/snailplot-rmd/&quot;&gt;fantastic&lt;/a&gt; &lt;a href=&quot;https://markdingemanse.net/publications/visuals/how-asr-training-data-differs-from-real-conversation&quot;&gt;visualisations&lt;/a&gt;, which give insight into the conversational dynamics at play.&lt;/p&gt;
&lt;p&gt;Mark has hundreds of conversations to analyse, so he made functions that contains the essential elements of his workflow. Now, when he loads a new conversation, he can for instance use this function** to quickly get an overview of the basic statistics:&lt;/p&gt;
&lt;p&gt;&gt; conversation &amp;#x3C;- read.csv(“data/conversation25.csv”)
&gt; inspect_convo(conversation)
Number of speakers: 2
Length of conversation: 10:03
Number of utterances: 9438But Mark does not work alone. His group contains PhD students and postdocs, and is a popular place for bachelor and master internships. He shares his scripts with his group, but they can be a daunting sight for those who have not programmed much before. And as his toolkit grows, he loses track of the different elements it contains, and what updates he has shared with whom.&lt;/p&gt;
&lt;p&gt;Mark needs an R package.&lt;/p&gt;
&lt;h3 id=&quot;a-package-makes-you-a-better-programmer&quot;&gt;A package makes you a better programmer.&lt;/h3&gt;
&lt;p&gt;An important element of packaged functions is their documentation: a user who only has access to the name of the function, needs to know how to use it. But writing documentation is not just for users: it does something for you as a developer as well.&lt;/p&gt;
&lt;p&gt;Writing down the logic of your functions — what goes in? What comes out? Exactly what formats are needed for each argument?— helps you think more critically about the objects you use and create as part of your workflow. You may not expect it, but documentation is a powerful way to take a step back and start viewing your set of functions as a whole.&lt;/p&gt;
&lt;p&gt;This is where you go from scripting to software engineering.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why your research deserves to be an R package&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-921434e2.m43Kfwp4_Z1RWn4W.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@retrosupply?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;RetroSupply&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;packaged-code-is-more-robust-and-developing-it-is-more-efficient&quot;&gt;Packaged code is more robust, and developing it is more efficient.&lt;/h3&gt;
&lt;p&gt;Because your functions are in a package, you now also have access to another powerful tool in the software engineering toolbox: testing.&lt;/p&gt;
&lt;p&gt;Most likely, when you were developing your function, you were running it over and over to confirm it still did what it was supposed to. You gave it input, and checked that it returned the right output.&lt;/p&gt;
&lt;p&gt;You were testing your function, and it took a lot of time.&lt;/p&gt;
&lt;p&gt;With tests, we can automate this process. Mark, for instance, knows that when he puts the file conversation25.csv* into &lt;em&gt;inspect_convo&lt;/em&gt;, it should return information about the number of speakers (2), the length of the file (10 minutes and 3 seconds), and the number of utterances (9438). He does not have to keep checking this himself, but can put his knowledge inside a test:&lt;/p&gt;
&lt;p&gt;test_that(“Conversation inspection returns the right results”, {&lt;/p&gt;
&lt;h1 id=&quot;load-the-test-object-and-run-inspect_convo&quot;&gt;load the test object and run inspect_convo&lt;/h1&gt;
&lt;p&gt;load(“conversation25.Rda”)
conversation &amp;#x3C;- inspect_convo(conversation25)&lt;/p&gt;
&lt;h1 id=&quot;inspect_convo-should-return-the-right-information&quot;&gt;inspect_convo should return the right information&lt;/h1&gt;
&lt;p&gt;expect_true(conversation[1] == “Number of speakers: 2”)
expect_true(conversation[2] == “Length of conversation: 10:03”)
expect_true(conversation[3] == “Number of utterances: 9438”)
})Now he simply runs the tests, and Rstudio will tell him if they pass. This quickly starts saving him a lot of time, especially when the package grows and starts including more functions. With one click, Mark can confirm that everything, everywhere, is OK.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why your research deserves to be an R package&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;382&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-f3599774.CaOP46cu_Z1C3a1f.webp&quot; srcset=&quot;&quot;&gt;
The Rstudio view of the tests in this package confirm that every function is operating as it should.Being able to check functionality like this comes with a lot of freedom, to grow your package, but also to improve the things already written. How efficient is that function you wrote, really? When you edit (or “refactor”) the code, your tests give you the peace of mind that your edits have not caused any inadvertent problems. After all, as soon as something breaks, you will know!&lt;/p&gt;
&lt;h3 id=&quot;but-what-about-my-paper&quot;&gt;But what about my paper?&lt;/h3&gt;
&lt;p&gt;While you may be happy that someone else can reuse your functions, it is likely that the original goal of your research project was not to write a toolkit, but a paper. Not to worry, there is a designated space for this inside an R package: a vignette.&lt;/p&gt;
&lt;p&gt;In a vignette, you take a reader through your project from A to Z. While explaining your workflow in accompanying markdown-formatted text, you apply your functions in blocks of R code, and the resulting document shows both the code and the resulting output. This is the cherry on top: you have turned your research into an easily reusable toolkit, and shown how to use the functions in a reproducible document.&lt;/p&gt;
&lt;h3 id=&quot;would-you-like-some-help&quot;&gt;Would you like some help?&lt;/h3&gt;
&lt;p&gt;There are a lot of online resources that can help you work on your first package. For one, the book &lt;a href=&quot;https://r-pkgs.org/&quot;&gt;R Packages&lt;/a&gt; is a resource I cannot recommend enough. It has been the basis for the &lt;a href=&quot;https://carpentries-incubator.github.io/lesson-R-packaging/&quot;&gt;Carpentries lesson “R Packaging”&lt;/a&gt;, which is regularly held as part of the eScience Center’s digital skills workshops. Take a look &lt;a href=&quot;https://www.esciencecenter.nl/events/?f=workshops&quot;&gt;at our schedule&lt;/a&gt; to see upcoming dates for “Reproducible Research with R Packages”, and join us!&lt;/p&gt;
&lt;p&gt;*) The story used in this blog is inspired by the package &lt;a href=&quot;https://github.com/elpaco-escience/talkr/&quot;&gt;&lt;em&gt;talkr&lt;/em&gt;&lt;/a&gt;, which is part of &lt;a href=&quot;https://research-software-directory.org/projects/diversity-aware&quot;&gt;&lt;em&gt;Towards next-generation scientific computing tools for diversity-aware language science and technology&lt;/em&gt;&lt;/a&gt;, a project with Mark Dingemanse and Andreas Liesenfeld at the Radboud Universiteit Nijmegen. You can read more about the real Mark at his own website: &lt;a href=&quot;https://markdingemanse.net/&quot;&gt;markdingemanse.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;**) The functions and files in this blog are simplified and fictionalised for ease of reading.&lt;/p&gt;</description><pubDate>Wed, 30 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;1&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If after reading this post you are motivated to make your own R package, consider joining our upcoming workshop! &lt;em&gt;&lt;a href=&quot;https://www.eventbrite.nl/e/reproducible-research-with-r-packages-tickets-672884123527&quot;&gt;&lt;em&gt;Free tickets are now available&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you are an R user, think about this scenario:&lt;/p&gt;
&lt;p&gt;How often have you reused someone else’s code — a colleague’s workflow, perhaps a script you found as an appendix in a paper? Did it run right away? Was it easy to reuse?&lt;/p&gt;
&lt;p&gt;Now, ask yourself whether you have used someone else’s packaged code. How often have you started your own script with &lt;em&gt;library (packagename)&lt;/em&gt;, and used functions that are not part of base R?&lt;/p&gt;
&lt;p&gt;I am willing to bet quite a lot that the second scenario is an order of magnitude more common than the first. There is a reason for this: packages are made to be reused. Scripts, while technically reusable, are not.&lt;/p&gt;
&lt;p&gt;Let me now ask you about your own work: do you want it to be reused?&lt;/p&gt;
&lt;p&gt;You know what you have to do now, right?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why your research deserves to be an R package&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-bebe4eaf.DCiM-mIO_2mR8fo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@kadh?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Kira auf der Heide&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;but-making-a-package-isnt-that-complicated&quot;&gt;But making a package… isn’t that complicated?&lt;/h3&gt;
&lt;p&gt;An R package distinguishes itself from scripted code in a few ways, but it is much less complex than you may think.&lt;/p&gt;
&lt;p&gt;First of all, when your code is packaged, it is contained in a standardized folder structure. The code itself lives in a designated folder (aptly named ‘R’). In addition, the root of the package contains files with some basic information about your package — like the title, the authors, and the license for future users.&lt;/p&gt;
&lt;p&gt;Secondly, and perhaps most crucially, packaged code consists of functions only. Functions are the units at the centre of a package. They take information as arguments and return an output. For example, I have a function called *multiply. *This function, you guessed it, multiplies the two arguments I give it, and returns the result:&lt;/p&gt;
&lt;p&gt;multiply &amp;#x3C;- function(a, b){
return(a * b)
}After including this function in a package — let’s call it *mypackage — *someone else can now use it without opening and running the entire codebase, but instead by attaching the package and calling the function:&lt;/p&gt;
&lt;p&gt;&gt; library(myPackage)
&gt; multiply(3,4)
[1] 12You have likely written functions before. And you know how folders work. To dot the i’s and cross the t’s, Rstudio is here to help: it contains many built-in functions to make package creation a breeze.&lt;/p&gt;
&lt;h3 id=&quot;your-work-deserves-to-be-reused&quot;&gt;Your work deserves to be reused.&lt;/h3&gt;
&lt;p&gt;Just in case you are now doubting yourself, please don’t. Scripting an analysis is more than just applying existing calculations. The workflow itself is an original thought. Even if you have not, say, designed a new statistical method yourself, the methods you choose, the way you select and handle your data, the visualisations you make — they are your work, and could be reused as a standardised workflow in your field.&lt;/p&gt;
&lt;p&gt;Let’s take an example. Mark*, a linguistics professor, runs frequent analyses on datasets made from taped conversations. He uses R to uncover the unwritten rules of conversation, finding out how people weave their utterances together. With this data, he creates &lt;a href=&quot;https://ideophone.org/snailplot-rmd/&quot;&gt;fantastic&lt;/a&gt; &lt;a href=&quot;https://markdingemanse.net/publications/visuals/how-asr-training-data-differs-from-real-conversation&quot;&gt;visualisations&lt;/a&gt;, which give insight into the conversational dynamics at play.&lt;/p&gt;
&lt;p&gt;Mark has hundreds of conversations to analyse, so he made functions that contains the essential elements of his workflow. Now, when he loads a new conversation, he can for instance use this function** to quickly get an overview of the basic statistics:&lt;/p&gt;
&lt;p&gt;&gt; conversation &amp;#x3C;- read.csv(“data/conversation25.csv”)
&gt; inspect_convo(conversation)
Number of speakers: 2
Length of conversation: 10:03
Number of utterances: 9438But Mark does not work alone. His group contains PhD students and postdocs, and is a popular place for bachelor and master internships. He shares his scripts with his group, but they can be a daunting sight for those who have not programmed much before. And as his toolkit grows, he loses track of the different elements it contains, and what updates he has shared with whom.&lt;/p&gt;
&lt;p&gt;Mark needs an R package.&lt;/p&gt;
&lt;h3 id=&quot;a-package-makes-you-a-better-programmer&quot;&gt;A package makes you a better programmer.&lt;/h3&gt;
&lt;p&gt;An important element of packaged functions is their documentation: a user who only has access to the name of the function, needs to know how to use it. But writing documentation is not just for users: it does something for you as a developer as well.&lt;/p&gt;
&lt;p&gt;Writing down the logic of your functions — what goes in? What comes out? Exactly what formats are needed for each argument?— helps you think more critically about the objects you use and create as part of your workflow. You may not expect it, but documentation is a powerful way to take a step back and start viewing your set of functions as a whole.&lt;/p&gt;
&lt;p&gt;This is where you go from scripting to software engineering.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why your research deserves to be an R package&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-921434e2.m43Kfwp4_Z1RWn4W.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@retrosupply?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;RetroSupply&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;packaged-code-is-more-robust-and-developing-it-is-more-efficient&quot;&gt;Packaged code is more robust, and developing it is more efficient.&lt;/h3&gt;
&lt;p&gt;Because your functions are in a package, you now also have access to another powerful tool in the software engineering toolbox: testing.&lt;/p&gt;
&lt;p&gt;Most likely, when you were developing your function, you were running it over and over to confirm it still did what it was supposed to. You gave it input, and checked that it returned the right output.&lt;/p&gt;
&lt;p&gt;You were testing your function, and it took a lot of time.&lt;/p&gt;
&lt;p&gt;With tests, we can automate this process. Mark, for instance, knows that when he puts the file conversation25.csv* into &lt;em&gt;inspect_convo&lt;/em&gt;, it should return information about the number of speakers (2), the length of the file (10 minutes and 3 seconds), and the number of utterances (9438). He does not have to keep checking this himself, but can put his knowledge inside a test:&lt;/p&gt;
&lt;p&gt;test_that(“Conversation inspection returns the right results”, {&lt;/p&gt;
&lt;h1 id=&quot;load-the-test-object-and-run-inspect_convo&quot;&gt;load the test object and run inspect_convo&lt;/h1&gt;
&lt;p&gt;load(“conversation25.Rda”)
conversation &amp;#x3C;- inspect_convo(conversation25)&lt;/p&gt;
&lt;h1 id=&quot;inspect_convo-should-return-the-right-information&quot;&gt;inspect_convo should return the right information&lt;/h1&gt;
&lt;p&gt;expect_true(conversation[1] == “Number of speakers: 2”)
expect_true(conversation[2] == “Length of conversation: 10:03”)
expect_true(conversation[3] == “Number of utterances: 9438”)
})Now he simply runs the tests, and Rstudio will tell him if they pass. This quickly starts saving him a lot of time, especially when the package grows and starts including more functions. With one click, Mark can confirm that everything, everywhere, is OK.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why your research deserves to be an R package&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;382&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-f3599774.CaOP46cu_Z1C3a1f.webp&quot; srcset=&quot;&quot;&gt;
The Rstudio view of the tests in this package confirm that every function is operating as it should.Being able to check functionality like this comes with a lot of freedom, to grow your package, but also to improve the things already written. How efficient is that function you wrote, really? When you edit (or “refactor”) the code, your tests give you the peace of mind that your edits have not caused any inadvertent problems. After all, as soon as something breaks, you will know!&lt;/p&gt;
&lt;h3 id=&quot;but-what-about-my-paper&quot;&gt;But what about my paper?&lt;/h3&gt;
&lt;p&gt;While you may be happy that someone else can reuse your functions, it is likely that the original goal of your research project was not to write a toolkit, but a paper. Not to worry, there is a designated space for this inside an R package: a vignette.&lt;/p&gt;
&lt;p&gt;In a vignette, you take a reader through your project from A to Z. While explaining your workflow in accompanying markdown-formatted text, you apply your functions in blocks of R code, and the resulting document shows both the code and the resulting output. This is the cherry on top: you have turned your research into an easily reusable toolkit, and shown how to use the functions in a reproducible document.&lt;/p&gt;
&lt;h3 id=&quot;would-you-like-some-help&quot;&gt;Would you like some help?&lt;/h3&gt;
&lt;p&gt;There are a lot of online resources that can help you work on your first package. For one, the book &lt;a href=&quot;https://r-pkgs.org/&quot;&gt;R Packages&lt;/a&gt; is a resource I cannot recommend enough. It has been the basis for the &lt;a href=&quot;https://carpentries-incubator.github.io/lesson-R-packaging/&quot;&gt;Carpentries lesson “R Packaging”&lt;/a&gt;, which is regularly held as part of the eScience Center’s digital skills workshops. Take a look &lt;a href=&quot;https://www.esciencecenter.nl/events/?f=workshops&quot;&gt;at our schedule&lt;/a&gt; to see upcoming dates for “Reproducible Research with R Packages”, and join us!&lt;/p&gt;
&lt;p&gt;*) The story used in this blog is inspired by the package &lt;a href=&quot;https://github.com/elpaco-escience/talkr/&quot;&gt;&lt;em&gt;talkr&lt;/em&gt;&lt;/a&gt;, which is part of &lt;a href=&quot;https://research-software-directory.org/projects/diversity-aware&quot;&gt;&lt;em&gt;Towards next-generation scientific computing tools for diversity-aware language science and technology&lt;/em&gt;&lt;/a&gt;, a project with Mark Dingemanse and Andreas Liesenfeld at the Radboud Universiteit Nijmegen. You can read more about the real Mark at his own website: &lt;a href=&quot;https://markdingemanse.net/&quot;&gt;markdingemanse.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;**) The functions and files in this blog are simplified and fictionalised for ease of reading.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/why-your-research-deserves-to-be-an-r-pa-bebe4eaf.DCiM-mIO.jpg" medium="image"/><author>Barbara Vreede</author></item><item><title>Lilio — a calendar package for machine learning with time series data</title><link>https://blog2.esciencecenter.nl/posts/2023-08-21---lilio-a-calendar-package-for-machine-learning-with-time-seri</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-08-21---lilio-a-calendar-package-for-machine-learning-with-time-seri</guid><description>&lt;h2 id=&quot;designed-with-the-s2s-community-available-for-everyone&quot;&gt;Designed with the S2S community, available for everyone&lt;/h2&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;These are just some of the questions that scientists in the field of sub-seasonal to seasonal (S2S) weather and climate prediction have to deal with on a daily basis. Especially now that the use of machine learning is &lt;a href=&quot;https://s2s-ai-challenge.github.io/&quot;&gt;gaining traction&lt;/a&gt;. In this blog post, we introduce &lt;a href=&quot;https://lilio.readthedocs.io/en/latest/index.html&quot;&gt;Lilio&lt;/a&gt;, a new calendar &lt;a href=&quot;https://pypi.org/project/lilio/&quot;&gt;package &lt;/a&gt;that was designed to help tackle these questions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;295&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-42268afa.DQXZijBm_kI8Gb.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://github.com/AI4S2S/lilio&quot;&gt;https://github.com/AI4S2S/lilio&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-niche&quot;&gt;The niche&lt;/h2&gt;
&lt;p&gt;Before we dive into the capabilities of Lilio, let me briefly review why existing packages didn’t cut the deal for us. &lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;Pandas&lt;/a&gt; is great and we rely on it, but we wanted more flexibility to construct varying intervals with custom gaps in between. And instead of a continuous index, we wanted to exploit the periodicity in our use cases. Existing time series models (e.g. *&lt;a href=&quot;https://medium.com/unit8-machine-learning-publication/time-series-forecasting-using-past-and-future-external-data-with-darts-1f0539585993&quot;&gt;Darts&lt;/a&gt;) often apply the same model irrespective of the forecast issue date, and the forecasts are anchored to said issue date. By contrast, our experiments are usually anchored to a clear target period, and each target may have a unique set of predictors. We have different models with different precursors for a windy May, a wet monsoon, a mild winter, …&lt;/p&gt;
&lt;h2 id=&quot;the-fill&quot;&gt;The fill&lt;/h2&gt;
&lt;p&gt;So, how does Lilio help with all of that? First of all, we stack the years to obtain a 2-dimensional calendar. Each row represents a year, and columns are intervals within that year. Typically we have several precursor periods leading up to one or more target periods. This aligns nicely with the common representation of samples and features in ML data. In our case, the target is in the rightmost column(s).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;179&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-e88dbf7f.DGXG8Njk_2unjb.webp&quot; srcset=&quot;&quot;&gt;
Conceptual illustration of the structure of our calendars.We define the “anchor date” to be between the target and precursor periods. All other intervals are expressed as offsets to this anchor date. Conveniently, this eliminates any ambiguity related to leap years. Here’s a calendar generated with Lilio:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;558&quot; height=&quot;253&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-fd12e9cf.CFTBVga4_Z18KxhS.webp&quot; srcset=&quot;&quot;&gt;
Example calendar with uniform 10-day intervals, here represented as offsets to the anchor date.By default, we include as many blocks (of a given frequency) as fit in one year but not more. To control this behaviour, Lilio provides options to allow or prohibit overlap. This makes it straightforward to apply existing train/test splitting strategies without leakage.&lt;/p&gt;
&lt;h2 id=&quot;anchor--offset--date&quot;&gt;Anchor + offset = date&lt;/h2&gt;
&lt;p&gt;Initially, Lilio calendars don’t include years. Only after we map the calendar onto a given year range or dataset, actual dates can be calculated. Since the start or end date of the calendar doesn’t always nicely align with the input data, the calendar also comes with a method to map it to the range of available data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-bd2f18b7.CQTMkBtB_1LmwU6.webp&quot; srcset=&quot;&quot;&gt;
Same calendar as above but plotted on a datetime axis. The anchor date for this calendar is 30 November. Combined with the anchor years 2020 and 2021, the actual dates can be inferred.&lt;/p&gt;
&lt;h2 id=&quot;visualizations--wishful-drawing&quot;&gt;Visualizations &amp;#x26; wishful drawing&lt;/h2&gt;
&lt;p&gt;The visualizations shown above are generated automatically. This turns out to be very helpful in the initial process of setting up your experiments. We even found ourselves making “wishful drawings” to communicate about alternative calendars that we’d like to support.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;185&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-a153c1a1.ljuxYc1j_Z266lfM.webp&quot; srcset=&quot;&quot;&gt;
Illustrated feature request for a “rolling calendar”&lt;/p&gt;
&lt;h2 id=&quot;resampling&quot;&gt;Resampling&lt;/h2&gt;
&lt;p&gt;Lilio’s resampling functionality can be used to aggregate the input data based on the calendar’s intervals. Here, again, we heavily rely on the presence of bounded intervals. By using these as resampling bins, we ensure that all input data ends up on the exact same time axis.&lt;/p&gt;
&lt;h2 id=&quot;simple-and-custom-calendars&quot;&gt;Simple and custom calendars&lt;/h2&gt;
&lt;p&gt;For many applications, a simple weekly, monthly, or (n-)daily calendar may be all you need, and Lilio makes this super easy. With only a bit more effort, you can also construct calendars with gaps and overlapping intervals of varying lengths. Here’s a more exotic calendar for predicting the chances of a white Christmas:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;581&quot; height=&quot;269&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-17ff14ed.CAzdFlPH_7Ogq9.webp&quot; srcset=&quot;&quot;&gt;
This calendar uses more fine-grained information closer to the target&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;Lilio has been developed in the context of a larger &lt;a href=&quot;https://research-software-directory.org/projects/ai4s2s&quot;&gt;project &lt;/a&gt;in which we are developing a Python package to set up and streamline S2S — machine learning workflows. It will be a key component in our experimental setup. At the same time, the calendar is also very suitable as a stand-alone component for use in other applications. We are curious to learn about new use cases that you may have for it.&lt;/p&gt;
&lt;h2 id=&quot;final-note&quot;&gt;Final note&lt;/h2&gt;
&lt;p&gt;Collaborative research software development is a &lt;a href=&quot;https://github.com/AI4S2S/lilio/graphs/contributors&quot;&gt;team effort&lt;/a&gt;. Please give appropriate credit and consider&lt;a href=&quot;https://github.com/AI4S2S/lilio&quot;&gt; joining us&lt;/a&gt; 😊. And if you read up to this point and still wonder who Lilio was: &lt;a href=&quot;https://en.wikipedia.org/wiki/Aloysius_Lilius&quot;&gt;here you go&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Mon, 21 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;designed-with-the-s2s-community-available-for-everyone&quot;&gt;Designed with the S2S community, available for everyone&lt;/h2&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;These are just some of the questions that scientists in the field of sub-seasonal to seasonal (S2S) weather and climate prediction have to deal with on a daily basis. Especially now that the use of machine learning is &lt;a href=&quot;https://s2s-ai-challenge.github.io/&quot;&gt;gaining traction&lt;/a&gt;. In this blog post, we introduce &lt;a href=&quot;https://lilio.readthedocs.io/en/latest/index.html&quot;&gt;Lilio&lt;/a&gt;, a new calendar &lt;a href=&quot;https://pypi.org/project/lilio/&quot;&gt;package &lt;/a&gt;that was designed to help tackle these questions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;295&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-42268afa.DQXZijBm_kI8Gb.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://github.com/AI4S2S/lilio&quot;&gt;https://github.com/AI4S2S/lilio&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-niche&quot;&gt;The niche&lt;/h2&gt;
&lt;p&gt;Before we dive into the capabilities of Lilio, let me briefly review why existing packages didn’t cut the deal for us. &lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;Pandas&lt;/a&gt; is great and we rely on it, but we wanted more flexibility to construct varying intervals with custom gaps in between. And instead of a continuous index, we wanted to exploit the periodicity in our use cases. Existing time series models (e.g. *&lt;a href=&quot;https://medium.com/unit8-machine-learning-publication/time-series-forecasting-using-past-and-future-external-data-with-darts-1f0539585993&quot;&gt;Darts&lt;/a&gt;) often apply the same model irrespective of the forecast issue date, and the forecasts are anchored to said issue date. By contrast, our experiments are usually anchored to a clear target period, and each target may have a unique set of predictors. We have different models with different precursors for a windy May, a wet monsoon, a mild winter, …&lt;/p&gt;
&lt;h2 id=&quot;the-fill&quot;&gt;The fill&lt;/h2&gt;
&lt;p&gt;So, how does Lilio help with all of that? First of all, we stack the years to obtain a 2-dimensional calendar. Each row represents a year, and columns are intervals within that year. Typically we have several precursor periods leading up to one or more target periods. This aligns nicely with the common representation of samples and features in ML data. In our case, the target is in the rightmost column(s).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;179&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-e88dbf7f.DGXG8Njk_2unjb.webp&quot; srcset=&quot;&quot;&gt;
Conceptual illustration of the structure of our calendars.We define the “anchor date” to be between the target and precursor periods. All other intervals are expressed as offsets to this anchor date. Conveniently, this eliminates any ambiguity related to leap years. Here’s a calendar generated with Lilio:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;558&quot; height=&quot;253&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-fd12e9cf.CFTBVga4_Z18KxhS.webp&quot; srcset=&quot;&quot;&gt;
Example calendar with uniform 10-day intervals, here represented as offsets to the anchor date.By default, we include as many blocks (of a given frequency) as fit in one year but not more. To control this behaviour, Lilio provides options to allow or prohibit overlap. This makes it straightforward to apply existing train/test splitting strategies without leakage.&lt;/p&gt;
&lt;h2 id=&quot;anchor--offset--date&quot;&gt;Anchor + offset = date&lt;/h2&gt;
&lt;p&gt;Initially, Lilio calendars don’t include years. Only after we map the calendar onto a given year range or dataset, actual dates can be calculated. Since the start or end date of the calendar doesn’t always nicely align with the input data, the calendar also comes with a method to map it to the range of available data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-bd2f18b7.CQTMkBtB_1LmwU6.webp&quot; srcset=&quot;&quot;&gt;
Same calendar as above but plotted on a datetime axis. The anchor date for this calendar is 30 November. Combined with the anchor years 2020 and 2021, the actual dates can be inferred.&lt;/p&gt;
&lt;h2 id=&quot;visualizations--wishful-drawing&quot;&gt;Visualizations &amp;#x26; wishful drawing&lt;/h2&gt;
&lt;p&gt;The visualizations shown above are generated automatically. This turns out to be very helpful in the initial process of setting up your experiments. We even found ourselves making “wishful drawings” to communicate about alternative calendars that we’d like to support.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;185&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-a153c1a1.ljuxYc1j_Z266lfM.webp&quot; srcset=&quot;&quot;&gt;
Illustrated feature request for a “rolling calendar”&lt;/p&gt;
&lt;h2 id=&quot;resampling&quot;&gt;Resampling&lt;/h2&gt;
&lt;p&gt;Lilio’s resampling functionality can be used to aggregate the input data based on the calendar’s intervals. Here, again, we heavily rely on the presence of bounded intervals. By using these as resampling bins, we ensure that all input data ends up on the exact same time axis.&lt;/p&gt;
&lt;h2 id=&quot;simple-and-custom-calendars&quot;&gt;Simple and custom calendars&lt;/h2&gt;
&lt;p&gt;For many applications, a simple weekly, monthly, or (n-)daily calendar may be all you need, and Lilio makes this super easy. With only a bit more effort, you can also construct calendars with gaps and overlapping intervals of varying lengths. Here’s a more exotic calendar for predicting the chances of a white Christmas:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lilio — a calendar package for machine learning with time series data&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;581&quot; height=&quot;269&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-17ff14ed.CAzdFlPH_7Ogq9.webp&quot; srcset=&quot;&quot;&gt;
This calendar uses more fine-grained information closer to the target&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;Lilio has been developed in the context of a larger &lt;a href=&quot;https://research-software-directory.org/projects/ai4s2s&quot;&gt;project &lt;/a&gt;in which we are developing a Python package to set up and streamline S2S — machine learning workflows. It will be a key component in our experimental setup. At the same time, the calendar is also very suitable as a stand-alone component for use in other applications. We are curious to learn about new use cases that you may have for it.&lt;/p&gt;
&lt;h2 id=&quot;final-note&quot;&gt;Final note&lt;/h2&gt;
&lt;p&gt;Collaborative research software development is a &lt;a href=&quot;https://github.com/AI4S2S/lilio/graphs/contributors&quot;&gt;team effort&lt;/a&gt;. Please give appropriate credit and consider&lt;a href=&quot;https://github.com/AI4S2S/lilio&quot;&gt; joining us&lt;/a&gt; 😊. And if you read up to this point and still wonder who Lilio was: &lt;a href=&quot;https://en.wikipedia.org/wiki/Aloysius_Lilius&quot;&gt;here you go&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/lilio-a-calendar-package-for-machine-lea-42268afa.DQXZijBm.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Summer is here, and so are large language models.</title><link>https://blog2.esciencecenter.nl/posts/2023-07-10---summer-is-here-and-so-are-large-language-models</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-07-10---summer-is-here-and-so-are-large-language-models</guid><description>&lt;p&gt;Welcome to the technological revolution of 2023, where the landscape of communication and information processing has been forever transformed.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Summer is here, and so are large language models.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/summer-is-here-and-so-are-large-language-d532273d.DPS4yuCo_2nfro4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@deepmind?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Google DeepMind&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The early months of this year have been dominated by the extraordinary rise of ChatGPT and other large language models. These remarkable AI-powered systems have become the driving force behind an unprecedented level of automation and efficiency in generating summaries and content. In fact, the emergence of ChatGPT has been so influential that it has rendered the traditional practice of crafting personal summary blogs unnecessary. With its unparalleled capabilities, ChatGPT now stands as the ultimate tool to effortlessly generate comprehensive and insightful summaries, paving the way for a new era of intelligent content creation.&lt;/p&gt;
&lt;p&gt;The paragraph above was written by ChatGPT. **Other entries on our blog are still written by humans though, and good ones too. So below are our favourite blogs on large language models:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/interview-with-chatgpt-c17b87214b9c?sk=f49c1d589776446384b8ad35abcb088e&quot;&gt;Aron Jansen interviewed ChatGPT&lt;/a&gt; about the eScience Center. Amazingly, it did not know the eScience Center at the time (it definitely does now!). Arguably, this post was mostly written by ChatGPT — but Aron shows us the art of good prompting.&lt;/p&gt;
&lt;p&gt;Candace Makeda Moore warned us about the &lt;a href=&quot;https://blog2.esciencecenter.nl/the-medical-chatbot-will-not-see-you-now-b2c5d67c7029?sk=d94a5bf43e44b0bfdec4a2552154b83c&quot;&gt;use of ChatGPT in medical contexts&lt;/a&gt;, in this excellent reference of the pitfalls and problems of putting all your trust in these models.&lt;/p&gt;
&lt;p&gt;To give some context to the hype, &lt;a href=&quot;https://blog2.esciencecenter.nl/language-modeling-the-first-100-years-357556816148?sk=d21561541fa78fa4fa4b43e491dc5131&quot;&gt;Carsten Schnober wrote a blog about the history of language models&lt;/a&gt;. It’s an unparalleled and crystal clear description of the history of language models, utopian and dystopian fantasies, as well as concrete potentials and risks.&lt;/p&gt;
&lt;p&gt;An older, but still very relevant post on language models was written by our former engineer Florian Huber. &lt;a href=&quot;https://blog2.esciencecenter.nl/king-man-woman-king-9a7fd2935a85?sk=444566a4998338af9d2bc4fa8e7ba79b&quot;&gt;He explains what language models actually “understand”&lt;/a&gt;, and drew his own funny comics to accompany the story.&lt;/p&gt;
&lt;p&gt;The eScience Center blog is going on a summer hiatus. In the meantime, we hope you enjoy these excellent stories by our excellent colleagues.*&lt;/p&gt;</description><pubDate>Mon, 10 Jul 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to the technological revolution of 2023, where the landscape of communication and information processing has been forever transformed.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Summer is here, and so are large language models.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/summer-is-here-and-so-are-large-language-d532273d.DPS4yuCo_2nfro4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@deepmind?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Google DeepMind&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The early months of this year have been dominated by the extraordinary rise of ChatGPT and other large language models. These remarkable AI-powered systems have become the driving force behind an unprecedented level of automation and efficiency in generating summaries and content. In fact, the emergence of ChatGPT has been so influential that it has rendered the traditional practice of crafting personal summary blogs unnecessary. With its unparalleled capabilities, ChatGPT now stands as the ultimate tool to effortlessly generate comprehensive and insightful summaries, paving the way for a new era of intelligent content creation.&lt;/p&gt;
&lt;p&gt;The paragraph above was written by ChatGPT. **Other entries on our blog are still written by humans though, and good ones too. So below are our favourite blogs on large language models:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/interview-with-chatgpt-c17b87214b9c?sk=f49c1d589776446384b8ad35abcb088e&quot;&gt;Aron Jansen interviewed ChatGPT&lt;/a&gt; about the eScience Center. Amazingly, it did not know the eScience Center at the time (it definitely does now!). Arguably, this post was mostly written by ChatGPT — but Aron shows us the art of good prompting.&lt;/p&gt;
&lt;p&gt;Candace Makeda Moore warned us about the &lt;a href=&quot;https://blog2.esciencecenter.nl/the-medical-chatbot-will-not-see-you-now-b2c5d67c7029?sk=d94a5bf43e44b0bfdec4a2552154b83c&quot;&gt;use of ChatGPT in medical contexts&lt;/a&gt;, in this excellent reference of the pitfalls and problems of putting all your trust in these models.&lt;/p&gt;
&lt;p&gt;To give some context to the hype, &lt;a href=&quot;https://blog2.esciencecenter.nl/language-modeling-the-first-100-years-357556816148?sk=d21561541fa78fa4fa4b43e491dc5131&quot;&gt;Carsten Schnober wrote a blog about the history of language models&lt;/a&gt;. It’s an unparalleled and crystal clear description of the history of language models, utopian and dystopian fantasies, as well as concrete potentials and risks.&lt;/p&gt;
&lt;p&gt;An older, but still very relevant post on language models was written by our former engineer Florian Huber. &lt;a href=&quot;https://blog2.esciencecenter.nl/king-man-woman-king-9a7fd2935a85?sk=444566a4998338af9d2bc4fa8e7ba79b&quot;&gt;He explains what language models actually “understand”&lt;/a&gt;, and drew his own funny comics to accompany the story.&lt;/p&gt;
&lt;p&gt;The eScience Center blog is going on a summer hiatus. In the meantime, we hope you enjoy these excellent stories by our excellent colleagues.*&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/summer-is-here-and-so-are-large-language-d532273d.DPS4yuCo.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Mcfly: An easy-to-use tool for deep learning for time series classification</title><link>https://blog2.esciencecenter.nl/posts/2023-06-26---mcfly-an-easy-to-use-tool-for-deep-learning-for-time-series-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-06-26---mcfly-an-easy-to-use-tool-for-deep-learning-for-time-series-</guid><description>&lt;h2 id=&quot;a-new-mcfly-30-release-is-out-see-how-it-works-and-how-it-can-help-you-to-apply-deep-learning-to-time-series-classification&quot;&gt;A new mcfly 3.0 release is out. See how it works and how it can help you to apply deep learning to time series classification.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Apr 15, 2020&lt;/p&gt;
&lt;p&gt;Once the models are generated, they will be trained on the given data (or a subset to speed things up). This is done using &lt;code&gt;train_models_on_samples&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial/blob/master/notebooks/tutorial/tutorial_quick.ipynb&quot;&gt;See full tutorial notebook for more information.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The performance of the trained models can then interactively be compared using mcfly***, for example by comparing the accuracy on the validation set versus a number of key hyperparameters (see screenshot below). The built-in visualization is interactive and allows to select specific models (here numbered 0 to 7), or select specific architectures (here ‘CNN’ or ‘InceptionTime’), or learning rates. Most important feature to look at are the two plots on the top which display the development of the accuracy on both the training set and the validation set. A good model should perform decently well on both sides.&lt;/p&gt;
&lt;p&gt;mcfly build-in visualization of the model performance. While in this example all models achieve good results on the training dataset, much fewer reach decent results on the validation dataset.&lt;/p&gt;
&lt;h3 id=&quot;overfitting&quot;&gt;Overfitting&lt;/h3&gt;
&lt;p&gt;Since the RacketSports dataset only consits of 150 training examples, you will frequently see that generated deep learning models will &lt;strong&gt;overfit&lt;/strong&gt; the data. Overfitting is one of the most common problems when working with deep learning. It essentially means that you optimize too much on the training data so that the performance on unseen data will suffer. A typical signature for this is that models will do well on the training data (high training accuracy), but will perform poorly on the validation data (low validation accuracy). A typical example is shown below with 8 models, most of which report high &lt;code&gt;train_accuracy&lt;/code&gt;but very low &lt;code&gt;val_accuracy&lt;/code&gt;values!&lt;/p&gt;
&lt;p&gt;Example results of 8 mcfly generated models trained on RacketSports dataset. Six perform well on the training data, but only 2 models also perform well on the validation data.If we now pick one of the better performing models (or iteratively generate and train more models), then we can get quite good results on the RacketSports dataset. Below you can see how we could inspect this by generating a confusion matrix. And here it indeed reveals that most of the times the picked &lt;strong&gt;model is correctly predicting the actual activity!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Generating a confusion matrix using the validation dataset.&lt;/p&gt;
&lt;h3 id=&quot;and-now-what-are-you-waiting-for&quot;&gt;And now… what are you waiting for?&lt;/h3&gt;
&lt;p&gt;Grab some interesting time series data and try out some deep learning!&lt;/p&gt;
&lt;h2 id=&quot;did-you-use-mcfly&quot;&gt;Did you use mcfly?&lt;/h2&gt;
&lt;p&gt;Awesome! We are always happy to hear from people who have made good use of &lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt;. Please get in touch if you have suggestions and ideas for future developments or fixes (e.g. via &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;GitHub&lt;/a&gt;, via&lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt; twitter&lt;/a&gt;, or as response to this post). Many thanks.&lt;/p&gt;
&lt;p&gt;**Reference:
**D. van Kuppevelt, C. Meijer, F. Huber, A. van der Ploeg, S. Georgievska, V.T. van Hees. &lt;em&gt;Mcfly: Automated deep learning on time series.&lt;/em&gt; SoftwareX, Volume 12, 2020. &lt;a href=&quot;https://doi.org/10.1016/j.softx.2020.100548&quot;&gt;doi: 10.1016/j.softx.2020.100548&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/mcfly-time-series-classification-made-easy-e47de8d29838&quot;&gt;Former blog post from 2017&lt;/a&gt; by [Dafne van Kuppevelt]&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt; on pypi: &lt;a href=&quot;https://pypi.org/project/mcfly/&quot;&gt;https://pypi.org/project/mcfly/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt; on GitHub: &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;https://github.com/NLeSC/mcfly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ready-to-use RacketSports dataset on zenodo: &lt;a href=&quot;https://zenodo.org/record/3743603#.XpAypXKxUuU&quot;&gt;https://zenodo.org/record/3743603&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt; tutorial(s): &lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial&quot;&gt;https://github.com/NLeSC/mcfly-tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tutorial notebook with all code mentioned in this blog post: **&lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial/blob/main/notebooks/tutorial/tutorial_quick.ipynb&quot;&gt;https://github.com/NLeSC/mcfly-tutorial/blob/main/notebooks/tutorial/tutorial_quick.ipynb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;mcfly&lt;/em&gt;*** *was developed at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;&lt;strong&gt;Netherlands eScience Center&lt;/strong&gt;&lt;/a&gt; by [Dafne van Kuppevelt], Christiaan Meijer, [Sonja Georgievska], [Vincent van Hees], [Florian Huber], [Patrick Bos], [Jurriaan H. Spaaks], Mateusz Kuzak, [Johan Hidding], [Atze van der Ploeg].&lt;/p&gt;
&lt;p&gt;Thanks to Johan Rheeder, [Sonja Georgievska], [Dafne van Kuppevelt], [Peter Kalverla,] [Patrick Bos], and [Tom Bakker] for helpful comments and edits.&lt;/p&gt;</description><pubDate>Mon, 26 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;a-new-mcfly-30-release-is-out-see-how-it-works-and-how-it-can-help-you-to-apply-deep-learning-to-time-series-classification&quot;&gt;A new mcfly 3.0 release is out. See how it works and how it can help you to apply deep learning to time series classification.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Apr 15, 2020&lt;/p&gt;
&lt;p&gt;Once the models are generated, they will be trained on the given data (or a subset to speed things up). This is done using &lt;code&gt;train_models_on_samples&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial/blob/master/notebooks/tutorial/tutorial_quick.ipynb&quot;&gt;See full tutorial notebook for more information.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The performance of the trained models can then interactively be compared using mcfly***, for example by comparing the accuracy on the validation set versus a number of key hyperparameters (see screenshot below). The built-in visualization is interactive and allows to select specific models (here numbered 0 to 7), or select specific architectures (here ‘CNN’ or ‘InceptionTime’), or learning rates. Most important feature to look at are the two plots on the top which display the development of the accuracy on both the training set and the validation set. A good model should perform decently well on both sides.&lt;/p&gt;
&lt;p&gt;mcfly build-in visualization of the model performance. While in this example all models achieve good results on the training dataset, much fewer reach decent results on the validation dataset.&lt;/p&gt;
&lt;h3 id=&quot;overfitting&quot;&gt;Overfitting&lt;/h3&gt;
&lt;p&gt;Since the RacketSports dataset only consits of 150 training examples, you will frequently see that generated deep learning models will &lt;strong&gt;overfit&lt;/strong&gt; the data. Overfitting is one of the most common problems when working with deep learning. It essentially means that you optimize too much on the training data so that the performance on unseen data will suffer. A typical signature for this is that models will do well on the training data (high training accuracy), but will perform poorly on the validation data (low validation accuracy). A typical example is shown below with 8 models, most of which report high &lt;code&gt;train_accuracy&lt;/code&gt;but very low &lt;code&gt;val_accuracy&lt;/code&gt;values!&lt;/p&gt;
&lt;p&gt;Example results of 8 mcfly generated models trained on RacketSports dataset. Six perform well on the training data, but only 2 models also perform well on the validation data.If we now pick one of the better performing models (or iteratively generate and train more models), then we can get quite good results on the RacketSports dataset. Below you can see how we could inspect this by generating a confusion matrix. And here it indeed reveals that most of the times the picked &lt;strong&gt;model is correctly predicting the actual activity!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Generating a confusion matrix using the validation dataset.&lt;/p&gt;
&lt;h3 id=&quot;and-now-what-are-you-waiting-for&quot;&gt;And now… what are you waiting for?&lt;/h3&gt;
&lt;p&gt;Grab some interesting time series data and try out some deep learning!&lt;/p&gt;
&lt;h2 id=&quot;did-you-use-mcfly&quot;&gt;Did you use mcfly?&lt;/h2&gt;
&lt;p&gt;Awesome! We are always happy to hear from people who have made good use of &lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt;. Please get in touch if you have suggestions and ideas for future developments or fixes (e.g. via &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;GitHub&lt;/a&gt;, via&lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt; twitter&lt;/a&gt;, or as response to this post). Many thanks.&lt;/p&gt;
&lt;p&gt;**Reference:
**D. van Kuppevelt, C. Meijer, F. Huber, A. van der Ploeg, S. Georgievska, V.T. van Hees. &lt;em&gt;Mcfly: Automated deep learning on time series.&lt;/em&gt; SoftwareX, Volume 12, 2020. &lt;a href=&quot;https://doi.org/10.1016/j.softx.2020.100548&quot;&gt;doi: 10.1016/j.softx.2020.100548&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;links&quot;&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/mcfly-time-series-classification-made-easy-e47de8d29838&quot;&gt;Former blog post from 2017&lt;/a&gt; by [Dafne van Kuppevelt]&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt; on pypi: &lt;a href=&quot;https://pypi.org/project/mcfly/&quot;&gt;https://pypi.org/project/mcfly/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt; on GitHub: &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;https://github.com/NLeSC/mcfly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ready-to-use RacketSports dataset on zenodo: &lt;a href=&quot;https://zenodo.org/record/3743603#.XpAypXKxUuU&quot;&gt;https://zenodo.org/record/3743603&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;mcfly&lt;/strong&gt;&lt;/em&gt; tutorial(s): &lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial&quot;&gt;https://github.com/NLeSC/mcfly-tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tutorial notebook with all code mentioned in this blog post: **&lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial/blob/main/notebooks/tutorial/tutorial_quick.ipynb&quot;&gt;https://github.com/NLeSC/mcfly-tutorial/blob/main/notebooks/tutorial/tutorial_quick.ipynb&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;mcfly&lt;/em&gt;*** *was developed at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;&lt;strong&gt;Netherlands eScience Center&lt;/strong&gt;&lt;/a&gt; by [Dafne van Kuppevelt], Christiaan Meijer, [Sonja Georgievska], [Vincent van Hees], [Florian Huber], [Patrick Bos], [Jurriaan H. Spaaks], Mateusz Kuzak, [Johan Hidding], [Atze van der Ploeg].&lt;/p&gt;
&lt;p&gt;Thanks to Johan Rheeder, [Sonja Georgievska], [Dafne van Kuppevelt], [Peter Kalverla,] [Patrick Bos], and [Tom Bakker] for helpful comments and edits.&lt;/p&gt;</content:encoded><author>Florian Huber</author></item><item><title>Reduce, reuse, recycle: save the planet one GitHub action at a time</title><link>https://blog2.esciencecenter.nl/posts/2023-06-20---reduce-reuse-recycle-save-the-planet-one-github-action-at-a-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-06-20---reduce-reuse-recycle-save-the-planet-one-github-action-at-a-</guid><description>&lt;p&gt;**&lt;/p&gt;
&lt;h1 id=&quot;reduce-reuse-recycle-save-the-planet-one-github-action-at-a-time&quot;&gt;Reduce, reuse, recycle: save the planet one GitHub action at a time&lt;/h1&gt;
&lt;p&gt;53&lt;/p&gt;
&lt;p&gt;Written by &lt;a href=&quot;https://medium.com/@stefsmeets&quot;&gt;Stef Smeets&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@s.vanrijn&quot;&gt;Sander van Rijn&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ralphkayden?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Ralph (Ravi) Kayden&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Ask any environmentalist what you can do to help combat climate change and protect the environment, and they will tell you to &lt;a href=&quot;https://en.wikipedia.org/wiki/Waste_hierarchy&quot;&gt;“Reduce, Reuse, Recycle.”&lt;/a&gt; These actions are focused on maximizing practical benefit while minimizing the cost to the environment through conservation of resources and preventing the emission of greenhouse gases.&lt;/p&gt;
&lt;p&gt;As software engineers, we are big fans of integration and continuous delivery (CI/CD) workflows as part of sustainable software development. GitHub actions is &lt;a href=&quot;https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#about-billing-for-github-actions&quot;&gt;completely free for public repositories&lt;/a&gt;, so why wouldn’t we? We use it for everything, from code analysis and linting, running tests and builds in isolated environments, generating documentation on &lt;a href=&quot;https://docs.readthedocs.io/en/stable/integrations.html&quot;&gt;readthedocs&lt;/a&gt;, and publishing packages on &lt;a href=&quot;https://github.com/marketplace/actions/pypi-publish&quot;&gt;PyPI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Until all of our power comes from nuclear fusion, and data centers can be made of trees, running any code will have an environmental impact: CO2 and other emissions from the power used and the production of the computers it runs on. Not writing code won’t solve our problems either, so we need to find places in our workflow where we can reduce our impact.&lt;/p&gt;
&lt;p&gt;Many CI/CD systems are configured to run automatically, often out of sight, so their impact to the planet adds up quickly. We have been asking ourselves some questions, like what we can do to make our use of CI/CD more sustainable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do we need to build the documentation for every commit we make to the code?&lt;/li&gt;
&lt;li&gt;Do we need to test on every version of Python on all platforms to ensure code works?&lt;/li&gt;
&lt;li&gt;Do we need to run all our machine learning notebooks on every push?&lt;/li&gt;
&lt;li&gt;When we fix a typo in our documentation, do we need to run a complete suite of regression tests?&lt;/li&gt;
&lt;li&gt;When we fix a bug, can we get away just re-running the failed tests?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blogpost we share what we have learned and give some ideas about what you can do to reduce your impact using &lt;a href=&quot;https://docs.github.com/en/actions&quot;&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-bother&quot;&gt;Why bother?&lt;/h2&gt;
&lt;p&gt;Data centers need large amounts of energy, from running servers, computing hardware, and refrigerating equipment. And, let’s not forget that the production of servers, cables and supporting equipment, and mining of the required raw materials also contribute.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href=&quot;https://www.iea.org/reports/data-centres-and-data-transmission-networks&quot;&gt;IEA&lt;/a&gt;, all data centers and data transmission networks account for 2–3% of global electricity use. This corresponds to 300 Mt &lt;a href=&quot;https://en.wikipedia.org/wiki/Global_warming_potential#Carbon_dioxide_equivalent&quot;&gt;CO2-eq&lt;/a&gt; in 2020 (0.9% energy related greenhouse gas emissions). The costs for the environment are enormous. Although improvements in efficiency and hyperscale data centers help limit the growth in energy demands somewhat, the demand for data workloads and internet traffic still grows every year.&lt;/p&gt;
&lt;p&gt;GitHub (this blog is about GitHub Actions after all!) claims to be &lt;a href=&quot;https://github.blog/2021-04-22-environmental-sustainability-github/&quot;&gt;committed to environmental sustainability&lt;/a&gt;. A noble effort, but its parent company Microsoft increased its CO2 emissions by &lt;a href=&quot;https://aka.ms/SustainabilityReport2022&quot;&gt;nearly 15% from 2020 to 2022&lt;/a&gt;. Most companies who claim to achieve ‘net zero’ do so not by reducing their emissions, but by compensating elsewhere. Microsoft compensated only about 10% of their emissions in 2022. This is typically done through &lt;a href=&quot;https://en.wikipedia.org/wiki/Guarantee_of_origin&quot;&gt;buying certified green energy&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Carbon_offsets_and_credits&quot;&gt;CO2 compensation&lt;/a&gt;, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Emissions_trading&quot;&gt;emission trading&lt;/a&gt;. This allows companies to be green on paper by trading certificates, with little direct effect on their business operations. Such climate certificates are often sold on a promise, like planting trees or saving a forest from clearing. Better than nothing, but it’s even better to not have those emissions in the first place.&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@etiennegirardet?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Etienne Girardet&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reduce&quot;&gt;Reduce&lt;/h2&gt;
&lt;p&gt;So, what can we do?&lt;/p&gt;
&lt;p&gt;The best thing we can do is prevent resource usage by reducing the number of times we trigger the CI/CD workflows.&lt;/p&gt;
&lt;h3 id=&quot;restrict-branch-and-event-type&quot;&gt;Restrict branch and event type&lt;/h3&gt;
&lt;p&gt;Many of us have configured our CI to run whenever a commit is pushed to a pull request (PR). While this gives great peace of mind to see that our tests pass, we can’t help but wonder if this is really necessary.&lt;/p&gt;
&lt;p&gt;One pattern we like to use when we are still working on a PR is to keep it in &lt;a href=&quot;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request&quot;&gt;Draft mode*&lt;/a&gt;. Once we are happy with our code and want some feedback, we mark the PR as as &lt;em&gt;Ready for review&lt;/em&gt;. We can configure the CI to only run once a PR is &lt;em&gt;Ready for review&lt;/em&gt;. This gives the reviewer peace of mind that the PR is bug free and is safe to be merged.&lt;/p&gt;
&lt;p&gt;This also saves a whole bunch of unnecessary CI runs, and gives you more control when actually running the CI.&lt;/p&gt;
&lt;p&gt;To set this up, add this to your github action:&lt;/p&gt;
&lt;h1 id=&quot;testsyml&quot;&gt;tests.yml&lt;/h1&gt;
&lt;p&gt;name: Tests&lt;/p&gt;
&lt;p&gt;on:
pull_request:
branches:
- main
types:
- opened
- reopened
- synchronize
- ready_for_review
push:
branches:
- main&lt;/p&gt;
&lt;p&gt;jobs:
test:
if: github.event.pull_request.draft == false
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steps:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ...See an example of how we have implemented this for one of our projects [here](https://github.com/duqtools/duqtools/blob/main/.github/workflows/test.yaml).&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;filter-by-changed-files&quot;&gt;Filter by changed files&lt;/h3&gt;
&lt;p&gt;Another common pattern we use is to only run a job when the relevant files have changed. Let’s say we have a simple project with the following folder structure:&lt;/p&gt;
&lt;p&gt;project-to-save-the-planet/
├── docs/
│   └── the_plan.md
│   └── …
├── src/
│   ├── save_the_planet.py
│   ├── supporting_documentation.md
│   └── …
├── tests/
│   └── …
├── …
└── README.mdWe don’t have to re-run all tests if something only changed in the documentation, nor do we have to rebuild the documentation if we only make changes to some tests. And if we only fix a typo in &lt;code&gt;README.md&lt;/code&gt; neither will be necessary. These restrictions can be enabled by adding filters in the &lt;code&gt;[paths](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore)&lt;/code&gt; section of the workflow triggers. These &lt;code&gt;paths&lt;/code&gt; specifications can also be combined with the other filters such as branches shown earlier, to trigger only if it matches the paths and **branch. **
Here’s an example configuration that triggers only on changes in the &lt;code&gt;docs&lt;/code&gt; folders:&lt;/p&gt;
&lt;h1 id=&quot;docsyml&quot;&gt;docs.yml&lt;/h1&gt;
&lt;p&gt;on:
push:
…
paths:
- ‘docs/**’&lt;/p&gt;
&lt;p&gt;jobs:
…Certain paths or types of files can also be excluded using an exclamation mark (&lt;code&gt;!&lt;/code&gt;). This can be useful if we want to trigger the tests to run on changes in &lt;code&gt;src/&lt;/code&gt; or &lt;code&gt;tests/&lt;/code&gt;, except when we make changes to some supporting documentation or other data that does not affect the outcome of the tests. Here’s an example of such a workflow:&lt;/p&gt;
&lt;h1 id=&quot;testsyml-1&quot;&gt;tests.yml&lt;/h1&gt;
&lt;p&gt;on:
push:
…
paths:
- ‘src/&lt;strong&gt;’
- ‘!src/supporting_documentation.md’
- ‘tests/&lt;/strong&gt;’&lt;/p&gt;
&lt;p&gt;jobs:
…&lt;/p&gt;
&lt;h3 id=&quot;use-cpu-versions-of-tensorflow-and-pytorch&quot;&gt;Use CPU versions of tensorflow and pytorch&lt;/h3&gt;
&lt;p&gt;If you are working in machine learning, you will know that tensorflow and pytorch are enormous libraries. Together with their dependencies, they can be several gigabytes in size. On a CI, downloading these packages can already take up to a minute.&lt;/p&gt;
&lt;p&gt;But, did you know that most of this space is taken up by GPU support? Try using &lt;code&gt;[tensorflow-cpu](https://pypi.org/project/tensorflow-cpu/)&lt;/code&gt;or &lt;code&gt;[pytorch-cpu](https://pytorch.org/get-started/locally/)&lt;/code&gt; instead of full-fat libraries. From our experience, this reduces the install size of our Python environments by approximately 1.5 GB on linux systems (this has no effect on Windows and Mac runners). The trick here is to install these prior to installing your package via &lt;code&gt;pip&lt;/code&gt;. These will then be skipped by &lt;code&gt;pip&lt;/code&gt; if these packages are also defined in your &lt;code&gt;pyproject.toml&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt;. Considering that all the common CI systems typically do not have GPUs in them, this makes the installs significantly lighter and therefore faster to run too!&lt;/p&gt;
&lt;p&gt;To do so, add this step to your GitHub action prior to installing your package:&lt;/p&gt;
&lt;h1 id=&quot;testsyml-2&quot;&gt;tests.yml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Install tensorflow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if: runner.os == &apos;Linux&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    python3 -m pip install tensorflow-cpu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Install pytorch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if: runner.os == &apos;Linux&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    python3 -m pip install torch --index-url https://download.pytorch.org/whl/cpu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Install dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      pip install .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Why throw away when you can reuse?&lt;/em&gt; Photo by &lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Upcycled_Roses.jpg&quot;&gt;JulieN2212 via Wikimedia Commons&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reuse&quot;&gt;Reuse&lt;/h2&gt;
&lt;p&gt;If you must run the CI, the best way to reduce its impact is limit the actual work that needs to be done.&lt;/p&gt;
&lt;p&gt;With the &lt;a href=&quot;https://github.com/actions/cache&quot;&gt;cache action&lt;/a&gt;, you can cache dependencies and build outputs to make your workflows faster and thus more efficient. Maybe you need to compile some dependency, download and pre-compute some data, or set up your python environment via &lt;code&gt;pip&lt;/code&gt;. These typically do not change much from run to run, so try to cache these where possible.&lt;/p&gt;
&lt;h3 id=&quot;caching-your-python-environment&quot;&gt;Caching your Python environment&lt;/h3&gt;
&lt;p&gt;Just the installation of the dependencies of some Python code via pip can be quite significant. Some libraries just seem to pull in an endless stream of dependencies. So, why don’t we cache our entire Python environment?&lt;/p&gt;
&lt;p&gt;Below is a snippet that we find effective in our workflows for Python code.&lt;/p&gt;
&lt;p&gt;As the cache key, we use a combination of the Python directory name (this includes the version) in combination with the hash of the &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;setup.cfg&lt;/code&gt;, or &lt;code&gt;requirements.txt&lt;/code&gt; file. Whenever these get updated, the cache gets invalidated and regenerated.&lt;/p&gt;
&lt;p&gt;This means we can also safely skip the &lt;code&gt;pip install&lt;/code&gt; step if we hit the cache. Depending on the number of dependencies, this virtually eliminates the setup time of your workflow.&lt;/p&gt;
&lt;h1 id=&quot;testsyaml&quot;&gt;tests.yaml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - uses: actions/cache@v3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id: cache-python-env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      path: ${{ env.pythonLocation }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      key: ${{ env.pythonLocation }}-${{ hashFiles(&apos;pyproject.toml&apos;) }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - name: Install dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if: steps.cache-python-env.outputs.cache-hit != &apos;true&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      python -m pip install -e .[develop]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;caching-any-directory&quot;&gt;Caching any directory&lt;/h3&gt;
&lt;p&gt;To generalize the action below, the example below shows how any directory can be cached. We have used this to cache dependencies that need to be compiled. This can save minutes if not more from your workflow every single time it gets triggered.&lt;/p&gt;
&lt;p&gt;We recommend adding a version to the cache key, so that you can easily invalidate the cache and force a re-trigger through the action itself.&lt;/p&gt;
&lt;p&gt;Any subsequent workflows, will restore the directory from GitHub’s cache.&lt;/p&gt;
&lt;h1 id=&quot;testsyaml-1&quot;&gt;tests.yaml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - uses: actions/cache@v3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id: cache-important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      path: important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      key: cache-key-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - name: Compile dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if: steps.cache-important-dependency.outputs.cache-hit != &apos;true&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      mkdir important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      cd important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      echo &quot;All I want is world peace... Or a piece of the world.&quot; &amp;#x26;gt; t.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Failing code into the red bin, please. Photo by &lt;a href=&quot;https://unsplash.com/@pawel_czerwinski?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Pawel Czerwinski&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;recycle&quot;&gt;Recycle&lt;/h2&gt;
&lt;p&gt;Finally, can we recycle **anything that is left when our CI run is done? Although not exactly trash, what’s typically leftover is the test results: which tests passed and failed. If any tests failed, those definitely have to pass before we want to continue. It makes sense then to re-run those tests first, and we can stop if any of those fail again.&lt;/p&gt;
&lt;h3 id=&quot;pytest-last-failed&quot;&gt;Pytest last failed&lt;/h3&gt;
&lt;p&gt;Pytest has a very handy &lt;code&gt;[--last-failed](https://docs.pytest.org/en/stable/how-to/cache.html)&lt;/code&gt; flag for exactly this purpose, but that obviously depends on a local cache to remember the outcome of the previous run. Luckily for you, &lt;a href=&quot;https://github.com/sjvrijn/pytest-last-failed&quot;&gt;we’ve already made a GitHub action&lt;/a&gt; that takes care of setting this up for you! Simply use this action instead of your &lt;code&gt;*run: pytest --my --pytest --args*&lt;/code&gt; step:&lt;/p&gt;
&lt;h1 id=&quot;testsyaml-2&quot;&gt;tests.yaml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
# create python environment and install pytest&lt;br&gt;
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Run pytest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  uses: sjvrijn/pytest-last-failed@v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    pytest-args: &apos;--my --pytest --args&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this blog post, we introduced some options to make your sustainable software development more sustainable to the planet as well, whether by preventing double work or avoiding unnecessary CI runs in the first place. All it takes is a few extra lines in your workflows to help save the planet and save yourself some time in the process.&lt;/p&gt;
&lt;p&gt;Of course, there are many other strategies to reduce your impact, such as using pre-built dependencies, more efficient libraries, or preparing a docker container for complex test environments.&lt;/p&gt;
&lt;p&gt;It turns out that once you start looking, there are many technical options to reduce your impact. The more difficult challenge may be a social one, to convince your peers that change is necessary. In the end, we hope that this blog post inspired you, and that you will consider the environmental impact of your work.&lt;/p&gt;</description><pubDate>Tue, 20 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;**&lt;/p&gt;
&lt;h1 id=&quot;reduce-reuse-recycle-save-the-planet-one-github-action-at-a-time&quot;&gt;Reduce, reuse, recycle: save the planet one GitHub action at a time&lt;/h1&gt;
&lt;p&gt;53&lt;/p&gt;
&lt;p&gt;Written by &lt;a href=&quot;https://medium.com/@stefsmeets&quot;&gt;Stef Smeets&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@s.vanrijn&quot;&gt;Sander van Rijn&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@ralphkayden?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Ralph (Ravi) Kayden&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;Ask any environmentalist what you can do to help combat climate change and protect the environment, and they will tell you to &lt;a href=&quot;https://en.wikipedia.org/wiki/Waste_hierarchy&quot;&gt;“Reduce, Reuse, Recycle.”&lt;/a&gt; These actions are focused on maximizing practical benefit while minimizing the cost to the environment through conservation of resources and preventing the emission of greenhouse gases.&lt;/p&gt;
&lt;p&gt;As software engineers, we are big fans of integration and continuous delivery (CI/CD) workflows as part of sustainable software development. GitHub actions is &lt;a href=&quot;https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#about-billing-for-github-actions&quot;&gt;completely free for public repositories&lt;/a&gt;, so why wouldn’t we? We use it for everything, from code analysis and linting, running tests and builds in isolated environments, generating documentation on &lt;a href=&quot;https://docs.readthedocs.io/en/stable/integrations.html&quot;&gt;readthedocs&lt;/a&gt;, and publishing packages on &lt;a href=&quot;https://github.com/marketplace/actions/pypi-publish&quot;&gt;PyPI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Until all of our power comes from nuclear fusion, and data centers can be made of trees, running any code will have an environmental impact: CO2 and other emissions from the power used and the production of the computers it runs on. Not writing code won’t solve our problems either, so we need to find places in our workflow where we can reduce our impact.&lt;/p&gt;
&lt;p&gt;Many CI/CD systems are configured to run automatically, often out of sight, so their impact to the planet adds up quickly. We have been asking ourselves some questions, like what we can do to make our use of CI/CD more sustainable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do we need to build the documentation for every commit we make to the code?&lt;/li&gt;
&lt;li&gt;Do we need to test on every version of Python on all platforms to ensure code works?&lt;/li&gt;
&lt;li&gt;Do we need to run all our machine learning notebooks on every push?&lt;/li&gt;
&lt;li&gt;When we fix a typo in our documentation, do we need to run a complete suite of regression tests?&lt;/li&gt;
&lt;li&gt;When we fix a bug, can we get away just re-running the failed tests?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this blogpost we share what we have learned and give some ideas about what you can do to reduce your impact using &lt;a href=&quot;https://docs.github.com/en/actions&quot;&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why-bother&quot;&gt;Why bother?&lt;/h2&gt;
&lt;p&gt;Data centers need large amounts of energy, from running servers, computing hardware, and refrigerating equipment. And, let’s not forget that the production of servers, cables and supporting equipment, and mining of the required raw materials also contribute.&lt;/p&gt;
&lt;p&gt;According to the &lt;a href=&quot;https://www.iea.org/reports/data-centres-and-data-transmission-networks&quot;&gt;IEA&lt;/a&gt;, all data centers and data transmission networks account for 2–3% of global electricity use. This corresponds to 300 Mt &lt;a href=&quot;https://en.wikipedia.org/wiki/Global_warming_potential#Carbon_dioxide_equivalent&quot;&gt;CO2-eq&lt;/a&gt; in 2020 (0.9% energy related greenhouse gas emissions). The costs for the environment are enormous. Although improvements in efficiency and hyperscale data centers help limit the growth in energy demands somewhat, the demand for data workloads and internet traffic still grows every year.&lt;/p&gt;
&lt;p&gt;GitHub (this blog is about GitHub Actions after all!) claims to be &lt;a href=&quot;https://github.blog/2021-04-22-environmental-sustainability-github/&quot;&gt;committed to environmental sustainability&lt;/a&gt;. A noble effort, but its parent company Microsoft increased its CO2 emissions by &lt;a href=&quot;https://aka.ms/SustainabilityReport2022&quot;&gt;nearly 15% from 2020 to 2022&lt;/a&gt;. Most companies who claim to achieve ‘net zero’ do so not by reducing their emissions, but by compensating elsewhere. Microsoft compensated only about 10% of their emissions in 2022. This is typically done through &lt;a href=&quot;https://en.wikipedia.org/wiki/Guarantee_of_origin&quot;&gt;buying certified green energy&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Carbon_offsets_and_credits&quot;&gt;CO2 compensation&lt;/a&gt;, or &lt;a href=&quot;https://en.wikipedia.org/wiki/Emissions_trading&quot;&gt;emission trading&lt;/a&gt;. This allows companies to be green on paper by trading certificates, with little direct effect on their business operations. Such climate certificates are often sold on a promise, like planting trees or saving a forest from clearing. Better than nothing, but it’s even better to not have those emissions in the first place.&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@etiennegirardet?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Etienne Girardet&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reduce&quot;&gt;Reduce&lt;/h2&gt;
&lt;p&gt;So, what can we do?&lt;/p&gt;
&lt;p&gt;The best thing we can do is prevent resource usage by reducing the number of times we trigger the CI/CD workflows.&lt;/p&gt;
&lt;h3 id=&quot;restrict-branch-and-event-type&quot;&gt;Restrict branch and event type&lt;/h3&gt;
&lt;p&gt;Many of us have configured our CI to run whenever a commit is pushed to a pull request (PR). While this gives great peace of mind to see that our tests pass, we can’t help but wonder if this is really necessary.&lt;/p&gt;
&lt;p&gt;One pattern we like to use when we are still working on a PR is to keep it in &lt;a href=&quot;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request&quot;&gt;Draft mode*&lt;/a&gt;. Once we are happy with our code and want some feedback, we mark the PR as as &lt;em&gt;Ready for review&lt;/em&gt;. We can configure the CI to only run once a PR is &lt;em&gt;Ready for review&lt;/em&gt;. This gives the reviewer peace of mind that the PR is bug free and is safe to be merged.&lt;/p&gt;
&lt;p&gt;This also saves a whole bunch of unnecessary CI runs, and gives you more control when actually running the CI.&lt;/p&gt;
&lt;p&gt;To set this up, add this to your github action:&lt;/p&gt;
&lt;h1 id=&quot;testsyml&quot;&gt;tests.yml&lt;/h1&gt;
&lt;p&gt;name: Tests&lt;/p&gt;
&lt;p&gt;on:
pull_request:
branches:
- main
types:
- opened
- reopened
- synchronize
- ready_for_review
push:
branches:
- main&lt;/p&gt;
&lt;p&gt;jobs:
test:
if: github.event.pull_request.draft == false
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;steps:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ...See an example of how we have implemented this for one of our projects [here](https://github.com/duqtools/duqtools/blob/main/.github/workflows/test.yaml).&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;filter-by-changed-files&quot;&gt;Filter by changed files&lt;/h3&gt;
&lt;p&gt;Another common pattern we use is to only run a job when the relevant files have changed. Let’s say we have a simple project with the following folder structure:&lt;/p&gt;
&lt;p&gt;project-to-save-the-planet/
├── docs/
│   └── the_plan.md
│   └── …
├── src/
│   ├── save_the_planet.py
│   ├── supporting_documentation.md
│   └── …
├── tests/
│   └── …
├── …
└── README.mdWe don’t have to re-run all tests if something only changed in the documentation, nor do we have to rebuild the documentation if we only make changes to some tests. And if we only fix a typo in &lt;code&gt;README.md&lt;/code&gt; neither will be necessary. These restrictions can be enabled by adding filters in the &lt;code&gt;[paths](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore)&lt;/code&gt; section of the workflow triggers. These &lt;code&gt;paths&lt;/code&gt; specifications can also be combined with the other filters such as branches shown earlier, to trigger only if it matches the paths and **branch. **
Here’s an example configuration that triggers only on changes in the &lt;code&gt;docs&lt;/code&gt; folders:&lt;/p&gt;
&lt;h1 id=&quot;docsyml&quot;&gt;docs.yml&lt;/h1&gt;
&lt;p&gt;on:
push:
…
paths:
- ‘docs/**’&lt;/p&gt;
&lt;p&gt;jobs:
…Certain paths or types of files can also be excluded using an exclamation mark (&lt;code&gt;!&lt;/code&gt;). This can be useful if we want to trigger the tests to run on changes in &lt;code&gt;src/&lt;/code&gt; or &lt;code&gt;tests/&lt;/code&gt;, except when we make changes to some supporting documentation or other data that does not affect the outcome of the tests. Here’s an example of such a workflow:&lt;/p&gt;
&lt;h1 id=&quot;testsyml-1&quot;&gt;tests.yml&lt;/h1&gt;
&lt;p&gt;on:
push:
…
paths:
- ‘src/&lt;strong&gt;’
- ‘!src/supporting_documentation.md’
- ‘tests/&lt;/strong&gt;’&lt;/p&gt;
&lt;p&gt;jobs:
…&lt;/p&gt;
&lt;h3 id=&quot;use-cpu-versions-of-tensorflow-and-pytorch&quot;&gt;Use CPU versions of tensorflow and pytorch&lt;/h3&gt;
&lt;p&gt;If you are working in machine learning, you will know that tensorflow and pytorch are enormous libraries. Together with their dependencies, they can be several gigabytes in size. On a CI, downloading these packages can already take up to a minute.&lt;/p&gt;
&lt;p&gt;But, did you know that most of this space is taken up by GPU support? Try using &lt;code&gt;[tensorflow-cpu](https://pypi.org/project/tensorflow-cpu/)&lt;/code&gt;or &lt;code&gt;[pytorch-cpu](https://pytorch.org/get-started/locally/)&lt;/code&gt; instead of full-fat libraries. From our experience, this reduces the install size of our Python environments by approximately 1.5 GB on linux systems (this has no effect on Windows and Mac runners). The trick here is to install these prior to installing your package via &lt;code&gt;pip&lt;/code&gt;. These will then be skipped by &lt;code&gt;pip&lt;/code&gt; if these packages are also defined in your &lt;code&gt;pyproject.toml&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt;. Considering that all the common CI systems typically do not have GPUs in them, this makes the installs significantly lighter and therefore faster to run too!&lt;/p&gt;
&lt;p&gt;To do so, add this step to your GitHub action prior to installing your package:&lt;/p&gt;
&lt;h1 id=&quot;testsyml-2&quot;&gt;tests.yml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Install tensorflow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if: runner.os == &apos;Linux&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    python3 -m pip install tensorflow-cpu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Install pytorch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if: runner.os == &apos;Linux&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    python3 -m pip install torch --index-url https://download.pytorch.org/whl/cpu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Install dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      pip install .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Why throw away when you can reuse?&lt;/em&gt; Photo by &lt;a href=&quot;https://commons.wikimedia.org/wiki/File:Upcycled_Roses.jpg&quot;&gt;JulieN2212 via Wikimedia Commons&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reuse&quot;&gt;Reuse&lt;/h2&gt;
&lt;p&gt;If you must run the CI, the best way to reduce its impact is limit the actual work that needs to be done.&lt;/p&gt;
&lt;p&gt;With the &lt;a href=&quot;https://github.com/actions/cache&quot;&gt;cache action&lt;/a&gt;, you can cache dependencies and build outputs to make your workflows faster and thus more efficient. Maybe you need to compile some dependency, download and pre-compute some data, or set up your python environment via &lt;code&gt;pip&lt;/code&gt;. These typically do not change much from run to run, so try to cache these where possible.&lt;/p&gt;
&lt;h3 id=&quot;caching-your-python-environment&quot;&gt;Caching your Python environment&lt;/h3&gt;
&lt;p&gt;Just the installation of the dependencies of some Python code via pip can be quite significant. Some libraries just seem to pull in an endless stream of dependencies. So, why don’t we cache our entire Python environment?&lt;/p&gt;
&lt;p&gt;Below is a snippet that we find effective in our workflows for Python code.&lt;/p&gt;
&lt;p&gt;As the cache key, we use a combination of the Python directory name (this includes the version) in combination with the hash of the &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;setup.cfg&lt;/code&gt;, or &lt;code&gt;requirements.txt&lt;/code&gt; file. Whenever these get updated, the cache gets invalidated and regenerated.&lt;/p&gt;
&lt;p&gt;This means we can also safely skip the &lt;code&gt;pip install&lt;/code&gt; step if we hit the cache. Depending on the number of dependencies, this virtually eliminates the setup time of your workflow.&lt;/p&gt;
&lt;h1 id=&quot;testsyaml&quot;&gt;tests.yaml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - uses: actions/cache@v3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id: cache-python-env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      path: ${{ env.pythonLocation }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      key: ${{ env.pythonLocation }}-${{ hashFiles(&apos;pyproject.toml&apos;) }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - name: Install dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if: steps.cache-python-env.outputs.cache-hit != &apos;true&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      python -m pip install -e .[develop]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;caching-any-directory&quot;&gt;Caching any directory&lt;/h3&gt;
&lt;p&gt;To generalize the action below, the example below shows how any directory can be cached. We have used this to cache dependencies that need to be compiled. This can save minutes if not more from your workflow every single time it gets triggered.&lt;/p&gt;
&lt;p&gt;We recommend adding a version to the cache key, so that you can easily invalidate the cache and force a re-trigger through the action itself.&lt;/p&gt;
&lt;p&gt;Any subsequent workflows, will restore the directory from GitHub’s cache.&lt;/p&gt;
&lt;h1 id=&quot;testsyaml-1&quot;&gt;tests.yaml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - uses: actions/cache@v3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    id: cache-important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      path: important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      key: cache-key-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  - name: Compile dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    if: steps.cache-important-dependency.outputs.cache-hit != &apos;true&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    run: |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      mkdir important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      cd important-dependency&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;      echo &quot;All I want is world peace... Or a piece of the world.&quot; &amp;#x26;gt; t.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Failing code into the red bin, please. Photo by &lt;a href=&quot;https://unsplash.com/@pawel_czerwinski?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Pawel Czerwinski&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;recycle&quot;&gt;Recycle&lt;/h2&gt;
&lt;p&gt;Finally, can we recycle **anything that is left when our CI run is done? Although not exactly trash, what’s typically leftover is the test results: which tests passed and failed. If any tests failed, those definitely have to pass before we want to continue. It makes sense then to re-run those tests first, and we can stop if any of those fail again.&lt;/p&gt;
&lt;h3 id=&quot;pytest-last-failed&quot;&gt;Pytest last failed&lt;/h3&gt;
&lt;p&gt;Pytest has a very handy &lt;code&gt;[--last-failed](https://docs.pytest.org/en/stable/how-to/cache.html)&lt;/code&gt; flag for exactly this purpose, but that obviously depends on a local cache to remember the outcome of the previous run. Luckily for you, &lt;a href=&quot;https://github.com/sjvrijn/pytest-last-failed&quot;&gt;we’ve already made a GitHub action&lt;/a&gt; that takes care of setting this up for you! Simply use this action instead of your &lt;code&gt;*run: pytest --my --pytest --args*&lt;/code&gt; step:&lt;/p&gt;
&lt;h1 id=&quot;testsyaml-2&quot;&gt;tests.yaml&lt;/h1&gt;
&lt;p&gt;jobs:
test:
steps:
# create python environment and install pytest&lt;br&gt;
…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;- name: Run pytest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  uses: sjvrijn/pytest-last-failed@v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    pytest-args: &apos;--my --pytest --args&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this blog post, we introduced some options to make your sustainable software development more sustainable to the planet as well, whether by preventing double work or avoiding unnecessary CI runs in the first place. All it takes is a few extra lines in your workflows to help save the planet and save yourself some time in the process.&lt;/p&gt;
&lt;p&gt;Of course, there are many other strategies to reduce your impact, such as using pre-built dependencies, more efficient libraries, or preparing a docker container for complex test environments.&lt;/p&gt;
&lt;p&gt;It turns out that once you start looking, there are many technical options to reduce your impact. The more difficult challenge may be a social one, to convince your peers that change is necessary. In the end, we hope that this blog post inspired you, and that you will consider the environmental impact of your work.&lt;/p&gt;</content:encoded><author>Stef Smeets</author></item><item><title>NL-RSE: What Open Science can learn from Open Source</title><link>https://blog2.esciencecenter.nl/posts/2023-06-08---nl-rse-what-open-science-can-learn-from-open-source</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-06-08---nl-rse-what-open-science-can-learn-from-open-source</guid><description>&lt;p&gt;&lt;em&gt;NL-RSE meetups are bimonthly events where the &lt;em&gt;&lt;a href=&quot;https://nl-rse.org/&quot;&gt;&lt;em&gt;Dutch community for Research Software Engineers&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; comes together to learn new skills or hear inspiring talks by experts in the field of Open Science, Open Source, Research Software or Software Engineering. The &lt;em&gt;&lt;a href=&quot;https://www.eventbrite.com/e/nl-rse-introduction-to-automated-software-testing-tickets-633227900697&quot;&gt;&lt;em&gt;next NL-RSE meetup&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; takes place on 15 June in Leiden and will be about automated testing. You can sign up for the meetup &lt;em&gt;&lt;a href=&quot;https://www.eventbrite.com/e/nl-rse-introduction-to-automated-software-testing-tickets-633227900697&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and the mailing list &lt;em&gt;&lt;a href=&quot;https://nl-rse.org/pages/join&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Back in 2021, lawyer, philosopher, and Open Science advocate &lt;a href=&quot;https://twitter.com/jdelacueva&quot;&gt;Javier de la Cueva&lt;/a&gt; gave a talk at an NL-RSE meetup about what Open Science can learn from Open Source. This post is a report of that talk — originally first posted on the &lt;a href=&quot;https://nl-rse.org/posts/2021-07-07-jdlc-meetup-june&quot;&gt;NL-RSE blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;NL-RSE: What Open Science can learn from Open Source&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/nl-rse-what-open-science-can-learn-from--46f96ea7.B4loulY6_1PWI65.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rocinante_11?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mick Haupt&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/jdelacueva&quot;&gt;Javier de la Cueva&lt;/a&gt; does not like slideshows — “&lt;em&gt;it limits the ways we communicate, like squeezing thoughts into 140 characters&lt;/em&gt;”, but for the NL-RSE meetup, he made one anyway. De la Cueva is a lawyer, philosopher, and Open Science advocate, with expertise in free software and intellectual property. During the &lt;a href=&quot;https://nl-rse.org/events/2021-06-11-meetup&quot;&gt;meetup on Friday, 11 June 2021&lt;/a&gt;, he gave a passionate talk about what the Open Science movement can learn from the Free Software movement, blending the topics of software development and science in a way not unfamiliar to those identifying as RSEs.&lt;/p&gt;
&lt;p&gt;If anyone’s an expert on these topics, it’s De la Cueva. He switched from Windows to Linux in 2000, after receiving a Blue Screen of Death on his Windows machine — “&lt;em&gt;Why would you create a wall that doesn’t allow me to understand something I paid for?&lt;/em&gt;”. In 2002, when Wikipedia was planning to commercialize, De la Cueva and others &lt;a href=&quot;https://www.wired.co.uk/article/wikipedia-spanish-fork&quot;&gt;forked the Spanish version of the page onto a server in the University of Seville, Spain&lt;/a&gt;, proving to Wikipedia’s owners that the entire project could be run on non-profit servers — a move some consider responsible for keeping Wikipedia free of commercial ads and paywalls to this day. Later, in 2006, he was, in his own words, “&lt;em&gt;the first lawyer&lt;/em&gt; &lt;em&gt;to obtain a judicial ruling where the term &lt;em&gt;&lt;a href=&quot;https://copyleft.org/&quot;&gt;&lt;em&gt;copyleft&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; was included&lt;/em&gt;”. For the case in question, &lt;a href=&quot;https://edri.org/our-work/edrigramnumber4-9spaincc/&quot;&gt;Ladinamo&lt;/a&gt;, De la Cueva defended the owners of a bar who were sued for failing to pay the compulsory licensing fee for playing music in their establishment. He won the case by successfully arguing that the music’s Creative Commons licenses allowed for public performance, and that no additional fees had to be paid.&lt;/p&gt;
&lt;p&gt;In 2014, De la Cueva defended his philosophy thesis, &lt;a href=&quot;https://www.researchgate.net/publication/266487696_Pragmaticas_tecnologicas_ciudadanas_y_regeneracion_democratica&quot;&gt;Citizen Technological Pragmatics and Democratic Regeneration&lt;/a&gt; (abstract in English, thesis in Spanish). The work discusses how open access, open science, open data, and open government affect public knowledge and democracy. The thesis reflects Javier’s varied interests, providing insights from the fields of law, technology, political philosophy, and philosophy of language. Today, De la Cueva works as a lawyer and professor at IE University in Madrid. Along with his university teaching activities, De la Cueva is actively involved in science dissemination, “because a functioning democracy needs its citizens to be informed about scientific development*”. Science, he says, should not be about &lt;em&gt;who&lt;/em&gt; does it, but about &lt;em&gt;what&lt;/em&gt; scientists are doing. A common sensical enough statement, but one that may sound like an unrealistic utopia to anyone who has ever worked in academia.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;NL-RSE: What Open Science can learn from Open Source&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/nl-rse-what-open-science-can-learn-from--e598c5b9.fh3CfeSY_Z2mRXuJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@umby?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Umberto&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;American sociologist of science [Robert K. Merton](&lt;a href=&quot;https://en.wikipedia.org/wiki/Robert_K._Merton#&quot;&gt;https://en.wikipedia.org/wiki/Robert_K._Merton#&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sociology_of_science_and_CUDOS) recognized this tension: he observed that the social system of science works both in agreement with, but also often in contradiction to, its own ideal. Merton expressed the ideal of science in four concrete moral principles, referred to as CUDOS** : Science must be &lt;strong&gt;C&lt;/strong&gt;ommunist (in the sense of communal), meaning that all scientists have common ownership of scientific goods, giving up intellectual property of their work in exchange for recognition. It should be &lt;strong&gt;U&lt;/strong&gt;niversal, or independent of the socio-political status and personal attributes of its participants. Scientific institutions should also be &lt;strong&gt;D&lt;/strong&gt;isinterested, meaning personal gain of individuals within them is inferior to the greater goal of the scientific enterprise. Lastly, science must have &lt;strong&gt;O&lt;/strong&gt;rganised &lt;strong&gt;S&lt;/strong&gt;cepticism.&lt;/p&gt;
&lt;p&gt;For science to be in line with CUDOS, we have to rethink the relationship between scientists and their work. Because every scientific institution inevitably brings their own view of the world to the way they collect, analyse, and publish their data, open access to scientific publications only is not enough. After all, after data is collected, it is translated and analysed (often with the use of in-house developed software), written up into results, preprints and research papers, which can obscure the bias inherent in every step of the way leading up to that publication. Ideally, science openly shares every output that it creates, including data, publications, education, software and other tools. These outputs should be reused to two ends: First, to reproduce existing findings, De la Cueva argues — “&lt;em&gt;there is too much emphasis on novelty in science&lt;/em&gt;”. Second, to combine all levels of existing scientific outputs into new structures, which De la Cueva considers crucial for innovation.&lt;/p&gt;
&lt;p&gt;Open Science can look at the Free Software movement for an example on how to openly share its output. Free Software developers recognise the importance of their software’s reusability, which means they understand the importance of licensing and diversity of licenses. Scientists, on the other hand, do not hold the power to put a license on their scientific output. De la Cueva argues that this should change. Science could, for example, take inspiration from the Internet Engineering Task Force (IETF), which manages standards for the Internet. Any contributor permits the IETF to distribute their contributions freely, and in turn can use any of the other standards, which have been licensed in the same way. This results in an open Internet that is freely accessible to all. If we want CUDOS for science, the same mechanism could be applied to scientific outputs, where scientists permit their contributions to be distributed freely, and in turn are able to freely use others’ contributions.&lt;/p&gt;
&lt;p&gt;De la Cueva points at two signs that science is moving in the right direction. First, the existence of preprint servers. Second, the &lt;a href=&quot;https://www.aje.com/arc/open-access-changing-landscape/&quot;&gt;rise in peer-reviewed open access journals&lt;/a&gt;. And arguably, the increasingly common practice of publicly sharing research software, and adherence to FAIR data principles, can be counted as positive signs too. But there’s still work to be done: “&lt;em&gt;We still pay 9500 euros to obtain open access in&lt;/em&gt; Nature. &lt;em&gt;And the default for publications is still&lt;/em&gt; All rights reserved. &lt;em&gt;This has to end.&lt;/em&gt;”&lt;/p&gt;
&lt;p&gt;Thanks to Lourens Veen and Pablo Rodríguez-Sánchez for helpful comments and additions.&lt;/p&gt;</description><pubDate>Thu, 08 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;NL-RSE meetups are bimonthly events where the &lt;em&gt;&lt;a href=&quot;https://nl-rse.org/&quot;&gt;&lt;em&gt;Dutch community for Research Software Engineers&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; comes together to learn new skills or hear inspiring talks by experts in the field of Open Science, Open Source, Research Software or Software Engineering. The &lt;em&gt;&lt;a href=&quot;https://www.eventbrite.com/e/nl-rse-introduction-to-automated-software-testing-tickets-633227900697&quot;&gt;&lt;em&gt;next NL-RSE meetup&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; takes place on 15 June in Leiden and will be about automated testing. You can sign up for the meetup &lt;em&gt;&lt;a href=&quot;https://www.eventbrite.com/e/nl-rse-introduction-to-automated-software-testing-tickets-633227900697&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, and the mailing list &lt;em&gt;&lt;a href=&quot;https://nl-rse.org/pages/join&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Back in 2021, lawyer, philosopher, and Open Science advocate &lt;a href=&quot;https://twitter.com/jdelacueva&quot;&gt;Javier de la Cueva&lt;/a&gt; gave a talk at an NL-RSE meetup about what Open Science can learn from Open Source. This post is a report of that talk — originally first posted on the &lt;a href=&quot;https://nl-rse.org/posts/2021-07-07-jdlc-meetup-june&quot;&gt;NL-RSE blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;NL-RSE: What Open Science can learn from Open Source&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/nl-rse-what-open-science-can-learn-from--46f96ea7.B4loulY6_1PWI65.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rocinante_11?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Mick Haupt&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/jdelacueva&quot;&gt;Javier de la Cueva&lt;/a&gt; does not like slideshows — “&lt;em&gt;it limits the ways we communicate, like squeezing thoughts into 140 characters&lt;/em&gt;”, but for the NL-RSE meetup, he made one anyway. De la Cueva is a lawyer, philosopher, and Open Science advocate, with expertise in free software and intellectual property. During the &lt;a href=&quot;https://nl-rse.org/events/2021-06-11-meetup&quot;&gt;meetup on Friday, 11 June 2021&lt;/a&gt;, he gave a passionate talk about what the Open Science movement can learn from the Free Software movement, blending the topics of software development and science in a way not unfamiliar to those identifying as RSEs.&lt;/p&gt;
&lt;p&gt;If anyone’s an expert on these topics, it’s De la Cueva. He switched from Windows to Linux in 2000, after receiving a Blue Screen of Death on his Windows machine — “&lt;em&gt;Why would you create a wall that doesn’t allow me to understand something I paid for?&lt;/em&gt;”. In 2002, when Wikipedia was planning to commercialize, De la Cueva and others &lt;a href=&quot;https://www.wired.co.uk/article/wikipedia-spanish-fork&quot;&gt;forked the Spanish version of the page onto a server in the University of Seville, Spain&lt;/a&gt;, proving to Wikipedia’s owners that the entire project could be run on non-profit servers — a move some consider responsible for keeping Wikipedia free of commercial ads and paywalls to this day. Later, in 2006, he was, in his own words, “&lt;em&gt;the first lawyer&lt;/em&gt; &lt;em&gt;to obtain a judicial ruling where the term &lt;em&gt;&lt;a href=&quot;https://copyleft.org/&quot;&gt;&lt;em&gt;copyleft&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; was included&lt;/em&gt;”. For the case in question, &lt;a href=&quot;https://edri.org/our-work/edrigramnumber4-9spaincc/&quot;&gt;Ladinamo&lt;/a&gt;, De la Cueva defended the owners of a bar who were sued for failing to pay the compulsory licensing fee for playing music in their establishment. He won the case by successfully arguing that the music’s Creative Commons licenses allowed for public performance, and that no additional fees had to be paid.&lt;/p&gt;
&lt;p&gt;In 2014, De la Cueva defended his philosophy thesis, &lt;a href=&quot;https://www.researchgate.net/publication/266487696_Pragmaticas_tecnologicas_ciudadanas_y_regeneracion_democratica&quot;&gt;Citizen Technological Pragmatics and Democratic Regeneration&lt;/a&gt; (abstract in English, thesis in Spanish). The work discusses how open access, open science, open data, and open government affect public knowledge and democracy. The thesis reflects Javier’s varied interests, providing insights from the fields of law, technology, political philosophy, and philosophy of language. Today, De la Cueva works as a lawyer and professor at IE University in Madrid. Along with his university teaching activities, De la Cueva is actively involved in science dissemination, “because a functioning democracy needs its citizens to be informed about scientific development*”. Science, he says, should not be about &lt;em&gt;who&lt;/em&gt; does it, but about &lt;em&gt;what&lt;/em&gt; scientists are doing. A common sensical enough statement, but one that may sound like an unrealistic utopia to anyone who has ever worked in academia.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;NL-RSE: What Open Science can learn from Open Source&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/nl-rse-what-open-science-can-learn-from--e598c5b9.fh3CfeSY_Z2mRXuJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@umby?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Umberto&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;American sociologist of science [Robert K. Merton](&lt;a href=&quot;https://en.wikipedia.org/wiki/Robert_K._Merton#&quot;&gt;https://en.wikipedia.org/wiki/Robert_K._Merton#&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sociology_of_science_and_CUDOS) recognized this tension: he observed that the social system of science works both in agreement with, but also often in contradiction to, its own ideal. Merton expressed the ideal of science in four concrete moral principles, referred to as CUDOS** : Science must be &lt;strong&gt;C&lt;/strong&gt;ommunist (in the sense of communal), meaning that all scientists have common ownership of scientific goods, giving up intellectual property of their work in exchange for recognition. It should be &lt;strong&gt;U&lt;/strong&gt;niversal, or independent of the socio-political status and personal attributes of its participants. Scientific institutions should also be &lt;strong&gt;D&lt;/strong&gt;isinterested, meaning personal gain of individuals within them is inferior to the greater goal of the scientific enterprise. Lastly, science must have &lt;strong&gt;O&lt;/strong&gt;rganised &lt;strong&gt;S&lt;/strong&gt;cepticism.&lt;/p&gt;
&lt;p&gt;For science to be in line with CUDOS, we have to rethink the relationship between scientists and their work. Because every scientific institution inevitably brings their own view of the world to the way they collect, analyse, and publish their data, open access to scientific publications only is not enough. After all, after data is collected, it is translated and analysed (often with the use of in-house developed software), written up into results, preprints and research papers, which can obscure the bias inherent in every step of the way leading up to that publication. Ideally, science openly shares every output that it creates, including data, publications, education, software and other tools. These outputs should be reused to two ends: First, to reproduce existing findings, De la Cueva argues — “&lt;em&gt;there is too much emphasis on novelty in science&lt;/em&gt;”. Second, to combine all levels of existing scientific outputs into new structures, which De la Cueva considers crucial for innovation.&lt;/p&gt;
&lt;p&gt;Open Science can look at the Free Software movement for an example on how to openly share its output. Free Software developers recognise the importance of their software’s reusability, which means they understand the importance of licensing and diversity of licenses. Scientists, on the other hand, do not hold the power to put a license on their scientific output. De la Cueva argues that this should change. Science could, for example, take inspiration from the Internet Engineering Task Force (IETF), which manages standards for the Internet. Any contributor permits the IETF to distribute their contributions freely, and in turn can use any of the other standards, which have been licensed in the same way. This results in an open Internet that is freely accessible to all. If we want CUDOS for science, the same mechanism could be applied to scientific outputs, where scientists permit their contributions to be distributed freely, and in turn are able to freely use others’ contributions.&lt;/p&gt;
&lt;p&gt;De la Cueva points at two signs that science is moving in the right direction. First, the existence of preprint servers. Second, the &lt;a href=&quot;https://www.aje.com/arc/open-access-changing-landscape/&quot;&gt;rise in peer-reviewed open access journals&lt;/a&gt;. And arguably, the increasingly common practice of publicly sharing research software, and adherence to FAIR data principles, can be counted as positive signs too. But there’s still work to be done: “&lt;em&gt;We still pay 9500 euros to obtain open access in&lt;/em&gt; Nature. &lt;em&gt;And the default for publications is still&lt;/em&gt; All rights reserved. &lt;em&gt;This has to end.&lt;/em&gt;”&lt;/p&gt;
&lt;p&gt;Thanks to Lourens Veen and Pablo Rodríguez-Sánchez for helpful comments and additions.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/nl-rse-what-open-science-can-learn-from--46f96ea7.B4loulY6.jpg" medium="image"/><author>Lieke de Boer</author></item><item><title>Language Modeling: The First 100 Years</title><link>https://blog2.esciencecenter.nl/posts/2023-06-01---language-modeling-the-first-100-years</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-06-01---language-modeling-the-first-100-years</guid><description>&lt;p&gt;&lt;em&gt;ChatGPT has become the symbol for a new wave of Artificial Intelligence. New models with even stronger conversational skills are released on a weekly basis, and the world discusses about their impact on humanity. There are utopian and dystopian fantasies, as well as concrete potentials and risks. A view of the history of language modeling helps to understand the present and the future.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-7a4401d7.BU5-v53y_Z1Yf5uV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@brett_jordan?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Brett Jordan&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When Andrej Markov sat down with Alexander Pushkin’s poetic book &lt;em&gt;Eugene Onegin&lt;/em&gt; in 1913, he was not planning to distract himself from his work as a mathematician. Instead, he went through the verses and counted letters, resulting in the study “An Example of Statistical Investigation of the Text &lt;em&gt;Eugene Onegin&lt;/em&gt; Concerning the Connection of Samples in Chains”, &lt;a href=&quot;https://www.cambridge.org/core/journals/science-in-context/article/abs/an-example-of-statistical-investigation-of-the-text-eugene-onegin-concerning-the-connection-of-samples-in-chains/EA1E005FA0BC4522399A4E9DA0304862&quot;&gt;translated into English as late as 2006&lt;/a&gt;. The famous mathematician was not so much fascinated by the poetry, but by the distribution of consonants and vowels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;405&quot; height=&quot;599&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-ffedec5e.7v742PVF_ZV8yce.webp&quot; srcset=&quot;&quot;&gt;
Andrej Markov — By Unknown author — Converted into JPEG format from [1], Public Domain, &lt;a href=&quot;https://commons.wikimedia.org/w/index.php?curid=448609&quot;&gt;https://commons.wikimedia.org/w/index.php?curid=448609&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;causes-and-conditions&quot;&gt;Causes and Conditions&lt;/h2&gt;
&lt;p&gt;Markov demonstrated that the likelihood of a letter being a vowel or a consonant can be approximated from its preceding letters. Based on these findings, he developed a probabilistic model for causal sequences, today known as Markov chain. The so-called Markov assumption holds for language on various levels beyond characters, including words. Look at the following sentence stub:&lt;/p&gt;
&lt;p&gt;This is a big &amp;#x3C;?&gt;As readers, we cannot say which word should replace the &lt;em&gt;&amp;#x3C;?&gt;&lt;/em&gt;, but based on the preceding words, we know it is likely a noun (e.g. &lt;em&gt;house&lt;/em&gt; or &lt;em&gt;tree&lt;/em&gt;) or another adjective (e.g. *beautiful *or &lt;em&gt;green&lt;/em&gt;) and most certainly not a determiner (e.g. *the *or &lt;em&gt;a&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Conditional probability plays an important role: while &lt;em&gt;the&lt;/em&gt; is the most frequent word in English, it is very unlikely to occur in the position of the &lt;em&gt;&amp;#x3C;?&gt;&lt;/em&gt; above. Language modeling is about formalizing this kind of linguistic structures: what is the probability of a word &lt;em&gt;w&lt;/em&gt;, given a sequence of words &lt;em&gt;w1&lt;/em&gt;, &lt;em&gt;w2&lt;/em&gt;, … . The language model can be expressed mathematically as &lt;em&gt;P&lt;/em&gt;(&lt;em&gt;w&lt;/em&gt;|&lt;em&gt;c&lt;/em&gt;), where &lt;em&gt;c&lt;/em&gt; is short for the given word sequence*.* As English speakers, we know that for the context &lt;em&gt;c&lt;/em&gt; given above, the conditional** probability of &lt;em&gt;the&lt;/em&gt; — &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;the&lt;/strong&gt;|&lt;em&gt;c&lt;/em&gt;) — is much lower than, for instance, &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;house&lt;/strong&gt;|&lt;em&gt;c&lt;/em&gt;), even though the &lt;strong&gt;unconditional&lt;/strong&gt; probability &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;the&lt;/strong&gt;) is larger than that of any other word.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;512&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-cd3d68fc.CZlWP48u_Z1FzBIe.webp&quot; srcset=&quot;&quot;&gt;
Markov Chains — Joxemai4, CC BY-SA 3.0 &amp;#x3C;&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0&quot;&gt;https://creativecommons.org/licenses/by-sa/3.0&lt;/a&gt;&gt;, via Wikimedia CommonsApart from the grammatical functions of words, semantics — the meanings of words — play an important role when estimating these probabilities. While, for instance, &lt;em&gt;dwarf&lt;/em&gt; is a noun just like &lt;em&gt;house&lt;/em&gt; or &lt;em&gt;tree&lt;/em&gt;, it is semantically less likely to appear after the adjective &lt;em&gt;big&lt;/em&gt;; while &lt;em&gt;big dwarf&lt;/em&gt; is perfectly valid syntactically, it is an oxymoron and therefore unlikely (but not impossible) to occur. Therefore, &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;tree&lt;/strong&gt;|&lt;strong&gt;big&lt;/strong&gt;) is larger than &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;dwarf&lt;/strong&gt;|&lt;strong&gt;big&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;By counting word sequences in a text data set — the training data — , these probabilities can be estimated. However, there will always be (new) words that do not occur in the training data which combine letters in previously unseen, but valid sequences. There also is an infinite number of valid sentences; regardless of how many texts a model has processed, words will always be arranged in ways that have never been seen before. Frequency-based methods conceptually suffer from the “&lt;a href=&quot;https://plato.stanford.edu/entries/induction-problem/&quot;&gt;problem of induction&lt;/a&gt;”: what was written in the past can at best approximate what will be written in the future. Taking that uncertainty into account has been the difficult part of language modeling.&lt;/p&gt;
&lt;h2 id=&quot;enigmatic-language&quot;&gt;Enigmatic Language&lt;/h2&gt;
&lt;p&gt;During World War 2, three decades after Markov’s experiments, mathematicians from both sides ran a race to encrypt their radio messages. With the help of statistical knowledge about language (plus some blunders from the other side), the famous team around British mathematician Alan Turing at Bletchley Park eventually managed to decipher the messages encrypted with the Enigma machine used by the German military.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;763&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-2f68a964.BFsFbNva_Z18WXt5.webp&quot; srcset=&quot;&quot;&gt;
The Enigma encryption machine — Museo della Scienza e della Tecnologia “Leonardo da Vinci”, CC BY-SA 4.0 &amp;#x3C;&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0&quot;&gt;https://creativecommons.org/licenses/by-sa/4.0&lt;/a&gt;&gt;, via Wikimedia CommonsMotivated by the success during the war, information theory and cryptography coined the mental model of language modeling. As a former PhD student of the famous information scientist Claude Shannon, Warren Weaver proposed to apply statistical methods to translate texts from one language into another.&lt;/p&gt;
&lt;p&gt;The basic idea was: let’s look at a text in another language (Russian) as if it was an encrypted (English) text. We could then use the methods used for decryption to translate it from Russian into English. Probably needless to say that this did not work very well. The immense productivity of language does not really align with the way encryption algorithms work.&lt;/p&gt;
&lt;h2 id=&quot;distributional-semantics&quot;&gt;Distributional Semantics&lt;/h2&gt;
&lt;p&gt;From a linguistics perspective, the likelihood of a word occurring in a particular position in a sentence depends on two dimensions: syntax and semantics. For the former, human language tends to develop grammatical rules. Formalizing the grammar of a language by these rules was a focus for computational linguists for a long time, but never fully succeeded because there are many exceptions to these rules. Additionally, they are subject to change over time, and are not always followed even by native speakers of a language.&lt;/p&gt;
&lt;p&gt;Modeling semantics, on the other hand, is essential for modeling not only syntactically valid, but also meaningful sentences. This poses other challenges than grammatical rules. There are identical words that have multiple meanings (homonyms, e.g. &lt;em&gt;bank&lt;/em&gt;), there are different words that have (almost) identical meanings (synonyms, e.g. &lt;em&gt;freedom&lt;/em&gt; and &lt;em&gt;liberty&lt;/em&gt;), and there is a very broad spectrum in between. The nuanced meaning of a word can differ per culture, dialect, and even individual speaker.&lt;/p&gt;
&lt;p&gt;The British linguist John Rupert Firth noted in 1957 that “a word is characterized by the company it keeps”. This insight has opened a beautiful door towards statistically modeling the semantics of a word. If two words appear in similar contexts frequently, it implies that their meaning is related. Note that there are many types of relatedness, including similarity, oppositions, as well as the syntactical function.&lt;/p&gt;
&lt;p&gt;Distributional semantics and the Markov assumption have since melted into a powerful armory in language modeling by the use of n*-grams, windows in a text whereby &lt;em&gt;n&lt;/em&gt; stands for the window size. For instance, three words form a tri-gram (or 3-gram). Like so many techniques for language processing, this can be applied on various levels again, including characters and words.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/N-gram_language_model&quot;&gt;&lt;em&gt;n&lt;/em&gt;-gram models&lt;/a&gt; of varying values for &lt;em&gt;n&lt;/em&gt; have proven to be robust for estimating frequency-based language models without explicitly taking syntactic rules into account. In applications such as machine translation or speech recognition, such models have been combined with a translation model or an acoustic model respectively. They used to form the basis of the state-of-the-art algorithms in these and other sub-fields of Natural Language Processing for a long time.&lt;/p&gt;
&lt;h2 id=&quot;embedding-words&quot;&gt;Embedding Words&lt;/h2&gt;
&lt;p&gt;The rise of artificial neural networks has brought its own methods to implement the distributional semantics hypothesis. &lt;a href=&quot;https://github.com/tmikolov/word2vec&quot;&gt;Word2Vec&lt;/a&gt; (2013), &lt;a href=&quot;https://nlp.stanford.edu/projects/glove/&quot;&gt;Glove&lt;/a&gt; (2014), &lt;a href=&quot;https://fasttext.cc/&quot;&gt;FastText&lt;/a&gt; (2016) and more generate vector representations for each word based on context windows around the word. These algorithms do not directly rely on frequencies, but their parameters are optimized so that the resulting representations of two words end up close in the vector space if they tend to occur in similar contexts. These vector representations are called word embeddings.&lt;/p&gt;
&lt;p&gt;Word embeddings do not only represent the meanings of words, the vector space into which they are embedded also allows arithmetic operations in the semantic space. A notorious example: when you take the vector for &lt;em&gt;king&lt;/em&gt;, then subtract the vector for &lt;em&gt;man&lt;/em&gt;, and add the vector for &lt;em&gt;woman&lt;/em&gt;, you come out close to the vector for &lt;em&gt;queen&lt;/em&gt;. Interestingly, these embeddings tend to encode both semantics and syntactical functions — reflecting the linguistic insight that the boundary between syntax and semantics is often affluent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-aa3f1bb3.zonGYRj8_Z1NpnxV.webp&quot; srcset=&quot;&quot;&gt;
Distributional Word Representations — Singerep, CC BY-SA 4.0 &amp;#x3C;&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0&quot;&gt;https://creativecommons.org/licenses/by-sa/4.0&lt;/a&gt;&gt;, via Wikimedia CommonsGiven those representations of individual words, the next level in language modeling is thus to represent sequences of words — phrases, sentences, or entire documents. The simplest approach is to concatenate or average all the word vectors of a sentence, and use it as input to any machine learning algorithm.&lt;/p&gt;
&lt;p&gt;Recurrent neural networks (RNNs) have been more successful by combining a neural network’s state after processing one word with the embeddings for the following word. After iterating over an entire sentence, the network output yields a vector representation, including linguistic phenomena like negation and references between words.&lt;/p&gt;
&lt;p&gt;RNNs, however, face two major disadvantages: important contextual information can be located at a far distance in a text, and the recursive nature of an RNN prevents parallel computation. LSTM and GRU gates have extended RNNs, but only mitigated the first issue.&lt;/p&gt;
&lt;p&gt;In 2017, the architecture that enables current models was proposed: &lt;em&gt;Transformers&lt;/em&gt;. Dedicated *attention matrices *(already &lt;a href=&quot;https://arxiv.org/abs/1409.0473&quot;&gt;proposed in 2014&lt;/a&gt;) learn which parts in an input sequence are important, instead of paying attention to a predefined context window. That allows a language model to, for instance, interpret the meaning of the ambiguous word &lt;em&gt;bank&lt;/em&gt; by paying attention to occurrences of words like *river — *or perhaps &lt;em&gt;rob&lt;/em&gt; and *money *— anywhere in a text. That mechanism enables Transformer models to take very large contexts into account, while the optimization of the model parameters can be parallelized efficiently.&lt;/p&gt;
&lt;p&gt;There are different techniques for the optimization of these parameters. The famous &lt;a href=&quot;https://aclanthology.org/N19-1423/&quot;&gt;BERT&lt;/a&gt;-family of models is optimized&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to fill random gaps in the sentences of the training data (masked language modeling), and&lt;/li&gt;
&lt;li&gt;to decide whether a particular sentence follows another one (next sentence prediction).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These techniques are especially effective for generating vector-based, numeric representations of words and texts that can be used for NLP tasks like, for instance, document classification.&lt;/p&gt;
&lt;p&gt;Generative models like GPT on the other hand go back to where Andrej Markov started: they are optimized to predict the next word in a sequence. On top of that, the &lt;a href=&quot;https://proceedings.neurips.cc/paper_files/paper/2022/hash/f978c8f3b5f399cae464e85f72e28503-Abstract-Conference.html&quot;&gt;RLHF (&lt;em&gt;Reinforcement Learning from Human Feedback&lt;/em&gt;)&lt;/a&gt; technique has enabled the model to learn very effectively from human “AI Trainers”, resulting in the impressive conversational skills that ChatGPT has shown.&lt;/p&gt;
&lt;p&gt;The combination of more effective and scalable training techniques and the immense number of parameters enable such models to produce texts in a specific language. They are fed virtually the entire internet, therewith learning almost all human languages. Even programming languages come as an (intentional) extra, enabling GPT-based models to function as programming assistants.&lt;/p&gt;
&lt;h2 id=&quot;modeling-language-the-next-100-years&quot;&gt;Modeling Language: The Next 100 Years&lt;/h2&gt;
&lt;p&gt;Looking back into the history of language modeling illustrates that Artificial Intelligence has not suddenly emerged in the recent past. The current generation of models builds on a rich past of active research in the fields of computational linguistics, natural language processing, information theory, and related fields; to reiterate some milestones: the &lt;a href=&quot;https://proceedings.neurips.cc/paper_files/paper/2022/hash/f978c8f3b5f399cae464e85f72e28503-Abstract-Conference.html&quot;&gt;RLHF method from 2019&lt;/a&gt; fine-tunes models based on the &lt;a href=&quot;https://papers.nips.cc/paper_files/paper/2017/hash/3f5ee243547dee91fbd053c1c4a845aa-Abstract.html&quot;&gt;Transformers neural network architecture from 2017&lt;/a&gt;. Transformer-based models have improved upon the word embeddings as introduced by &lt;a href=&quot;https://papers.nips.cc/paper_files/paper/2013/hash/9aa42b31882ec039965f3c4923ce901b-Abstract.html&quot;&gt;Word2Vec (2013)&lt;/a&gt;. Linguistic and stochastic theory has laid the basis for such algorithms.&lt;/p&gt;
&lt;p&gt;The race has now shifted into the arena of engineering and productizing, as in making language models smaller and faster and embedding them into useful applications. Significant progress on the quality side is nowhere to be seen currently. As an &lt;a href=&quot;https://www.semianalysis.com/p/google-we-have-no-moat-and-neither&quot;&gt;internal Google document&lt;/a&gt; stated recently, none of the big companies like OpenAI, Microsoft, Google or Facebook seem to have a model or strategy that could outcompete the others. More efficient, often free, and qualitatively competitive models appear on a weekly basis.&lt;/p&gt;
&lt;p&gt;On the other hand, language models can generate incredibly fluent language, but are intransparent and inaccurate &lt;a href=&quot;https://www.newyorker.com/tech/annals-of-technology/chatgpt-is-a-blurry-jpeg-of-the-web&quot;&gt;by definition&lt;/a&gt;. These properties make them credible actors in conversations with humans, while posing difficulties on applications like search and coding assistance.&lt;/p&gt;
&lt;p&gt;Debates about imminent singularity in which Artificial Intelligence spontaneously starts improving itself live in the realm of fiction rather than science. Such mystifications can take both utopian and dystopian angles, but rely on beliefs, lacking specific evidence. Apocalypses have been predicted many times with respect to Artificial Intelligence as well as other technologies. Grand stories about the faith of humanity absorb a lot of attention, but tend to reduce and over-simplify complex matters.&lt;/p&gt;
&lt;p&gt;Technology, however, is only one factor — predictions about the future of our society, let alone humanity, are at best naive if they ignore political, economical, and societal factors. For a productive discussion that takes realistic risks and potentials of new technologies into account, experts from all these fields need to join forces.&lt;/p&gt;</description><pubDate>Thu, 01 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;ChatGPT has become the symbol for a new wave of Artificial Intelligence. New models with even stronger conversational skills are released on a weekly basis, and the world discusses about their impact on humanity. There are utopian and dystopian fantasies, as well as concrete potentials and risks. A view of the history of language modeling helps to understand the present and the future.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-7a4401d7.BU5-v53y_Z1Yf5uV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@brett_jordan?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Brett Jordan&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When Andrej Markov sat down with Alexander Pushkin’s poetic book &lt;em&gt;Eugene Onegin&lt;/em&gt; in 1913, he was not planning to distract himself from his work as a mathematician. Instead, he went through the verses and counted letters, resulting in the study “An Example of Statistical Investigation of the Text &lt;em&gt;Eugene Onegin&lt;/em&gt; Concerning the Connection of Samples in Chains”, &lt;a href=&quot;https://www.cambridge.org/core/journals/science-in-context/article/abs/an-example-of-statistical-investigation-of-the-text-eugene-onegin-concerning-the-connection-of-samples-in-chains/EA1E005FA0BC4522399A4E9DA0304862&quot;&gt;translated into English as late as 2006&lt;/a&gt;. The famous mathematician was not so much fascinated by the poetry, but by the distribution of consonants and vowels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;405&quot; height=&quot;599&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-ffedec5e.7v742PVF_ZV8yce.webp&quot; srcset=&quot;&quot;&gt;
Andrej Markov — By Unknown author — Converted into JPEG format from [1], Public Domain, &lt;a href=&quot;https://commons.wikimedia.org/w/index.php?curid=448609&quot;&gt;https://commons.wikimedia.org/w/index.php?curid=448609&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;causes-and-conditions&quot;&gt;Causes and Conditions&lt;/h2&gt;
&lt;p&gt;Markov demonstrated that the likelihood of a letter being a vowel or a consonant can be approximated from its preceding letters. Based on these findings, he developed a probabilistic model for causal sequences, today known as Markov chain. The so-called Markov assumption holds for language on various levels beyond characters, including words. Look at the following sentence stub:&lt;/p&gt;
&lt;p&gt;This is a big &amp;#x3C;?&gt;As readers, we cannot say which word should replace the &lt;em&gt;&amp;#x3C;?&gt;&lt;/em&gt;, but based on the preceding words, we know it is likely a noun (e.g. &lt;em&gt;house&lt;/em&gt; or &lt;em&gt;tree&lt;/em&gt;) or another adjective (e.g. *beautiful *or &lt;em&gt;green&lt;/em&gt;) and most certainly not a determiner (e.g. *the *or &lt;em&gt;a&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Conditional probability plays an important role: while &lt;em&gt;the&lt;/em&gt; is the most frequent word in English, it is very unlikely to occur in the position of the &lt;em&gt;&amp;#x3C;?&gt;&lt;/em&gt; above. Language modeling is about formalizing this kind of linguistic structures: what is the probability of a word &lt;em&gt;w&lt;/em&gt;, given a sequence of words &lt;em&gt;w1&lt;/em&gt;, &lt;em&gt;w2&lt;/em&gt;, … . The language model can be expressed mathematically as &lt;em&gt;P&lt;/em&gt;(&lt;em&gt;w&lt;/em&gt;|&lt;em&gt;c&lt;/em&gt;), where &lt;em&gt;c&lt;/em&gt; is short for the given word sequence*.* As English speakers, we know that for the context &lt;em&gt;c&lt;/em&gt; given above, the conditional** probability of &lt;em&gt;the&lt;/em&gt; — &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;the&lt;/strong&gt;|&lt;em&gt;c&lt;/em&gt;) — is much lower than, for instance, &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;house&lt;/strong&gt;|&lt;em&gt;c&lt;/em&gt;), even though the &lt;strong&gt;unconditional&lt;/strong&gt; probability &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;the&lt;/strong&gt;) is larger than that of any other word.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;512&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-cd3d68fc.CZlWP48u_Z1FzBIe.webp&quot; srcset=&quot;&quot;&gt;
Markov Chains — Joxemai4, CC BY-SA 3.0 &amp;#x3C;&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/3.0&quot;&gt;https://creativecommons.org/licenses/by-sa/3.0&lt;/a&gt;&gt;, via Wikimedia CommonsApart from the grammatical functions of words, semantics — the meanings of words — play an important role when estimating these probabilities. While, for instance, &lt;em&gt;dwarf&lt;/em&gt; is a noun just like &lt;em&gt;house&lt;/em&gt; or &lt;em&gt;tree&lt;/em&gt;, it is semantically less likely to appear after the adjective &lt;em&gt;big&lt;/em&gt;; while &lt;em&gt;big dwarf&lt;/em&gt; is perfectly valid syntactically, it is an oxymoron and therefore unlikely (but not impossible) to occur. Therefore, &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;tree&lt;/strong&gt;|&lt;strong&gt;big&lt;/strong&gt;) is larger than &lt;em&gt;P&lt;/em&gt;(&lt;strong&gt;dwarf&lt;/strong&gt;|&lt;strong&gt;big&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;By counting word sequences in a text data set — the training data — , these probabilities can be estimated. However, there will always be (new) words that do not occur in the training data which combine letters in previously unseen, but valid sequences. There also is an infinite number of valid sentences; regardless of how many texts a model has processed, words will always be arranged in ways that have never been seen before. Frequency-based methods conceptually suffer from the “&lt;a href=&quot;https://plato.stanford.edu/entries/induction-problem/&quot;&gt;problem of induction&lt;/a&gt;”: what was written in the past can at best approximate what will be written in the future. Taking that uncertainty into account has been the difficult part of language modeling.&lt;/p&gt;
&lt;h2 id=&quot;enigmatic-language&quot;&gt;Enigmatic Language&lt;/h2&gt;
&lt;p&gt;During World War 2, three decades after Markov’s experiments, mathematicians from both sides ran a race to encrypt their radio messages. With the help of statistical knowledge about language (plus some blunders from the other side), the famous team around British mathematician Alan Turing at Bletchley Park eventually managed to decipher the messages encrypted with the Enigma machine used by the German military.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;763&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-2f68a964.BFsFbNva_Z18WXt5.webp&quot; srcset=&quot;&quot;&gt;
The Enigma encryption machine — Museo della Scienza e della Tecnologia “Leonardo da Vinci”, CC BY-SA 4.0 &amp;#x3C;&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0&quot;&gt;https://creativecommons.org/licenses/by-sa/4.0&lt;/a&gt;&gt;, via Wikimedia CommonsMotivated by the success during the war, information theory and cryptography coined the mental model of language modeling. As a former PhD student of the famous information scientist Claude Shannon, Warren Weaver proposed to apply statistical methods to translate texts from one language into another.&lt;/p&gt;
&lt;p&gt;The basic idea was: let’s look at a text in another language (Russian) as if it was an encrypted (English) text. We could then use the methods used for decryption to translate it from Russian into English. Probably needless to say that this did not work very well. The immense productivity of language does not really align with the way encryption algorithms work.&lt;/p&gt;
&lt;h2 id=&quot;distributional-semantics&quot;&gt;Distributional Semantics&lt;/h2&gt;
&lt;p&gt;From a linguistics perspective, the likelihood of a word occurring in a particular position in a sentence depends on two dimensions: syntax and semantics. For the former, human language tends to develop grammatical rules. Formalizing the grammar of a language by these rules was a focus for computational linguists for a long time, but never fully succeeded because there are many exceptions to these rules. Additionally, they are subject to change over time, and are not always followed even by native speakers of a language.&lt;/p&gt;
&lt;p&gt;Modeling semantics, on the other hand, is essential for modeling not only syntactically valid, but also meaningful sentences. This poses other challenges than grammatical rules. There are identical words that have multiple meanings (homonyms, e.g. &lt;em&gt;bank&lt;/em&gt;), there are different words that have (almost) identical meanings (synonyms, e.g. &lt;em&gt;freedom&lt;/em&gt; and &lt;em&gt;liberty&lt;/em&gt;), and there is a very broad spectrum in between. The nuanced meaning of a word can differ per culture, dialect, and even individual speaker.&lt;/p&gt;
&lt;p&gt;The British linguist John Rupert Firth noted in 1957 that “a word is characterized by the company it keeps”. This insight has opened a beautiful door towards statistically modeling the semantics of a word. If two words appear in similar contexts frequently, it implies that their meaning is related. Note that there are many types of relatedness, including similarity, oppositions, as well as the syntactical function.&lt;/p&gt;
&lt;p&gt;Distributional semantics and the Markov assumption have since melted into a powerful armory in language modeling by the use of n*-grams, windows in a text whereby &lt;em&gt;n&lt;/em&gt; stands for the window size. For instance, three words form a tri-gram (or 3-gram). Like so many techniques for language processing, this can be applied on various levels again, including characters and words.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/N-gram_language_model&quot;&gt;&lt;em&gt;n&lt;/em&gt;-gram models&lt;/a&gt; of varying values for &lt;em&gt;n&lt;/em&gt; have proven to be robust for estimating frequency-based language models without explicitly taking syntactic rules into account. In applications such as machine translation or speech recognition, such models have been combined with a translation model or an acoustic model respectively. They used to form the basis of the state-of-the-art algorithms in these and other sub-fields of Natural Language Processing for a long time.&lt;/p&gt;
&lt;h2 id=&quot;embedding-words&quot;&gt;Embedding Words&lt;/h2&gt;
&lt;p&gt;The rise of artificial neural networks has brought its own methods to implement the distributional semantics hypothesis. &lt;a href=&quot;https://github.com/tmikolov/word2vec&quot;&gt;Word2Vec&lt;/a&gt; (2013), &lt;a href=&quot;https://nlp.stanford.edu/projects/glove/&quot;&gt;Glove&lt;/a&gt; (2014), &lt;a href=&quot;https://fasttext.cc/&quot;&gt;FastText&lt;/a&gt; (2016) and more generate vector representations for each word based on context windows around the word. These algorithms do not directly rely on frequencies, but their parameters are optimized so that the resulting representations of two words end up close in the vector space if they tend to occur in similar contexts. These vector representations are called word embeddings.&lt;/p&gt;
&lt;p&gt;Word embeddings do not only represent the meanings of words, the vector space into which they are embedded also allows arithmetic operations in the semantic space. A notorious example: when you take the vector for &lt;em&gt;king&lt;/em&gt;, then subtract the vector for &lt;em&gt;man&lt;/em&gt;, and add the vector for &lt;em&gt;woman&lt;/em&gt;, you come out close to the vector for &lt;em&gt;queen&lt;/em&gt;. Interestingly, these embeddings tend to encode both semantics and syntactical functions — reflecting the linguistic insight that the boundary between syntax and semantics is often affluent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Language Modeling: The First 100 Years&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-aa3f1bb3.zonGYRj8_Z1NpnxV.webp&quot; srcset=&quot;&quot;&gt;
Distributional Word Representations — Singerep, CC BY-SA 4.0 &amp;#x3C;&lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0&quot;&gt;https://creativecommons.org/licenses/by-sa/4.0&lt;/a&gt;&gt;, via Wikimedia CommonsGiven those representations of individual words, the next level in language modeling is thus to represent sequences of words — phrases, sentences, or entire documents. The simplest approach is to concatenate or average all the word vectors of a sentence, and use it as input to any machine learning algorithm.&lt;/p&gt;
&lt;p&gt;Recurrent neural networks (RNNs) have been more successful by combining a neural network’s state after processing one word with the embeddings for the following word. After iterating over an entire sentence, the network output yields a vector representation, including linguistic phenomena like negation and references between words.&lt;/p&gt;
&lt;p&gt;RNNs, however, face two major disadvantages: important contextual information can be located at a far distance in a text, and the recursive nature of an RNN prevents parallel computation. LSTM and GRU gates have extended RNNs, but only mitigated the first issue.&lt;/p&gt;
&lt;p&gt;In 2017, the architecture that enables current models was proposed: &lt;em&gt;Transformers&lt;/em&gt;. Dedicated *attention matrices *(already &lt;a href=&quot;https://arxiv.org/abs/1409.0473&quot;&gt;proposed in 2014&lt;/a&gt;) learn which parts in an input sequence are important, instead of paying attention to a predefined context window. That allows a language model to, for instance, interpret the meaning of the ambiguous word &lt;em&gt;bank&lt;/em&gt; by paying attention to occurrences of words like *river — *or perhaps &lt;em&gt;rob&lt;/em&gt; and *money *— anywhere in a text. That mechanism enables Transformer models to take very large contexts into account, while the optimization of the model parameters can be parallelized efficiently.&lt;/p&gt;
&lt;p&gt;There are different techniques for the optimization of these parameters. The famous &lt;a href=&quot;https://aclanthology.org/N19-1423/&quot;&gt;BERT&lt;/a&gt;-family of models is optimized&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to fill random gaps in the sentences of the training data (masked language modeling), and&lt;/li&gt;
&lt;li&gt;to decide whether a particular sentence follows another one (next sentence prediction).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These techniques are especially effective for generating vector-based, numeric representations of words and texts that can be used for NLP tasks like, for instance, document classification.&lt;/p&gt;
&lt;p&gt;Generative models like GPT on the other hand go back to where Andrej Markov started: they are optimized to predict the next word in a sequence. On top of that, the &lt;a href=&quot;https://proceedings.neurips.cc/paper_files/paper/2022/hash/f978c8f3b5f399cae464e85f72e28503-Abstract-Conference.html&quot;&gt;RLHF (&lt;em&gt;Reinforcement Learning from Human Feedback&lt;/em&gt;)&lt;/a&gt; technique has enabled the model to learn very effectively from human “AI Trainers”, resulting in the impressive conversational skills that ChatGPT has shown.&lt;/p&gt;
&lt;p&gt;The combination of more effective and scalable training techniques and the immense number of parameters enable such models to produce texts in a specific language. They are fed virtually the entire internet, therewith learning almost all human languages. Even programming languages come as an (intentional) extra, enabling GPT-based models to function as programming assistants.&lt;/p&gt;
&lt;h2 id=&quot;modeling-language-the-next-100-years&quot;&gt;Modeling Language: The Next 100 Years&lt;/h2&gt;
&lt;p&gt;Looking back into the history of language modeling illustrates that Artificial Intelligence has not suddenly emerged in the recent past. The current generation of models builds on a rich past of active research in the fields of computational linguistics, natural language processing, information theory, and related fields; to reiterate some milestones: the &lt;a href=&quot;https://proceedings.neurips.cc/paper_files/paper/2022/hash/f978c8f3b5f399cae464e85f72e28503-Abstract-Conference.html&quot;&gt;RLHF method from 2019&lt;/a&gt; fine-tunes models based on the &lt;a href=&quot;https://papers.nips.cc/paper_files/paper/2017/hash/3f5ee243547dee91fbd053c1c4a845aa-Abstract.html&quot;&gt;Transformers neural network architecture from 2017&lt;/a&gt;. Transformer-based models have improved upon the word embeddings as introduced by &lt;a href=&quot;https://papers.nips.cc/paper_files/paper/2013/hash/9aa42b31882ec039965f3c4923ce901b-Abstract.html&quot;&gt;Word2Vec (2013)&lt;/a&gt;. Linguistic and stochastic theory has laid the basis for such algorithms.&lt;/p&gt;
&lt;p&gt;The race has now shifted into the arena of engineering and productizing, as in making language models smaller and faster and embedding them into useful applications. Significant progress on the quality side is nowhere to be seen currently. As an &lt;a href=&quot;https://www.semianalysis.com/p/google-we-have-no-moat-and-neither&quot;&gt;internal Google document&lt;/a&gt; stated recently, none of the big companies like OpenAI, Microsoft, Google or Facebook seem to have a model or strategy that could outcompete the others. More efficient, often free, and qualitatively competitive models appear on a weekly basis.&lt;/p&gt;
&lt;p&gt;On the other hand, language models can generate incredibly fluent language, but are intransparent and inaccurate &lt;a href=&quot;https://www.newyorker.com/tech/annals-of-technology/chatgpt-is-a-blurry-jpeg-of-the-web&quot;&gt;by definition&lt;/a&gt;. These properties make them credible actors in conversations with humans, while posing difficulties on applications like search and coding assistance.&lt;/p&gt;
&lt;p&gt;Debates about imminent singularity in which Artificial Intelligence spontaneously starts improving itself live in the realm of fiction rather than science. Such mystifications can take both utopian and dystopian angles, but rely on beliefs, lacking specific evidence. Apocalypses have been predicted many times with respect to Artificial Intelligence as well as other technologies. Grand stories about the faith of humanity absorb a lot of attention, but tend to reduce and over-simplify complex matters.&lt;/p&gt;
&lt;p&gt;Technology, however, is only one factor — predictions about the future of our society, let alone humanity, are at best naive if they ignore political, economical, and societal factors. For a productive discussion that takes realistic risks and potentials of new technologies into account, experts from all these fields need to join forces.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/language-modeling-the-first-100-years-7a4401d7.BU5-v53y.jpg" medium="image"/><author>Carsten Schnober</author></item><item><title>Research Ethics and Authorship: The Technological Solution</title><link>https://blog2.esciencecenter.nl/posts/2023-05-25---research-ethics-and-authorship-the-technological-solution</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-05-25---research-ethics-and-authorship-the-technological-solution</guid><description>&lt;h2 id=&quot;dr-candace-makeda-moore-discusses-the-potential-for-distributed-version-control-as-a-tool-to-prevent-questionable-authorship-practices&quot;&gt;Dr. Candace Makeda Moore discusses the potential for distributed version control as a tool to prevent questionable authorship practices.&lt;/h2&gt;
&lt;p&gt;Recently I read a story in &lt;em&gt;Retraction Watc&lt;/em&gt; h about a service selling authorships on scientific papers in the peer review pipeline. On the same day a colleague physician mentioned that at our hospital, there were many cases where authorship was given in exchange for access to certain patients as potential research subjects. While the former type of blatant research fraud makes headlines, the latter barely raises an eyebrow. But giving authorship for research related favors or other ‘political’ reasons is neither a victimless minor crime, nor it is a problem without an easy, free and enforceable solution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VoR_1wmNArGuE5-2-b031096c.MZpTOGMG_230uL5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Annie Spratt on Unsplash&lt;/p&gt;
&lt;p&gt;Because I come from a medical background, I am most familiar with standards in this field, although problems related to authorship extend to most scientific fields.&lt;/p&gt;
&lt;p&gt;Perhaps at this point it’s worth pointing towards what authorship should actually be, using academic medicine as an example. The International Committee of Medical Journal Editors (ICJME) has &lt;a href=&quot;https://www.icmje.org/recommendations/browse/roles-and-responsibilities/defining-the-role-of-authors-and-contributors.html&quot;&gt;exemplary recommendations&lt;/a&gt;. The spirit of these recommendations is incredibly simple: authors should be involved in the design or analysis as well as the literal writing of research. There is some variation in different fields, and differences from place to place, and of course there can be exceptions with specific kinds of research papers e.g. papers for datasets and/or code. But we probably all agree that in least in principle, an author should be someone who does something significant for the work.&lt;/p&gt;
&lt;p&gt;Unfortunately, in day to day academic medical research it is typical to see people getting authorship on papers for all sorts of illegitimate reasons. Getting someone to sign off that researchers can access patients in a particular department, handing over an existing dataset, and many more tasks are necessary and integral parts of research. Such actions deserve praise, and there should be some system to reward such tasks in place, but as the medical-scientific community has defined authorship, they alone should not confer authorship.&lt;/p&gt;
&lt;p&gt;There are several major impediments to the adoption of proper research ethics in authorship in medicine. Some are simply related to inertia and the infamous conservatism of medicine. At many institutions authorship is given in customary ways including to any principal investigator (PI) who so much as attends meetings around research, because &lt;em&gt;‘that is the way it has been done’&lt;/em&gt;. And of course no one wants to get on the bad side of someone like a powerful principal investigator who can potentially ruin their career.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;912&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_D3cyAE6qwer8JuUl-6d02b345.Unl3AIQ7_Z1AvwIF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by National Cancer Institute on Unsplash&lt;/p&gt;
&lt;p&gt;This is, of course, another reason fraudulent authorships happen quite commonly. Politics. In some cases a principal investigator or high ranking researcher may provide very necessary help to a research group, e.g. without their signature nothing will move. But the truth is that there are well defined rules around authorship. One of the reasons for this is that authorship is so critical to advancing academic careers. Unfortunately, in academic medical centers, in practice what this means is that all levels of researchers enter into a treacherous political game where the bulk of authorships tend to accrue towards more established researchers who have more resources in the way of data access, workers and political capital. Such systems favor researchers who are privileged across almost every other axis of privilege possible.&lt;/p&gt;
&lt;p&gt;A medical researcher who lives in the real world of any large academic hospital may think ‘if I don’t give authorships to important professors who helped me, I’ll never get their help again, or worse, they will open some kind of problems for me’. They feel disempowered about what would be essentially telling the truth by demanding correct authorship lists, because it would be their word against the word of someone more powerful and established in many cases. But there is literally a free solution right beneath the nose of researchers.&lt;/p&gt;
&lt;p&gt;Every modern researcher uses a computer to accomplish aspects of their research from code scripts or programs for statistical analysis to word processing programs for writing articles. The solution to these messy problems of authorship is right at the fingertips, or only a mouse click away from anyone with a computer and internet connection. The solution is &lt;strong&gt;distributed version control systems&lt;/strong&gt; like Git or Mercurial.&lt;/p&gt;
&lt;p&gt;When a version controlled repository is created, there is a history of who wrote what and when. Unlike Google Docs or Word or any other of the more common tools for writing papers, version control makes it almost impossible to erase the trace of someone else’s work, or claim you or someone else made significant contributions in writing an article when it did not happen. Unless, of course, you are part of the extremely tiny group of researchers particularly talented with programming. But let’s face it, most people in medical research don’t want to use version control because they literally don’t even know how. They never learned it because it was never considered a critical skill for research.&lt;/p&gt;
&lt;p&gt;Some people do not find git or other version control languages and programs intuitive. For whatever reason this seems particularly true of physicians. However, even leaving issues of authorship aside, version control is an important skill in terms of modern computational research. The Netherlands eScience Center offers small hands on courses lasting one or a few days to train researchers in this area. An example of one upcoming such course can be viewed &lt;a href=&quot;https://www.esciencecenter.nl/event/good-practices-in-research-software-development/&quot;&gt;here&lt;/a&gt;. We have also contributed to high quality &lt;a href=&quot;https://swcarpentry.github.io/git-novice/index.html&quot;&gt;open source free lesson material&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While such programs are often used in practice with services like Github or Gitlab, they need not be. Technically, you could just create a repository and send files for it to other people. You can even sign commits with and/or make them traceable by servers. If you use git, you can use `git blame` to figure out who did something.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;It looks like I may be to blame for problems in this environment?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LmRkMTNvxvcbQ0k7NXoOZg-33c307bf.CGvKcF-W_1vqOOq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I may have some blame for problems in the environment in this program (output of `git blame` in a terminal)&lt;/p&gt;
&lt;p&gt;Obviously, using version control as the medium through which scientific papers are written favors the young and computer savvy. Would this cause the reverse problem to privileging the old and established? Hardly. Help for Git or any other open source version control system can be found across the internet. Lately, I often run across young students who have taught themselves to use a version control system without anyone asking them to for a class. The biggest barrier to learning version control systems for most high ranking researchers in medicine may be the psychological pain of having to ask people they consider their inferiors for help.&lt;/p&gt;
&lt;p&gt;In a world where people are questioning if what journals actually do is of any value when everyone could just publish on the internet and/or preprint servers, checking authorship should be a task that they are legitimately valued for. Such a task could be accomplished using free open source software like Git. The only thing necessary is a dash of skill in computing, or barring that, some learning.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;346&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dmCCMU2_nkATdc_qG9xJSQ-c26bf96e.c7qQYxpJ_Z1uUiST.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One approach to begin learning version control is simply searching and reading on the internet&lt;/p&gt;
&lt;p&gt;How am I sure this could work? Because we see these processes everywhere and all the time in terms of the code related to research. I myself am an author on several open code repositories related to medical signal processing and/or image processing, and if anyone were to question my role, I could just point to the lines of code I wrote as evidence that I did in fact do real work. Open source code provides a model for how papers could be made way more transparent in terms of authorship. In fact if researchers were to send their code repository and a related repositories which include study design documents, every aspect of authorship can be verified.&lt;/p&gt;
&lt;p&gt;Physicians are often called upon to lead research in medicine for obvious reasons, but have never really get trained (save a few who had post-graduate training in very select fields such as imaging informatics or public health) to do any computational research at all. A future where physicians and others working in medical research take a few days to learn the fundamental tools of computational research is a better future for everyone, because then we can efficiently combine clinical insight and large datasets. Whether to shield themselves from authorship problems, or go after the larger goal of better science, medical researchers should embrace version control.&lt;/p&gt;</description><pubDate>Thu, 25 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;dr-candace-makeda-moore-discusses-the-potential-for-distributed-version-control-as-a-tool-to-prevent-questionable-authorship-practices&quot;&gt;Dr. Candace Makeda Moore discusses the potential for distributed version control as a tool to prevent questionable authorship practices.&lt;/h2&gt;
&lt;p&gt;Recently I read a story in &lt;em&gt;Retraction Watc&lt;/em&gt; h about a service selling authorships on scientific papers in the peer review pipeline. On the same day a colleague physician mentioned that at our hospital, there were many cases where authorship was given in exchange for access to certain patients as potential research subjects. While the former type of blatant research fraud makes headlines, the latter barely raises an eyebrow. But giving authorship for research related favors or other ‘political’ reasons is neither a victimless minor crime, nor it is a problem without an easy, free and enforceable solution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VoR_1wmNArGuE5-2-b031096c.MZpTOGMG_230uL5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Annie Spratt on Unsplash&lt;/p&gt;
&lt;p&gt;Because I come from a medical background, I am most familiar with standards in this field, although problems related to authorship extend to most scientific fields.&lt;/p&gt;
&lt;p&gt;Perhaps at this point it’s worth pointing towards what authorship should actually be, using academic medicine as an example. The International Committee of Medical Journal Editors (ICJME) has &lt;a href=&quot;https://www.icmje.org/recommendations/browse/roles-and-responsibilities/defining-the-role-of-authors-and-contributors.html&quot;&gt;exemplary recommendations&lt;/a&gt;. The spirit of these recommendations is incredibly simple: authors should be involved in the design or analysis as well as the literal writing of research. There is some variation in different fields, and differences from place to place, and of course there can be exceptions with specific kinds of research papers e.g. papers for datasets and/or code. But we probably all agree that in least in principle, an author should be someone who does something significant for the work.&lt;/p&gt;
&lt;p&gt;Unfortunately, in day to day academic medical research it is typical to see people getting authorship on papers for all sorts of illegitimate reasons. Getting someone to sign off that researchers can access patients in a particular department, handing over an existing dataset, and many more tasks are necessary and integral parts of research. Such actions deserve praise, and there should be some system to reward such tasks in place, but as the medical-scientific community has defined authorship, they alone should not confer authorship.&lt;/p&gt;
&lt;p&gt;There are several major impediments to the adoption of proper research ethics in authorship in medicine. Some are simply related to inertia and the infamous conservatism of medicine. At many institutions authorship is given in customary ways including to any principal investigator (PI) who so much as attends meetings around research, because &lt;em&gt;‘that is the way it has been done’&lt;/em&gt;. And of course no one wants to get on the bad side of someone like a powerful principal investigator who can potentially ruin their career.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;912&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_D3cyAE6qwer8JuUl-6d02b345.Unl3AIQ7_Z1AvwIF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by National Cancer Institute on Unsplash&lt;/p&gt;
&lt;p&gt;This is, of course, another reason fraudulent authorships happen quite commonly. Politics. In some cases a principal investigator or high ranking researcher may provide very necessary help to a research group, e.g. without their signature nothing will move. But the truth is that there are well defined rules around authorship. One of the reasons for this is that authorship is so critical to advancing academic careers. Unfortunately, in academic medical centers, in practice what this means is that all levels of researchers enter into a treacherous political game where the bulk of authorships tend to accrue towards more established researchers who have more resources in the way of data access, workers and political capital. Such systems favor researchers who are privileged across almost every other axis of privilege possible.&lt;/p&gt;
&lt;p&gt;A medical researcher who lives in the real world of any large academic hospital may think ‘if I don’t give authorships to important professors who helped me, I’ll never get their help again, or worse, they will open some kind of problems for me’. They feel disempowered about what would be essentially telling the truth by demanding correct authorship lists, because it would be their word against the word of someone more powerful and established in many cases. But there is literally a free solution right beneath the nose of researchers.&lt;/p&gt;
&lt;p&gt;Every modern researcher uses a computer to accomplish aspects of their research from code scripts or programs for statistical analysis to word processing programs for writing articles. The solution to these messy problems of authorship is right at the fingertips, or only a mouse click away from anyone with a computer and internet connection. The solution is &lt;strong&gt;distributed version control systems&lt;/strong&gt; like Git or Mercurial.&lt;/p&gt;
&lt;p&gt;When a version controlled repository is created, there is a history of who wrote what and when. Unlike Google Docs or Word or any other of the more common tools for writing papers, version control makes it almost impossible to erase the trace of someone else’s work, or claim you or someone else made significant contributions in writing an article when it did not happen. Unless, of course, you are part of the extremely tiny group of researchers particularly talented with programming. But let’s face it, most people in medical research don’t want to use version control because they literally don’t even know how. They never learned it because it was never considered a critical skill for research.&lt;/p&gt;
&lt;p&gt;Some people do not find git or other version control languages and programs intuitive. For whatever reason this seems particularly true of physicians. However, even leaving issues of authorship aside, version control is an important skill in terms of modern computational research. The Netherlands eScience Center offers small hands on courses lasting one or a few days to train researchers in this area. An example of one upcoming such course can be viewed &lt;a href=&quot;https://www.esciencecenter.nl/event/good-practices-in-research-software-development/&quot;&gt;here&lt;/a&gt;. We have also contributed to high quality &lt;a href=&quot;https://swcarpentry.github.io/git-novice/index.html&quot;&gt;open source free lesson material&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While such programs are often used in practice with services like Github or Gitlab, they need not be. Technically, you could just create a repository and send files for it to other people. You can even sign commits with and/or make them traceable by servers. If you use git, you can use `git blame` to figure out who did something.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;It looks like I may be to blame for problems in this environment?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LmRkMTNvxvcbQ0k7NXoOZg-33c307bf.CGvKcF-W_1vqOOq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I may have some blame for problems in the environment in this program (output of `git blame` in a terminal)&lt;/p&gt;
&lt;p&gt;Obviously, using version control as the medium through which scientific papers are written favors the young and computer savvy. Would this cause the reverse problem to privileging the old and established? Hardly. Help for Git or any other open source version control system can be found across the internet. Lately, I often run across young students who have taught themselves to use a version control system without anyone asking them to for a class. The biggest barrier to learning version control systems for most high ranking researchers in medicine may be the psychological pain of having to ask people they consider their inferiors for help.&lt;/p&gt;
&lt;p&gt;In a world where people are questioning if what journals actually do is of any value when everyone could just publish on the internet and/or preprint servers, checking authorship should be a task that they are legitimately valued for. Such a task could be accomplished using free open source software like Git. The only thing necessary is a dash of skill in computing, or barring that, some learning.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;346&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dmCCMU2_nkATdc_qG9xJSQ-c26bf96e.c7qQYxpJ_Z1uUiST.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One approach to begin learning version control is simply searching and reading on the internet&lt;/p&gt;
&lt;p&gt;How am I sure this could work? Because we see these processes everywhere and all the time in terms of the code related to research. I myself am an author on several open code repositories related to medical signal processing and/or image processing, and if anyone were to question my role, I could just point to the lines of code I wrote as evidence that I did in fact do real work. Open source code provides a model for how papers could be made way more transparent in terms of authorship. In fact if researchers were to send their code repository and a related repositories which include study design documents, every aspect of authorship can be verified.&lt;/p&gt;
&lt;p&gt;Physicians are often called upon to lead research in medicine for obvious reasons, but have never really get trained (save a few who had post-graduate training in very select fields such as imaging informatics or public health) to do any computational research at all. A future where physicians and others working in medical research take a few days to learn the fundamental tools of computational research is a better future for everyone, because then we can efficiently combine clinical insight and large datasets. Whether to shield themselves from authorship problems, or go after the larger goal of better science, medical researchers should embrace version control.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_VoR_1wmNArGuE5-2-b031096c.MZpTOGMG.webp" medium="image"/><author>Candace Moore</author></item><item><title>Creating a Community by Integrating Expertise, Tools and Ideas</title><link>https://blog2.esciencecenter.nl/posts/2023-05-16---creating-a-community-by-integrating-expertise-tools-and-idea</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-05-16---creating-a-community-by-integrating-expertise-tools-and-idea</guid><description>&lt;p&gt;A personal reflection on the first NPLinker eScience workshop for Natural Product Discovery&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://vdhooftcompmet.github.io/&quot;&gt;Justin van der Hooft&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog post is written by Wageningen University &amp;#x26; Research Assistant Professor Justin van der Hooft who participates in the Netherlands eScience Center’s &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/open-escience-call-2021/&quot;&gt;&lt;em&gt;Open eScience Call 2021&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;. His project, “A community-supported workflow connecting microbial genes, and organisms to their molecular products”, aims to facilitate the finding of novel bioactive molecules from nature. It does so by enabling the integrated use of various omics data types.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-7878c100.C_Xe3aQK_2rb83I.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/pt-br/@vollkornapfel?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Adrian Lange&lt;/a&gt; on [Unsplash](&lt;a href=&quot;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&quot;&gt;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Text)&lt;/p&gt;
&lt;h3 id=&quot;motivation-for-the-workshop&quot;&gt;Motivation for the workshop**&lt;/h3&gt;
&lt;p&gt;Nature is still full of unknown chemistry with possible beneficial properties such as antibiotic ones. Genomics technologies measure the genetic content of organisms in which the blueprint of their chemical output is present. Metabolomics technologies generate tons of spectral data of actually produced molecules. However, the analysis of large-scale omics datasets is still very challenging, especially when several types need to be integrated. What can we predict from genomics? What can we understand from metabolomics? And how best to connect these two workflows when doing exploratory data analysis without drowning in the data?&lt;/p&gt;
&lt;h3 id=&quot;outline-of-the-workshop&quot;&gt;Outline of the workshop**&lt;/h3&gt;
&lt;p&gt;During this first workshop in a series of two, we aimed to bring together researchers interested in integrative omics analysis with various backgrounds in terms of their career stage, the technologies they are already familiar with, and the organisms they work on. Following a selection process, 30 participants were selected to come to Wageningen to learn about analyzing genomes and metabolomes, and to get an outlook towards the integration of the two. The aims of &lt;a href=&quot;https://www.wur.nl/en/research-results/chair-groups/plant-sciences/bioinformatics/teaching/nplinker_workshop.htm&quot;&gt;the workshop&lt;/a&gt; were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bring together Genome &amp;#x26; Metabolome Miners and learn the motivation and key characteristics of main genome and metabolome mining tools.&lt;/li&gt;
&lt;li&gt;Educate and train natural product researchers and other interested scientists in genome and metabolome mining.&lt;/li&gt;
&lt;li&gt;Establish together with the community what are the perceived main challenges in combining genomics and metabolomics, and the wishes for tools that address these.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To stimulate networking amongst the participants and instructors, several measures were put in place: extended coffee and tea breaks, the opportunity to present a poster, and group discussions in changing compositions. We are grateful for the financial support from the eScience Center to make the workshop affordable for participants from across the globe through a travel reimbursement scheme and to enable the presence of 4 international instructors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;474&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-799c43e7.COzav1a3_Z1qBUcH.webp&quot; srcset=&quot;&quot;&gt;
All 30 participants from across the globe together with the instructors in front of the &lt;a href=&quot;https://www.wur.nl/en/location/omnia-2.htm&quot;&gt;Omnia building&lt;/a&gt; at the &lt;a href=&quot;https://www.wur.nl/en.htm&quot;&gt;Wageningen University &amp;#x26; Research&lt;/a&gt; campus.&lt;/p&gt;
&lt;h3 id=&quot;key-insights&quot;&gt;&lt;strong&gt;Key insights&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;If there is one thing that became clear to me during the workshop, then it is this: multidisciplinary research requires open science and collaborative efforts to come to full fruition. During the workshop, one of the most heard perceived difficulties to do integrative omics analysis, is the (perceived) steep learning curve to get familiar with another type of omics data and the analysis workflow that comes with it. How to judge if this data is of good quality? How do you know if you used the right settings during the analysis? Hence, to do integrative omics analyses for natural product discovery, effective knowledge and skill transfer is needed. Here, having open access materials available is one part of the solution: researchers can use them to get familiar with the topic and the main things to consider for a successful project outcome, and teachers can use the materials to get inspired to teach this topic to students. We have also discussed the need for clear guidelines and instructions to run analysis software tools, and how the collaborative writing of documentation could be a solution to get to instructions that are clear(er) for a wide(r) audience. Finally, most tools, especially those relying on machine learning principles, perform best with increasing amounts of available data: all participants agreed that sharing is caring, and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-cunliang-geng/&quot;&gt;Cunliang Geng&lt;/a&gt;, research software engineer from the eScience Center, also provided an overview of how to make your data and software FAIR.&lt;/p&gt;
&lt;h3 id=&quot;practice-as-you-preach&quot;&gt;&lt;strong&gt;Practice as you preach&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;There was a lot of knowledge and skill exchange between participants themselves and participants and instructors that cannot be easily captured here. One tangible outcome for the workshop partipicants is the collaborative notes document that they collectively created and which is full of useful links and thoughts. Another tangible outcome of the workshop for the broader community is that the instructors all made as much as &lt;a href=&quot;https://doi.org/10.5281/zenodo.7801713&quot;&gt;possible the materials available under an open access licence&lt;/a&gt;! I hope that this initiative will help to further foster teaching the future generation of omics miners, to aid in setting up teaching materials for genome mining, metabolomics, and metabolome mining, and to promote discussions in between and bring together the fields of genome mining and metabolome mining.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;421&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-485272b5.DCcNMSI__2nFqGv.webp&quot; srcset=&quot;&quot;&gt;
With huge thanks to all the NPLinker eScience Workshop instructors who came from across the globe to Wageningen to teach the participants many facets of genome mining and metabolome mining.&lt;/p&gt;
&lt;h3 id=&quot;personal-reflection&quot;&gt;&lt;strong&gt;Personal reflection&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Overall, I am glad that the participants generally liked the workshop format and content and that they look back at a great week in Wageningen. In particular, I was curious if the group discussions after lunch were appreciated, and based on the evaluation this was a good move, as it prevented the “after-lunch dip”, yet at the same time the participants could share their insights and frustrations. Furthermore, many of them were happy to realize that there are more scientists out there that struggle with integrating omics analyses and that have complementary skills and background to them. This was exactly the idea behind the community building! Also, we got some valuable feedback when organizing future workshops as this one: it is challenging to find the right balance for everyone between theoretical lectures and hands-on tutorials. Big thanks go out to all involved for their active participation, including the secretarial support in Wageningen. Finally, I look forward to organizing the second NPLinker eScience workshop that will be fully focused on how integrating genome and metabolome analysis can boost natural product discovery. The final day of the current workshop already demonstrated the currently ongoing developments within the NPLinker eScience project as well as by research groups around the world.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-a4afe6a8.C78hIVMS_1Ibc7m.webp&quot; srcset=&quot;&quot;&gt;
Community building during the workshop dinner&lt;/p&gt;</description><pubDate>Tue, 16 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A personal reflection on the first NPLinker eScience workshop for Natural Product Discovery&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;https://vdhooftcompmet.github.io/&quot;&gt;Justin van der Hooft&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog post is written by Wageningen University &amp;#x26; Research Assistant Professor Justin van der Hooft who participates in the Netherlands eScience Center’s &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/open-escience-call-2021/&quot;&gt;&lt;em&gt;Open eScience Call 2021&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;. His project, “A community-supported workflow connecting microbial genes, and organisms to their molecular products”, aims to facilitate the finding of novel bioactive molecules from nature. It does so by enabling the integrated use of various omics data types.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-7878c100.C_Xe3aQK_2rb83I.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/pt-br/@vollkornapfel?utm_source=unsplash&amp;#x26;utm_medium=referral&amp;#x26;utm_content=creditCopyText&quot;&gt;Adrian Lange&lt;/a&gt; on [Unsplash](&lt;a href=&quot;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&quot;&gt;https://unsplash.com/photos/Wk902ZLaA7M?utm_source=unsplash&amp;#x26;amp;utm_medium=referral&amp;#x26;amp;utm_content=creditCopy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Text)&lt;/p&gt;
&lt;h3 id=&quot;motivation-for-the-workshop&quot;&gt;Motivation for the workshop**&lt;/h3&gt;
&lt;p&gt;Nature is still full of unknown chemistry with possible beneficial properties such as antibiotic ones. Genomics technologies measure the genetic content of organisms in which the blueprint of their chemical output is present. Metabolomics technologies generate tons of spectral data of actually produced molecules. However, the analysis of large-scale omics datasets is still very challenging, especially when several types need to be integrated. What can we predict from genomics? What can we understand from metabolomics? And how best to connect these two workflows when doing exploratory data analysis without drowning in the data?&lt;/p&gt;
&lt;h3 id=&quot;outline-of-the-workshop&quot;&gt;Outline of the workshop**&lt;/h3&gt;
&lt;p&gt;During this first workshop in a series of two, we aimed to bring together researchers interested in integrative omics analysis with various backgrounds in terms of their career stage, the technologies they are already familiar with, and the organisms they work on. Following a selection process, 30 participants were selected to come to Wageningen to learn about analyzing genomes and metabolomes, and to get an outlook towards the integration of the two. The aims of &lt;a href=&quot;https://www.wur.nl/en/research-results/chair-groups/plant-sciences/bioinformatics/teaching/nplinker_workshop.htm&quot;&gt;the workshop&lt;/a&gt; were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bring together Genome &amp;#x26; Metabolome Miners and learn the motivation and key characteristics of main genome and metabolome mining tools.&lt;/li&gt;
&lt;li&gt;Educate and train natural product researchers and other interested scientists in genome and metabolome mining.&lt;/li&gt;
&lt;li&gt;Establish together with the community what are the perceived main challenges in combining genomics and metabolomics, and the wishes for tools that address these.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To stimulate networking amongst the participants and instructors, several measures were put in place: extended coffee and tea breaks, the opportunity to present a poster, and group discussions in changing compositions. We are grateful for the financial support from the eScience Center to make the workshop affordable for participants from across the globe through a travel reimbursement scheme and to enable the presence of 4 international instructors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;474&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-799c43e7.COzav1a3_Z1qBUcH.webp&quot; srcset=&quot;&quot;&gt;
All 30 participants from across the globe together with the instructors in front of the &lt;a href=&quot;https://www.wur.nl/en/location/omnia-2.htm&quot;&gt;Omnia building&lt;/a&gt; at the &lt;a href=&quot;https://www.wur.nl/en.htm&quot;&gt;Wageningen University &amp;#x26; Research&lt;/a&gt; campus.&lt;/p&gt;
&lt;h3 id=&quot;key-insights&quot;&gt;&lt;strong&gt;Key insights&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;If there is one thing that became clear to me during the workshop, then it is this: multidisciplinary research requires open science and collaborative efforts to come to full fruition. During the workshop, one of the most heard perceived difficulties to do integrative omics analysis, is the (perceived) steep learning curve to get familiar with another type of omics data and the analysis workflow that comes with it. How to judge if this data is of good quality? How do you know if you used the right settings during the analysis? Hence, to do integrative omics analyses for natural product discovery, effective knowledge and skill transfer is needed. Here, having open access materials available is one part of the solution: researchers can use them to get familiar with the topic and the main things to consider for a successful project outcome, and teachers can use the materials to get inspired to teach this topic to students. We have also discussed the need for clear guidelines and instructions to run analysis software tools, and how the collaborative writing of documentation could be a solution to get to instructions that are clear(er) for a wide(r) audience. Finally, most tools, especially those relying on machine learning principles, perform best with increasing amounts of available data: all participants agreed that sharing is caring, and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-cunliang-geng/&quot;&gt;Cunliang Geng&lt;/a&gt;, research software engineer from the eScience Center, also provided an overview of how to make your data and software FAIR.&lt;/p&gt;
&lt;h3 id=&quot;practice-as-you-preach&quot;&gt;&lt;strong&gt;Practice as you preach&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;There was a lot of knowledge and skill exchange between participants themselves and participants and instructors that cannot be easily captured here. One tangible outcome for the workshop partipicants is the collaborative notes document that they collectively created and which is full of useful links and thoughts. Another tangible outcome of the workshop for the broader community is that the instructors all made as much as &lt;a href=&quot;https://doi.org/10.5281/zenodo.7801713&quot;&gt;possible the materials available under an open access licence&lt;/a&gt;! I hope that this initiative will help to further foster teaching the future generation of omics miners, to aid in setting up teaching materials for genome mining, metabolomics, and metabolome mining, and to promote discussions in between and bring together the fields of genome mining and metabolome mining.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;421&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-485272b5.DCcNMSI__2nFqGv.webp&quot; srcset=&quot;&quot;&gt;
With huge thanks to all the NPLinker eScience Workshop instructors who came from across the globe to Wageningen to teach the participants many facets of genome mining and metabolome mining.&lt;/p&gt;
&lt;h3 id=&quot;personal-reflection&quot;&gt;&lt;strong&gt;Personal reflection&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Overall, I am glad that the participants generally liked the workshop format and content and that they look back at a great week in Wageningen. In particular, I was curious if the group discussions after lunch were appreciated, and based on the evaluation this was a good move, as it prevented the “after-lunch dip”, yet at the same time the participants could share their insights and frustrations. Furthermore, many of them were happy to realize that there are more scientists out there that struggle with integrating omics analyses and that have complementary skills and background to them. This was exactly the idea behind the community building! Also, we got some valuable feedback when organizing future workshops as this one: it is challenging to find the right balance for everyone between theoretical lectures and hands-on tutorials. Big thanks go out to all involved for their active participation, including the secretarial support in Wageningen. Finally, I look forward to organizing the second NPLinker eScience workshop that will be fully focused on how integrating genome and metabolome analysis can boost natural product discovery. The final day of the current workshop already demonstrated the currently ongoing developments within the NPLinker eScience project as well as by research groups around the world.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Creating a Community by Integrating Expertise, Tools and Ideas&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-a4afe6a8.C78hIVMS_1Ibc7m.webp&quot; srcset=&quot;&quot;&gt;
Community building during the workshop dinner&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/creating-a-community-by-integrating-expe-7878c100.C_Xe3aQK.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Molecular Simulations using Machine Learning, Part 3</title><link>https://blog2.esciencecenter.nl/posts/2023-05-04---molecular-simulations-using-machine-learning-part-3</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-05-04---molecular-simulations-using-machine-learning-part-3</guid><description>&lt;p&gt;24&lt;/p&gt;
&lt;p&gt;In the first part of this series we looked at the physics of simulating molecules, and went from quantum mechanics to something that is more efficient to solve, namely density functional theory and molecular dynamics. These both required the introduction of an unknown potential. In the second part we looked at designing a machine learning model tailored to approximating this potential.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-202fe83c.z9dqxaIK_Z1mJNuo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@dkoi?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;D koi&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this final part we will discuss what goes into training this model, in particular how to obtain the training data. And we will conclude with some caveats.&lt;/p&gt;
&lt;p&gt;It’s possible to read this without having read the previous parts, but I would recommend at least reading &lt;a href=&quot;https://blog2.esciencecenter.nl/molecular-simulations-using-machine-learning-part-2-1d647acd242c&quot;&gt;part 2&lt;/a&gt;, and &lt;a href=&quot;https://medium.com/escience-center/molecular-simulations-using-machine-learning-part-1-e8624a82f680&quot;&gt;part 1&lt;/a&gt; only if you’re interested in the physical background.&lt;/p&gt;
&lt;p&gt;I hope that these considerations will also be useful for anyone thinking of applying machine learning to their own field, even if it is not related to molecular simulations.&lt;/p&gt;
&lt;h2 id=&quot;how-to-obtain-the-training-data&quot;&gt;How to obtain the training data&lt;/h2&gt;
&lt;p&gt;To be able to train the model, we need lots of examples of nuclei positions and the corresponding interatomic potential. To see how we can obtain this, we have to go back to the figure summarizing the first part:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;553&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-b6950ebc.D9WZcrba_sTNER.webp&quot; srcset=&quot;&quot;&gt;
Remember we decoupled the electrons from the nuclei, the electrons being described by Density Functional Theory (DFT), and the nuclei by molecular dynamics (MD). For MD we needed an interatomic potential, which captures the effect the electrons have on the nuclei. But since we do have a way to compute the electron density, namely through DFT, the obvious solution is to use DFT to compute the interatomic potential that we then use in MD, this is called ab-initio Molecular Dynamics (aiMD).&lt;/p&gt;
&lt;p&gt;The downside as we discussed was that this is very slow, which was the reason to try using machine learning in the first place. We can still use it to compute the training data though! Note that this does assume that we can do DFT, i.e. that we know a density functional that is accurate for the system we want to study.&lt;/p&gt;
&lt;p&gt;After designing the machine learning model to be specifically tailored for this application, and thus very data-efficient, the hope is that with relatively little training data we can train a model, that we can then use to do much more and bigger simulations. The hope then is that once the model is trained, it will be as accurate as ab-initio molecular dynamics, but as fast as molecular dynamics using a simple potential, combining the best of both worlds.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;481&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-9c38fba1.TbqBRSxe_7QUBX.webp&quot; srcset=&quot;&quot;&gt;
When it comes to generating the training data, there are several tradeoffs that must be carefully considered. We will discuss several of them here.&lt;/p&gt;
&lt;h3 id=&quot;system-size&quot;&gt;system size&lt;/h3&gt;
&lt;p&gt;Since computing the potential for the training data is so expensive, ideally we want to be able to train the model on a small system, and once trained use it to simulate a larger system.&lt;/p&gt;
&lt;p&gt;To be more concrete, we could take for example 10 water molecules, and for 10.000 different configurations of these 10 nuclei use DFT to compute the interatomic potential. That gives us the input and output pairs on which we can train the model. Once it is trained, we can use this model to simulate millions of water molecules for many more steps.&lt;/p&gt;
&lt;p&gt;The tradeoff here is that if we make the training system &lt;em&gt;too&lt;/em&gt; small, it will never be able to learn enough about the larger system. In an extreme case, if we take as the training system a single water molecule, the model wouldn’t see any interactions between two molecules during training.&lt;/p&gt;
&lt;p&gt;So we must choose a training system that is small enough to be able to use DFT to generate the data, yet large enough that it captures all the interactions present in the much larger system the model will be used on once trained. What this is will depend heavily on the system considered, and will be a matter of trial and error combined with chemical intuition.&lt;/p&gt;
&lt;h3 id=&quot;system-configurations&quot;&gt;system configurations&lt;/h3&gt;
&lt;p&gt;Another question is how to choose the inputs, i.e. the nuclei positions on which we compute the interatomic potential. One option is to just do an aiMD simulation and use all of the steps as inputs. This has the advantage that, with the exception of the initial steps, all of the configurations were obtained by following an MD trajectory, so we can expect that they are typical and we are likely to run into similar (but bigger) configurations once we use the model. So it’s very beneficial if the model performs well on these configurations.&lt;/p&gt;
&lt;p&gt;Ideally we want all the inputs to be independent from each other, this maximizes the added value of each additional sample. So the other extreme is to sample the nuclear configurations at random, then they will indeed be completely independent from each other. However, configurations sampled at random are likely not to be physically realistic. So instead of samples being irrelevant because they are very similar to other samples, now they are irrelevant because they won’t be encountered when the trained model is used.&lt;/p&gt;
&lt;p&gt;So there is a tradeoff between diversity and representativeness. A good tradeoff between these two extremes can be made by first doing an MD simulation using not DFT but a faster, less accurate potential. These configurations will be much more representative than random ones, but much faster to obtain than using aiMD the whole time. Then, to minimise the correlation between steps, we only take every say 100th step. Finally, because the potential we used was less accurate, only for the steps we picked do we recompute the potential using DFT.&lt;/p&gt;
&lt;p&gt;In addition it helps to run the training simulation at a higher temperature than the system you want to use the model on. This makes the system explore more of the configuration space, and prevents the model running into unknown territory during its use.¹&lt;/p&gt;
&lt;h3 id=&quot;quality-vs-quantity&quot;&gt;Quality vs quantity&lt;/h3&gt;
&lt;p&gt;A final consideration is between the quality and the quantity of the data. Since we compute everything from DFT, and within DFT there are several choices that can make it more accurate and slower or vice versa, choices must be made here too. There need to be enough samples for the model to be able to generalise to configurations it hasn’t seen, but it also needs to be done within our computational budget.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;271&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-aba560be._jrghfx3_2dWoe5.webp&quot; srcset=&quot;&quot;&gt;
Tradeoffs to be navigated in generating training data.&lt;/p&gt;
&lt;h3 id=&quot;many-more-considerations&quot;&gt;Many more considerations&lt;/h3&gt;
&lt;p&gt;There are tons of other things to consider, here I have focussed on some of the issues that are most particular to this application, rather than providing a full overview of deep learning. I have also focussed on the more conceptually interesting questions. There are lots of details though that can have a significant effect on the final performance, such as what activation function is used, or what optimizer². It is best to start with an existing method if possible, and if improvement is necessary experiment with varying these details and seeing what effect they have on the final performance.&lt;/p&gt;
&lt;h3 id=&quot;getting-started&quot;&gt;Getting started&lt;/h3&gt;
&lt;p&gt;If you are a chemist and want to try this for yourself, a good place to start might be &lt;a href=&quot;https://github.com/mir-group/nequip&quot;&gt;nequip&lt;/a&gt;, &lt;a href=&quot;https://github.com/mir-group/allegro&quot;&gt;allegro&lt;/a&gt; or &lt;a href=&quot;https://github.com/deepmodeling/deepmd-kit&quot;&gt;DeepMD-Kit&lt;/a&gt;, these work smoothly with the molecular dynamics code LAMMPS. &lt;a href=&quot;https://github.com/atomistic-machine-learning/schnetpack&quot;&gt;SchNetPack&lt;/a&gt; works with python’s atomic simulation environment. They all implement different models, so it is a matter of figuring out which model works best for your use case and with which software you are most familiar.&lt;/p&gt;
&lt;p&gt;Unfortunately due to personal circumstances I didn’t have time to do any experiments myself, so I can’t recommend any particular one.&lt;/p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;
&lt;p&gt;After all this theory let’s look at one example from the &lt;a href=&quot;https://arxiv.org/abs/2204.05249&quot;&gt;Allegro&lt;/a&gt; paper. In the figure below a small system of Li_3 PO_4 is shown, consisting of 192 atoms. The training data the authors made consisted of 11,000 configurations selected randomly from a 50,000 step ab-initio MD simulation. To get a sense of the time scales involved, the time step in this case was 2 femtoseconds, where a femtosecond is 1/10⁶ nanoseconds. The model was trained on this for machine learning standards very small dataset.&lt;/p&gt;
&lt;p&gt;It then was able to simulate a much bigger version of the same system, consisting of 421,824 atoms, at a speed of half a nanosecond per day on a single GPU, or even 50,331,648 atoms at half that speed using 128 GPUs.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;238&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-566c4cd9.DeeuxsRw_Zq5sxm.webp&quot; srcset=&quot;&quot;&gt;
Example taken from &lt;a href=&quot;https://arxiv.org/abs/2204.05249&quot;&gt;https://arxiv.org/abs/2204.05249&lt;/a&gt;.Assessing the accuracy of the model is a much more subtle question than say for a model that classifies whether an image is a cat or a dog. I will just explain one plot from the paper that is just one measure of the accuracy. What is shown on the right in the figure above is the radial distribution function. This is a measure of the probability of finding a pair of atoms at a given distance. The peaks in the graph reveal characteristic structures or patterns in the material, such as the most common atomic bonds or the preferred spacing between certain atom types The figure shows that Allegro managed to come very close to the accurate but slow ab-initio Molecular Dynamics, at least in this measure.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Deep learning can be used to model the potential energy between molecules, needed in molecular dynamics simulations. This is a rapidly evolving field, with multiple libraries under active development, and regular papers with further improvements in methodology. It is exciting to follow these developments, and the larger scale simulations they will enable. For a relatively recent review, see &lt;a href=&quot;https://www.nature.com/articles/s41563-020-0777-6&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;footnotes&quot;&gt;footnotes&lt;/h3&gt;
&lt;p&gt;1: Thanks to Simon Batzner for correspondence on these issues.&lt;/p&gt;
&lt;p&gt;2: In fact as I write this blog, the &lt;a href=&quot;https://arxiv.org/abs/2303.08169&quot;&gt;latest innovation&lt;/a&gt; is exactly a new optimizer.&lt;/p&gt;</description><pubDate>Thu, 04 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;24&lt;/p&gt;
&lt;p&gt;In the first part of this series we looked at the physics of simulating molecules, and went from quantum mechanics to something that is more efficient to solve, namely density functional theory and molecular dynamics. These both required the introduction of an unknown potential. In the second part we looked at designing a machine learning model tailored to approximating this potential.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-202fe83c.z9dqxaIK_Z1mJNuo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@dkoi?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;D koi&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this final part we will discuss what goes into training this model, in particular how to obtain the training data. And we will conclude with some caveats.&lt;/p&gt;
&lt;p&gt;It’s possible to read this without having read the previous parts, but I would recommend at least reading &lt;a href=&quot;https://blog2.esciencecenter.nl/molecular-simulations-using-machine-learning-part-2-1d647acd242c&quot;&gt;part 2&lt;/a&gt;, and &lt;a href=&quot;https://medium.com/escience-center/molecular-simulations-using-machine-learning-part-1-e8624a82f680&quot;&gt;part 1&lt;/a&gt; only if you’re interested in the physical background.&lt;/p&gt;
&lt;p&gt;I hope that these considerations will also be useful for anyone thinking of applying machine learning to their own field, even if it is not related to molecular simulations.&lt;/p&gt;
&lt;h2 id=&quot;how-to-obtain-the-training-data&quot;&gt;How to obtain the training data&lt;/h2&gt;
&lt;p&gt;To be able to train the model, we need lots of examples of nuclei positions and the corresponding interatomic potential. To see how we can obtain this, we have to go back to the figure summarizing the first part:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;553&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-b6950ebc.D9WZcrba_sTNER.webp&quot; srcset=&quot;&quot;&gt;
Remember we decoupled the electrons from the nuclei, the electrons being described by Density Functional Theory (DFT), and the nuclei by molecular dynamics (MD). For MD we needed an interatomic potential, which captures the effect the electrons have on the nuclei. But since we do have a way to compute the electron density, namely through DFT, the obvious solution is to use DFT to compute the interatomic potential that we then use in MD, this is called ab-initio Molecular Dynamics (aiMD).&lt;/p&gt;
&lt;p&gt;The downside as we discussed was that this is very slow, which was the reason to try using machine learning in the first place. We can still use it to compute the training data though! Note that this does assume that we can do DFT, i.e. that we know a density functional that is accurate for the system we want to study.&lt;/p&gt;
&lt;p&gt;After designing the machine learning model to be specifically tailored for this application, and thus very data-efficient, the hope is that with relatively little training data we can train a model, that we can then use to do much more and bigger simulations. The hope then is that once the model is trained, it will be as accurate as ab-initio molecular dynamics, but as fast as molecular dynamics using a simple potential, combining the best of both worlds.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;481&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-9c38fba1.TbqBRSxe_7QUBX.webp&quot; srcset=&quot;&quot;&gt;
When it comes to generating the training data, there are several tradeoffs that must be carefully considered. We will discuss several of them here.&lt;/p&gt;
&lt;h3 id=&quot;system-size&quot;&gt;system size&lt;/h3&gt;
&lt;p&gt;Since computing the potential for the training data is so expensive, ideally we want to be able to train the model on a small system, and once trained use it to simulate a larger system.&lt;/p&gt;
&lt;p&gt;To be more concrete, we could take for example 10 water molecules, and for 10.000 different configurations of these 10 nuclei use DFT to compute the interatomic potential. That gives us the input and output pairs on which we can train the model. Once it is trained, we can use this model to simulate millions of water molecules for many more steps.&lt;/p&gt;
&lt;p&gt;The tradeoff here is that if we make the training system &lt;em&gt;too&lt;/em&gt; small, it will never be able to learn enough about the larger system. In an extreme case, if we take as the training system a single water molecule, the model wouldn’t see any interactions between two molecules during training.&lt;/p&gt;
&lt;p&gt;So we must choose a training system that is small enough to be able to use DFT to generate the data, yet large enough that it captures all the interactions present in the much larger system the model will be used on once trained. What this is will depend heavily on the system considered, and will be a matter of trial and error combined with chemical intuition.&lt;/p&gt;
&lt;h3 id=&quot;system-configurations&quot;&gt;system configurations&lt;/h3&gt;
&lt;p&gt;Another question is how to choose the inputs, i.e. the nuclei positions on which we compute the interatomic potential. One option is to just do an aiMD simulation and use all of the steps as inputs. This has the advantage that, with the exception of the initial steps, all of the configurations were obtained by following an MD trajectory, so we can expect that they are typical and we are likely to run into similar (but bigger) configurations once we use the model. So it’s very beneficial if the model performs well on these configurations.&lt;/p&gt;
&lt;p&gt;Ideally we want all the inputs to be independent from each other, this maximizes the added value of each additional sample. So the other extreme is to sample the nuclear configurations at random, then they will indeed be completely independent from each other. However, configurations sampled at random are likely not to be physically realistic. So instead of samples being irrelevant because they are very similar to other samples, now they are irrelevant because they won’t be encountered when the trained model is used.&lt;/p&gt;
&lt;p&gt;So there is a tradeoff between diversity and representativeness. A good tradeoff between these two extremes can be made by first doing an MD simulation using not DFT but a faster, less accurate potential. These configurations will be much more representative than random ones, but much faster to obtain than using aiMD the whole time. Then, to minimise the correlation between steps, we only take every say 100th step. Finally, because the potential we used was less accurate, only for the steps we picked do we recompute the potential using DFT.&lt;/p&gt;
&lt;p&gt;In addition it helps to run the training simulation at a higher temperature than the system you want to use the model on. This makes the system explore more of the configuration space, and prevents the model running into unknown territory during its use.¹&lt;/p&gt;
&lt;h3 id=&quot;quality-vs-quantity&quot;&gt;Quality vs quantity&lt;/h3&gt;
&lt;p&gt;A final consideration is between the quality and the quantity of the data. Since we compute everything from DFT, and within DFT there are several choices that can make it more accurate and slower or vice versa, choices must be made here too. There need to be enough samples for the model to be able to generalise to configurations it hasn’t seen, but it also needs to be done within our computational budget.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;271&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-aba560be._jrghfx3_2dWoe5.webp&quot; srcset=&quot;&quot;&gt;
Tradeoffs to be navigated in generating training data.&lt;/p&gt;
&lt;h3 id=&quot;many-more-considerations&quot;&gt;Many more considerations&lt;/h3&gt;
&lt;p&gt;There are tons of other things to consider, here I have focussed on some of the issues that are most particular to this application, rather than providing a full overview of deep learning. I have also focussed on the more conceptually interesting questions. There are lots of details though that can have a significant effect on the final performance, such as what activation function is used, or what optimizer². It is best to start with an existing method if possible, and if improvement is necessary experiment with varying these details and seeing what effect they have on the final performance.&lt;/p&gt;
&lt;h3 id=&quot;getting-started&quot;&gt;Getting started&lt;/h3&gt;
&lt;p&gt;If you are a chemist and want to try this for yourself, a good place to start might be &lt;a href=&quot;https://github.com/mir-group/nequip&quot;&gt;nequip&lt;/a&gt;, &lt;a href=&quot;https://github.com/mir-group/allegro&quot;&gt;allegro&lt;/a&gt; or &lt;a href=&quot;https://github.com/deepmodeling/deepmd-kit&quot;&gt;DeepMD-Kit&lt;/a&gt;, these work smoothly with the molecular dynamics code LAMMPS. &lt;a href=&quot;https://github.com/atomistic-machine-learning/schnetpack&quot;&gt;SchNetPack&lt;/a&gt; works with python’s atomic simulation environment. They all implement different models, so it is a matter of figuring out which model works best for your use case and with which software you are most familiar.&lt;/p&gt;
&lt;p&gt;Unfortunately due to personal circumstances I didn’t have time to do any experiments myself, so I can’t recommend any particular one.&lt;/p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;
&lt;p&gt;After all this theory let’s look at one example from the &lt;a href=&quot;https://arxiv.org/abs/2204.05249&quot;&gt;Allegro&lt;/a&gt; paper. In the figure below a small system of Li_3 PO_4 is shown, consisting of 192 atoms. The training data the authors made consisted of 11,000 configurations selected randomly from a 50,000 step ab-initio MD simulation. To get a sense of the time scales involved, the time step in this case was 2 femtoseconds, where a femtosecond is 1/10⁶ nanoseconds. The model was trained on this for machine learning standards very small dataset.&lt;/p&gt;
&lt;p&gt;It then was able to simulate a much bigger version of the same system, consisting of 421,824 atoms, at a speed of half a nanosecond per day on a single GPU, or even 50,331,648 atoms at half that speed using 128 GPUs.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Molecular Simulations using Machine Learning, Part 3&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;238&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-566c4cd9.DeeuxsRw_Zq5sxm.webp&quot; srcset=&quot;&quot;&gt;
Example taken from &lt;a href=&quot;https://arxiv.org/abs/2204.05249&quot;&gt;https://arxiv.org/abs/2204.05249&lt;/a&gt;.Assessing the accuracy of the model is a much more subtle question than say for a model that classifies whether an image is a cat or a dog. I will just explain one plot from the paper that is just one measure of the accuracy. What is shown on the right in the figure above is the radial distribution function. This is a measure of the probability of finding a pair of atoms at a given distance. The peaks in the graph reveal characteristic structures or patterns in the material, such as the most common atomic bonds or the preferred spacing between certain atom types The figure shows that Allegro managed to come very close to the accurate but slow ab-initio Molecular Dynamics, at least in this measure.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Deep learning can be used to model the potential energy between molecules, needed in molecular dynamics simulations. This is a rapidly evolving field, with multiple libraries under active development, and regular papers with further improvements in methodology. It is exciting to follow these developments, and the larger scale simulations they will enable. For a relatively recent review, see &lt;a href=&quot;https://www.nature.com/articles/s41563-020-0777-6&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;footnotes&quot;&gt;footnotes&lt;/h3&gt;
&lt;p&gt;1: Thanks to Simon Batzner for correspondence on these issues.&lt;/p&gt;
&lt;p&gt;2: In fact as I write this blog, the &lt;a href=&quot;https://arxiv.org/abs/2303.08169&quot;&gt;latest innovation&lt;/a&gt; is exactly a new optimizer.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/molecular-simulations-using-machine-lear-202fe83c.z9dqxaIK.jpg" medium="image"/><author>Aron</author></item><item><title>Researchers are not born engineers — why are they expected to know how to code?</title><link>https://blog2.esciencecenter.nl/posts/2023-04-20---researchers-are-not-born-engineers-why-are-they-expected-to-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-04-20---researchers-are-not-born-engineers-why-are-they-expected-to-</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;I refuse to be too hard on my past self. It’s understandable that researchers, who juggle multiple projects and deadlines, do not have the time, energy or resources to become coding experts. But research is increasingly reliant on technology, so it’s important that researchers have access to the support and education they need to develop and use high-quality code. Learning good coding practices (or having access to those who know them) not only improves the reproducibility and reliability of research, but it adds to the fun of coding, saves time and prevents future headaches.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Researchers are not born engineers — why are they expected to know how to code?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/researchers-are-not-born-engineers-why-a-448a811f.E8sRjKrA_Z29SuPn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@clemhlrdt?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Clément Hélardot&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I sat in on a &lt;a href=&quot;https://www.esciencecenter.nl/event/best-practices-in-research-software-development-coderefinery-3/&quot;&gt;course on good coding practices&lt;/a&gt; at the eScience Center two years ago, I first realized why my own code had been bad: I did not know about good practices. I learned how to properly &lt;a href=&quot;https://coderefinery.github.io/git-collaborative/&quot;&gt;collaborate on projects via GitHub&lt;/a&gt;, which was eye-opening. The fact that you could use branches to work together on solutions to different problems was completely novel to me. The fact that you could write tests to make sure you would realize if part of your code failed was mind-blowing. Also, making my code modular, so that scripts would not contain upwards of 2000 lines, made the entire project so much easier to read and understand. Writing proper help functions was something I used to feel was not that important, because I never wanted anyone to look at my code. Now, documentation is something I strongly believe in.&lt;/p&gt;
&lt;p&gt;I am currently farther away from being a researcher in my daily job than ever, but in this job I did write an R package, together with my eScience Center colleague &lt;a href=&quot;https://github.com/bvreede&quot;&gt;Barbara Vreede&lt;/a&gt;. Barbara is an amazing research software engineer who guided me through the process. The package is called &lt;a href=&quot;https://github.com/esciencecenter-digital-skills/training-infrastructure&quot;&gt;traininginfrastructure*&lt;/a&gt;and creates all necessary communication documents and folders for the workshops we run at the eScience Center. I’m very happy to say the package works and is used by my colleagues. It saves engineers who teach time on repetitive administrative duties and prevents mistakes in creating communication (no more copy-pasting emails with typos).&lt;/p&gt;
&lt;p&gt;By no means did I become a perfect research software engineer. But I realized how much I had learned when recently, a researcher contacted me to ask if she could use the same analysis that I had used during a project for my PhD. I reluctantly gave her access to the old private GitHub repo with my project’s scripts and had to dig some non-version controlled other scripts out of my email inbox. Being confronted with that code was sobering. One day, I may try to clean it up so that they are usable for more researchers in the future. But it made one wider point very clear to me: my work at the eScience Center really serves a purpose. It can bring people like me, researchers who write scripts that work, but that they hate, to write code that they can be proud of and freely share with those that may need it. It can save all of us time and effort. And what I learned here really did not take that much time: a 1-week course and some quality guidance in building a fairly simple R package.&lt;/p&gt;
&lt;p&gt;Some of those who collaborate with us on projects at the eScience Center find it difficult to accept our engineers’ wishes that they use the same practices we do in research software projects. I now understand that using good practices is the only way to build quality tools for research. If you are ever in a situation where someone forces you, you may end up gratefully learning about (and putting into practice!) version control, collaborative software engineering, testing, and documentation. It can be painful in the beginning, but it will make your and others’ life so much easier in the future, and your software a worthy research output on your CV.&lt;/p&gt;
&lt;p&gt;If you want to learn how to write quality code for research, check out &lt;a href=&quot;https://www.esciencecenter.nl/events/?f=workshops&quot;&gt;our free workshops&lt;/a&gt;! You can also apply for &lt;a href=&quot;https://www.esciencecenter.nl/calls-for-proposals/&quot;&gt;our calls&lt;/a&gt;, or sign up to our &lt;a href=&quot;http://eepurl.com/dtjzwP&quot;&gt;newsletter&lt;/a&gt; to stay tuned.&lt;/p&gt;</description><pubDate>Thu, 20 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;I refuse to be too hard on my past self. It’s understandable that researchers, who juggle multiple projects and deadlines, do not have the time, energy or resources to become coding experts. But research is increasingly reliant on technology, so it’s important that researchers have access to the support and education they need to develop and use high-quality code. Learning good coding practices (or having access to those who know them) not only improves the reproducibility and reliability of research, but it adds to the fun of coding, saves time and prevents future headaches.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Researchers are not born engineers — why are they expected to know how to code?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/researchers-are-not-born-engineers-why-a-448a811f.E8sRjKrA_Z29SuPn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@clemhlrdt?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Clément Hélardot&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When I sat in on a &lt;a href=&quot;https://www.esciencecenter.nl/event/best-practices-in-research-software-development-coderefinery-3/&quot;&gt;course on good coding practices&lt;/a&gt; at the eScience Center two years ago, I first realized why my own code had been bad: I did not know about good practices. I learned how to properly &lt;a href=&quot;https://coderefinery.github.io/git-collaborative/&quot;&gt;collaborate on projects via GitHub&lt;/a&gt;, which was eye-opening. The fact that you could use branches to work together on solutions to different problems was completely novel to me. The fact that you could write tests to make sure you would realize if part of your code failed was mind-blowing. Also, making my code modular, so that scripts would not contain upwards of 2000 lines, made the entire project so much easier to read and understand. Writing proper help functions was something I used to feel was not that important, because I never wanted anyone to look at my code. Now, documentation is something I strongly believe in.&lt;/p&gt;
&lt;p&gt;I am currently farther away from being a researcher in my daily job than ever, but in this job I did write an R package, together with my eScience Center colleague &lt;a href=&quot;https://github.com/bvreede&quot;&gt;Barbara Vreede&lt;/a&gt;. Barbara is an amazing research software engineer who guided me through the process. The package is called &lt;a href=&quot;https://github.com/esciencecenter-digital-skills/training-infrastructure&quot;&gt;traininginfrastructure*&lt;/a&gt;and creates all necessary communication documents and folders for the workshops we run at the eScience Center. I’m very happy to say the package works and is used by my colleagues. It saves engineers who teach time on repetitive administrative duties and prevents mistakes in creating communication (no more copy-pasting emails with typos).&lt;/p&gt;
&lt;p&gt;By no means did I become a perfect research software engineer. But I realized how much I had learned when recently, a researcher contacted me to ask if she could use the same analysis that I had used during a project for my PhD. I reluctantly gave her access to the old private GitHub repo with my project’s scripts and had to dig some non-version controlled other scripts out of my email inbox. Being confronted with that code was sobering. One day, I may try to clean it up so that they are usable for more researchers in the future. But it made one wider point very clear to me: my work at the eScience Center really serves a purpose. It can bring people like me, researchers who write scripts that work, but that they hate, to write code that they can be proud of and freely share with those that may need it. It can save all of us time and effort. And what I learned here really did not take that much time: a 1-week course and some quality guidance in building a fairly simple R package.&lt;/p&gt;
&lt;p&gt;Some of those who collaborate with us on projects at the eScience Center find it difficult to accept our engineers’ wishes that they use the same practices we do in research software projects. I now understand that using good practices is the only way to build quality tools for research. If you are ever in a situation where someone forces you, you may end up gratefully learning about (and putting into practice!) version control, collaborative software engineering, testing, and documentation. It can be painful in the beginning, but it will make your and others’ life so much easier in the future, and your software a worthy research output on your CV.&lt;/p&gt;
&lt;p&gt;If you want to learn how to write quality code for research, check out &lt;a href=&quot;https://www.esciencecenter.nl/events/?f=workshops&quot;&gt;our free workshops&lt;/a&gt;! You can also apply for &lt;a href=&quot;https://www.esciencecenter.nl/calls-for-proposals/&quot;&gt;our calls&lt;/a&gt;, or sign up to our &lt;a href=&quot;http://eepurl.com/dtjzwP&quot;&gt;newsletter&lt;/a&gt; to stay tuned.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/researchers-are-not-born-engineers-why-a-448a811f.E8sRjKrA.jpg" medium="image"/><author>Lieke de Boer</author></item><item><title>Molecular Simulations using Machine Learning, Part 2</title><link>https://blog2.esciencecenter.nl/posts/2023-04-13---molecular-simulations-using-machine-learning-part-2</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-04-13---molecular-simulations-using-machine-learning-part-2</guid><description>&lt;p&gt;&lt;em&gt;In this post, I will walk through the process of designing a model used in molecular simulations, from essential to state of the art. This is the second part of a series on using machine learning for molecular simulations. It is relatively self-contained if you haven’t read&lt;/em&gt; &lt;a href=&quot;https://blog.esciencecenter.nl/molecular-simulations-using-machine-learning-part-1-e8624a82f680?sk=8c9902b39588261826ab77e3e24f8766&quot;&gt;&lt;em&gt;the first part&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;875&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_GVOnfCp1wScCos1_-b1c8ae9b.BJjMZttk_Z1wrR14.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by BoliviaInteligente on Unsplash&lt;/p&gt;
&lt;p&gt;We will design a model that approximates a potential used in molecular simulations. We will start from the simplest possible model, and reason our way step by step towards the essentials of the current state of the art models. This at the same time roughly follows the historical development of these models, although we will not attempt to be precise in this regard.&lt;/p&gt;
&lt;p&gt;The principles we use to arrive at a good model are quite general. Although they will lead to different models in different applications, I hope this can be helpful for scientists in different fields thinking about applying machine learning to their own field.&lt;/p&gt;
&lt;h3 id=&quot;quick-recap&quot;&gt;Quick recap&lt;/h3&gt;
&lt;p&gt;The figure below summarizes part 1 in a bit more detail. We saw how quantum mechanics was simplified into Density Functional Theory describing electrons, and Molecular Dynamics describing the atomic nuclei. The clouds in the figure indicate a-priori unknown ingredients that arose from these approximations: the density functional and the interatomic potential.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1131&quot; height=&quot;894&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zwvn0X4z6_mG4zyQ4acULw-036d0626.CR6qfiv9_5UqRY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We will focus on the interatomic potential: a single function depending on the positions of all the nuclei. The same principles that we use to derive a model for this also apply to the density functional, but the details will be different, because its inputs are different.&lt;/p&gt;
&lt;h2 id=&quot;simplest-machine-learning-model&quot;&gt;Simplest machine learning model&lt;/h2&gt;
&lt;p&gt;When designing a machine learning model, it is useful to start from the very basic question: what should go into it, and what should come out.&lt;/p&gt;
&lt;p&gt;Well, we want the model to compute a potential, which is a single number, depending on the coordinates of all nuclei. So if we have N nuclei in 3-dimensional space, the model should take 3N numbers and turn them into a single number.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;749&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jCcxDmDEo7BTHXhrdDLR_g-832dfe19.Dc0wIY9X_Z2dnAc6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The simplest machine learning model: a linear model.&lt;/p&gt;
&lt;p&gt;The simplest possible machine learning model that meets this requirement would be multiplication by a 1 by 3N matrix W: M(x) = W x. This would multiply every one of the 3N inputs with a weight, and sum them all up. These weights are the trainable parameters. These are initially set to random values, and updated during training by correcting the errors the model makes. That part will remain the same throughout.&lt;/p&gt;
&lt;p&gt;This model has many undesirable properties, the most problematic one being that it is way too simple. A more precise way of saying this is that it is linear. This means that if we multiply all of the inputs by 2, the output will be multiplied by 2 as well. Or if we add 3 to say input x₁, the output will be the original output plus 3 w₁, where w₁ is the corresponding weight. In reality of course the effect of this change of one coordinate on the potential depends in a complicated way on its relationships to the coordinates of other particles. This model will never be able to capture that, no matter how much data you throw at it.&lt;/p&gt;
&lt;h2 id=&quot;deep-learning&quot;&gt;Deep learning&lt;/h2&gt;
&lt;p&gt;Removing this restriction takes us from machine learning to deep learning. The simplest neural network is basically a sequence of the simpler models from above, intermingled with nonlinear functions called activation functions. (Without these, the end result would still be linear!)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;657&quot; height=&quot;491&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MNG8au1e0VGNe723I3Fv1A-338974de.DjMYcLzq_Z1SL8p9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The simplest deep learning model: a fully connected neural network.&lt;/p&gt;
&lt;p&gt;The simplest example of this class of models has one hidden layer: it takes the 3N inputs to say 100 numbers by a matrix multiplication, and applicaties an activation function to each one separately. Then through a second matrix multiplication it takes those to the one number we need as an output.&lt;/p&gt;
&lt;p&gt;There are many different activation functions, conceptually the only important thing is that they are nonlinear. A simple often used example is the ReLU, which is 0 if its input is negative, and otherwise just passes on the input unchanged.&lt;/p&gt;
&lt;p&gt;The effect of adding just one of these hidden layers is profound. In a sense, this immediately fixes the problem with the previous model. That is, this model can approximate anything now, given enough parameters. This statement is known as the &lt;em&gt;universal approximation theorem&lt;/em&gt;. However, that is quite a theoretical result. It doesn’t say how large the hidden layer should be, how much data is necessary, or even if it’s possible to find the right parameters through training at all, only that they exist.&lt;/p&gt;
&lt;p&gt;To address all of these other concerns, we need to specialise the model further to our particular application. In other words, we want our model to not only take into account just the &lt;em&gt;size&lt;/em&gt; of the in- and outputs, but also its &lt;em&gt;structure&lt;/em&gt;. As a first example, although the model above has the correct number of 3N inputs, it is not aware at all that actually these have the structure of N triplets of coordinates.&lt;/p&gt;
&lt;p&gt;To elaborate on this and make it more precise, we’ll look at the concept of equivariance. For a book and lectures on exploiting the structure of our data that is much more detailed, but also quite technical, see &lt;a href=&quot;https://geometricdeeplearning.com/&quot;&gt;https://geometricdeeplearning.com/&lt;/a&gt;, and &lt;a href=&quot;https://www.nature.com/articles/s42256-021-00418-8&quot;&gt;this paper&lt;/a&gt; for applications specifically to molecules.&lt;/p&gt;
&lt;h3 id=&quot;equivariance&quot;&gt;Equivariance&lt;/h3&gt;
&lt;p&gt;Equivariance means that if we &lt;em&gt;first&lt;/em&gt; transform the input and &lt;em&gt;then&lt;/em&gt; apply the model to it, we get the same result as when we &lt;em&gt;first&lt;/em&gt; apply the model, and &lt;em&gt;then&lt;/em&gt; apply a similar transformation to the output. It is a property that a model can have for some transformations but not for others. For example if this is true for a model M when the transformations are rotations, we say that M is rotation equivariant or equivariant with respect to rotations, illustrated in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;420&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ez5PyIJRW8XGHQdlBjxxkQ-a83a4fc2.CH-zISRo_1gF3wY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example of equivariance of a hypothetical model M that just detects edges. No matter if we first apply the model and then rotate the result, or first rotate the input and then apply the model, we end up with the same result.&lt;/p&gt;
&lt;p&gt;Note that the definition refers to a &lt;em&gt;similar&lt;/em&gt; transformation on the output, not necessarily exactly the same as we applied to the input. In fact, usually the output of the model will be of a different shape than the input, so we cannot even do the exact same transformation. The important part is that we know a-priori what the transformation on the output is, and it depends only on what transformation we did on the input.&lt;/p&gt;
&lt;p&gt;A special case of equivariance is &lt;em&gt;invariance&lt;/em&gt;, which is when this similar transformation is actually the identity. In other words, if we transform the input, the output will remain unchanged. For a simple example of this, if the hypothetical model in the image above were just a classifier saying whether the image is a cat or a dog, we’d expect it to be invariant: for both inputs on the left of the image, the outputs on the right should be “cat”.&lt;/p&gt;
&lt;p&gt;Requiring the model to be equivariant with respect to some transformation imposes some constraints on it, it decreases the freedom in the model, or the number of parameters. So as long as the equivariances we impose are also satisfied by the true solution we are trying to approximate with the model, it makes it more data efficient and easier to train. If we didn’t impose equivariance, the model could potentially have learned it from the data, but that would require more data, more time and more parameters. If we know this property beforehand, clearly it pays off to enforce it, preventing the model from the get go to make mistakes of this kind.&lt;/p&gt;
&lt;p&gt;There are many different transformations that the true interatomic potential must be equivariant to. We will discuss these one by one and use them to refine our model.&lt;/p&gt;
&lt;h3 id=&quot;permutations&quot;&gt;Permutations&lt;/h3&gt;
&lt;p&gt;In turning the positions of all nuclei into a 3N-dimensional input vector, we had to implicitly decide an order: which particle is the first particle, which is the second, etc. Clearly this is just a choice of labelling; if we pick a different order for the exact same configuration of particles, the potential shouldn’t change. So we want our model to be &lt;em&gt;invariant&lt;/em&gt; with respect to permutations.&lt;/p&gt;
&lt;p&gt;Currently it is not, it has no idea that the output should be the same, and so it would have to learn that by seeing lots of examples of identical configurations that are labelled differently, but with the same training label. Clearly this is a huge waste of time, and we want to avoid this.&lt;/p&gt;
&lt;p&gt;There are several common functions that do not depend on the order of their arguments, i.e. that are permutation invariant, such as the sum, or the mean, or the maximum. We will just take the sum, as it preserves more information than the maximum. So the very simplest permutation-invariant model would just take all of the nuclei’s positions and sum them. (Actually this would still leave us with 3 coordinates, so we’d need a 1 by 3 matrix at the end to turn it into a single number.)&lt;/p&gt;
&lt;p&gt;This is of course again much too simple, in fact even more so than what we started with. We can improve the situation while still taking permutations into account by having only the &lt;em&gt;last&lt;/em&gt; layer be invariant, and adding &lt;em&gt;equivariant&lt;/em&gt; layers in between.&lt;/p&gt;
&lt;p&gt;Any function that does exactly the same to every nucleus will be equivariant with respect to permutations: if we reorder the inputs, the outputs will be the same as the original, except that they are also reordered in exactly the same way. For this function we can use what we ended up with in the previous section: a fully connected neural network. So that takes a nucleus’s 3 coordinates, and does several matrix multiplications and activation functions on it to end up with a different amount of numbers for each atom, that we can choose.&lt;/p&gt;
&lt;p&gt;Note that if the intermediate layers were &lt;em&gt;not&lt;/em&gt; equivariant, there would be no way to guarantee invariance at the final layer. Furthermore, it also already makes the model more data efficient, as one training sample automatically teaches it about all the different orderings of that same sample.&lt;/p&gt;
&lt;p&gt;Another important consequence of this is that, unlike the fully connected level, we now have a model that works regardless of how many nuclei there are. This is great, because it will allow us to train the model on a small system, and then use it on a larger system.&lt;/p&gt;
&lt;h3 id=&quot;locality-graph-neural-networks&quot;&gt;Locality, graph neural networks&lt;/h3&gt;
&lt;p&gt;The above modification does impose permutation invariance, but it was still too restrictive. It treats all the nuclei independently, finally just summing “individual potentials” to obtain the total potential. This is not realistic, we expect the potential to depend also on the distance &lt;em&gt;between&lt;/em&gt; nuclei, something that this model cannot learn.&lt;/p&gt;
&lt;p&gt;We can relax this restriction and at the same time incorporate another physical prior by adding more structure to the input.&lt;/p&gt;
&lt;p&gt;The physical principle is locality: what happens at some point x only depends on things close to x. More concretely in this case, the Coulomb potential between two particles at a distance r decreases as 1/r. This means that the interaction between two nuclei that are very far from each other doesn’t have any significant contribution to the potential.&lt;/p&gt;
&lt;p&gt;So for nuclei closer to each other than some cutoff distance r_c, we want to take their interaction into account, and we can connect them by an edge. Those that are further away are not connected by an edge. This way we turn the original point cloud input into a graph.&lt;/p&gt;
&lt;p&gt;We then extend the operation that previously did the same to all nuclei, to allow it to depend on an atom’s neighbours as well. However, the number of neighbours will be different for different nuclei, and if we allow this to make the output shapes of each atom different things will quickly grow out of hand. So we need a way to combine the neighbours in such a way as to keep the shape independent of the number of neighbours. Furthermore we again have the issue of permutation invariance, now at a smaller local scale. The solution to both problems is the same: we sum over the features of the neighbours.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;692&quot; height=&quot;526&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6pHDwX0OUPtuHWqbD0vUJw-f0843c46.d1xFbZ-o_Z1ORWx7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Illustration of message passing in a graph neural network. An atom c receives “messages” from its neighbours n and updates its state using those. The neighbours at the same time do the same. Multiple steps of this allow the message to propagate further.&lt;/p&gt;
&lt;p&gt;This is another permutation equivariant operation, now on graph inputs. It is called message passing, because it can be thought of as all of an atom’s neighbours passing messages to the central atom, who adds them all up. Doing this multiple times for all nuclei increases the region to which an atom is sensitive, because in the second step it can indirectly receive messages from its neighbours’ neighbours.&lt;/p&gt;
&lt;p&gt;At the end we have to sum over all nuclei again to obtain something invariant to permutations. These types of models are called Graph Neural Networks (GNNs).&lt;/p&gt;
&lt;h3 id=&quot;spatial-invariances&quot;&gt;Spatial invariances&lt;/h3&gt;
&lt;p&gt;While permutation invariance was more about the way we describe the system, how we label the nuclei, the remaining ones are actual spatial transformations: translations, rotations and reflections.&lt;/p&gt;
&lt;p&gt;If we move (“translate”) all nuclei in the same direction by the same amount, the interatomic potential doesn’t change. That is, whether we perform an experiment in Amsterdam, or we perform the exact same experiment in New York, the outcome should be the same. And the same holds for rotations and reflections. (If there were any external influence like gravity this would be different, but that is insignificant at the atomic scale.)&lt;/p&gt;
&lt;p&gt;As the model is now, it doesn’t know any of this. Building this in to the model makes it a lot more data efficient. From just one training simulation it would learn automatically about all its translations, rotations and reflections.&lt;/p&gt;
&lt;p&gt;The simplest way to enforce this is to only give the model inputs that are themselves invariant to these transformations. Clearly, if the inputs are not affected, the output is also not affected.&lt;/p&gt;
&lt;p&gt;That means we cannot have an atom’s position as an input by itself, as clearly that is not invariant under any of the transformations. But since we now have a graph, we can focus on &lt;em&gt;pairs&lt;/em&gt; of nuclei, and take the difference of their positions as an input. That is already invariant with respect to translations: if we add the same vector to both positions, it will cancel out in the difference. It is not yet invariant with respect to rotations or reflections, but if we reduce it further to just the absolute value of the difference, it is.&lt;/p&gt;
&lt;p&gt;That does the job, but it is again quite restrictive. Note the parallel here with the permutations we discussed previously: the simplest is to make everything invariant from the start, but it will turn out to be unnecessarily restrictive.&lt;/p&gt;
&lt;p&gt;For an example of something that is missed in this approach, consider a central atom with two two of its neighbours. The vectors pointing from the central atom to those two neighbours make up a certain angle to each other. If you think about it, this angle is also invariant with respect to all of the transformations. And it might well be a useful feature that has an effect on the potential that we want the model to represent. But there is no way to reconstruct this angle just from the absolute value of the differences in positions. Had we not thrown away that much information so early on, we &lt;em&gt;would&lt;/em&gt; be able to recover this angle: it’s related to the inner product between the two vectors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;554&quot; height=&quot;437&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_a_4d0GaMmdDN6ZJ8s81Rqg-6d8dab71.BVg6UK_y_Z2daGhj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The angle φ is invariant to translations, rotations and reflections.&lt;/p&gt;
&lt;p&gt;We could of course add these angles to the input “by hand” and stick to imposing invariance from the start, and there are models that do this. But there are many more features that we are throwing away. A more systematic approach would again be to only impose invariance in the final layer, and keep the others equivariant.&lt;/p&gt;
&lt;h3 id=&quot;higher-representationsorbitals&quot;&gt;Higher representations/orbitals&lt;/h3&gt;
&lt;p&gt;It gets a bit more complicated though. The complication is that there are many ways that things can transform under rotations. Chemists know these as orbitals, physicists and mathematicians as different representations of the rotation group.&lt;/p&gt;
&lt;p&gt;I’ll give an idea that, while not mathematically rigorous, captures the intuition of what’s important for us here. Imagine we start with two vectors representing the positions of two nuclei, which are in what is called the L=1 representation or the p orbital; here, the vector remains unchanged when rotated along its own axis but changes its position when rotated in any other way.&lt;/p&gt;
&lt;p&gt;We can combine these two vectors by taking the length of their difference. As mentioned before, this is invariant, it is called the L=0 representation or the s orbital. It is a single number that doesn’t change under any rotation. We can also simply add them, then it remains a vector.&lt;/p&gt;
&lt;p&gt;The two vectors together define a plane, a two dimensional surface that they both lie in (assuming that they are not parallel). Or more concretely imagine one vector pointing out of the cockpit of an actual plane and one along one wing. The plane they define together would be the floor of the inside of the actual plane.&lt;/p&gt;
&lt;p&gt;Loosely speaking this is how the two vectors can be combined to a higher representation, this would be the L=2 representation or the d orbital. Note that this plane depends on both vectors: if we rotate along the wing of the plane, that vector doesn’t change, but the one pointing out the cockpit certainly does, and so does the floor of the plane.&lt;/p&gt;
&lt;p&gt;This pattern continues: every time we add a new vector into the mix, we can either lower the representation by one, keep it the same, or increase it by one. For example if we start with a plane and a vector, you can imagine projecting the vector into the plane, that gives us a new vector, lowering the representation by one.&lt;/p&gt;
&lt;p&gt;So, crucially, the more complex combinations can be reduced down to something that is invariant, as we require for the output of the model.&lt;/p&gt;
&lt;p&gt;If we are very precise in how a layer is allowed to combine its inputs to form its outputs (how it combines the orbitals/representations), we can have intermediate layers that are equivariant, and a final equivariant output. This will then not only automatically capture the angles we mentioned before, but also more complex structures.&lt;/p&gt;
&lt;p&gt;This again makes the model more data-efficient, without paying the price of oversimplifying the input and throwing away a lot of information.&lt;/p&gt;
&lt;p&gt;This is implemented in the &lt;a href=&quot;https://github.com/e3nn/e3nn&quot;&gt;e3nn&lt;/a&gt; library, and used for example in the molecular dynamics models &lt;a href=&quot;https://github.com/mir-group/nequip&quot;&gt;nequip&lt;/a&gt; and &lt;a href=&quot;https://github.com/mir-group/allegro&quot;&gt;allegro&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;By looking carefully at the structure of the problem, in particular how the true interatomic potential must transform under several transformations of its input, we have constructed a model that is very data efficient. The arguments to get here were very generic, and apply to any model that approximates an invariant function of particle positions.&lt;/p&gt;
&lt;p&gt;First we saw that we needed more than one layer in order to learn more than just linear functions. We used permutation invariance combined with locality to arrive at a graph neural network. On top of this we required invariance with respect to the spatial transformations of translations, rotations and reflections. This gives us what is called an E(3)-equivariant GNN (E(3) is the name for these transformations in 3-dimensional space).&lt;/p&gt;
&lt;p&gt;In the final part we will look at considerations that go into training this model.&lt;/p&gt;</description><pubDate>Thu, 13 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;In this post, I will walk through the process of designing a model used in molecular simulations, from essential to state of the art. This is the second part of a series on using machine learning for molecular simulations. It is relatively self-contained if you haven’t read&lt;/em&gt; &lt;a href=&quot;https://blog.esciencecenter.nl/molecular-simulations-using-machine-learning-part-1-e8624a82f680?sk=8c9902b39588261826ab77e3e24f8766&quot;&gt;&lt;em&gt;the first part&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;875&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_GVOnfCp1wScCos1_-b1c8ae9b.BJjMZttk_Z1wrR14.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by BoliviaInteligente on Unsplash&lt;/p&gt;
&lt;p&gt;We will design a model that approximates a potential used in molecular simulations. We will start from the simplest possible model, and reason our way step by step towards the essentials of the current state of the art models. This at the same time roughly follows the historical development of these models, although we will not attempt to be precise in this regard.&lt;/p&gt;
&lt;p&gt;The principles we use to arrive at a good model are quite general. Although they will lead to different models in different applications, I hope this can be helpful for scientists in different fields thinking about applying machine learning to their own field.&lt;/p&gt;
&lt;h3 id=&quot;quick-recap&quot;&gt;Quick recap&lt;/h3&gt;
&lt;p&gt;The figure below summarizes part 1 in a bit more detail. We saw how quantum mechanics was simplified into Density Functional Theory describing electrons, and Molecular Dynamics describing the atomic nuclei. The clouds in the figure indicate a-priori unknown ingredients that arose from these approximations: the density functional and the interatomic potential.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1131&quot; height=&quot;894&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zwvn0X4z6_mG4zyQ4acULw-036d0626.CR6qfiv9_5UqRY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We will focus on the interatomic potential: a single function depending on the positions of all the nuclei. The same principles that we use to derive a model for this also apply to the density functional, but the details will be different, because its inputs are different.&lt;/p&gt;
&lt;h2 id=&quot;simplest-machine-learning-model&quot;&gt;Simplest machine learning model&lt;/h2&gt;
&lt;p&gt;When designing a machine learning model, it is useful to start from the very basic question: what should go into it, and what should come out.&lt;/p&gt;
&lt;p&gt;Well, we want the model to compute a potential, which is a single number, depending on the coordinates of all nuclei. So if we have N nuclei in 3-dimensional space, the model should take 3N numbers and turn them into a single number.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;749&quot; height=&quot;424&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jCcxDmDEo7BTHXhrdDLR_g-832dfe19.Dc0wIY9X_Z2dnAc6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The simplest machine learning model: a linear model.&lt;/p&gt;
&lt;p&gt;The simplest possible machine learning model that meets this requirement would be multiplication by a 1 by 3N matrix W: M(x) = W x. This would multiply every one of the 3N inputs with a weight, and sum them all up. These weights are the trainable parameters. These are initially set to random values, and updated during training by correcting the errors the model makes. That part will remain the same throughout.&lt;/p&gt;
&lt;p&gt;This model has many undesirable properties, the most problematic one being that it is way too simple. A more precise way of saying this is that it is linear. This means that if we multiply all of the inputs by 2, the output will be multiplied by 2 as well. Or if we add 3 to say input x₁, the output will be the original output plus 3 w₁, where w₁ is the corresponding weight. In reality of course the effect of this change of one coordinate on the potential depends in a complicated way on its relationships to the coordinates of other particles. This model will never be able to capture that, no matter how much data you throw at it.&lt;/p&gt;
&lt;h2 id=&quot;deep-learning&quot;&gt;Deep learning&lt;/h2&gt;
&lt;p&gt;Removing this restriction takes us from machine learning to deep learning. The simplest neural network is basically a sequence of the simpler models from above, intermingled with nonlinear functions called activation functions. (Without these, the end result would still be linear!)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;657&quot; height=&quot;491&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MNG8au1e0VGNe723I3Fv1A-338974de.DjMYcLzq_Z1SL8p9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The simplest deep learning model: a fully connected neural network.&lt;/p&gt;
&lt;p&gt;The simplest example of this class of models has one hidden layer: it takes the 3N inputs to say 100 numbers by a matrix multiplication, and applicaties an activation function to each one separately. Then through a second matrix multiplication it takes those to the one number we need as an output.&lt;/p&gt;
&lt;p&gt;There are many different activation functions, conceptually the only important thing is that they are nonlinear. A simple often used example is the ReLU, which is 0 if its input is negative, and otherwise just passes on the input unchanged.&lt;/p&gt;
&lt;p&gt;The effect of adding just one of these hidden layers is profound. In a sense, this immediately fixes the problem with the previous model. That is, this model can approximate anything now, given enough parameters. This statement is known as the &lt;em&gt;universal approximation theorem&lt;/em&gt;. However, that is quite a theoretical result. It doesn’t say how large the hidden layer should be, how much data is necessary, or even if it’s possible to find the right parameters through training at all, only that they exist.&lt;/p&gt;
&lt;p&gt;To address all of these other concerns, we need to specialise the model further to our particular application. In other words, we want our model to not only take into account just the &lt;em&gt;size&lt;/em&gt; of the in- and outputs, but also its &lt;em&gt;structure&lt;/em&gt;. As a first example, although the model above has the correct number of 3N inputs, it is not aware at all that actually these have the structure of N triplets of coordinates.&lt;/p&gt;
&lt;p&gt;To elaborate on this and make it more precise, we’ll look at the concept of equivariance. For a book and lectures on exploiting the structure of our data that is much more detailed, but also quite technical, see &lt;a href=&quot;https://geometricdeeplearning.com/&quot;&gt;https://geometricdeeplearning.com/&lt;/a&gt;, and &lt;a href=&quot;https://www.nature.com/articles/s42256-021-00418-8&quot;&gt;this paper&lt;/a&gt; for applications specifically to molecules.&lt;/p&gt;
&lt;h3 id=&quot;equivariance&quot;&gt;Equivariance&lt;/h3&gt;
&lt;p&gt;Equivariance means that if we &lt;em&gt;first&lt;/em&gt; transform the input and &lt;em&gt;then&lt;/em&gt; apply the model to it, we get the same result as when we &lt;em&gt;first&lt;/em&gt; apply the model, and &lt;em&gt;then&lt;/em&gt; apply a similar transformation to the output. It is a property that a model can have for some transformations but not for others. For example if this is true for a model M when the transformations are rotations, we say that M is rotation equivariant or equivariant with respect to rotations, illustrated in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;420&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ez5PyIJRW8XGHQdlBjxxkQ-a83a4fc2.CH-zISRo_1gF3wY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example of equivariance of a hypothetical model M that just detects edges. No matter if we first apply the model and then rotate the result, or first rotate the input and then apply the model, we end up with the same result.&lt;/p&gt;
&lt;p&gt;Note that the definition refers to a &lt;em&gt;similar&lt;/em&gt; transformation on the output, not necessarily exactly the same as we applied to the input. In fact, usually the output of the model will be of a different shape than the input, so we cannot even do the exact same transformation. The important part is that we know a-priori what the transformation on the output is, and it depends only on what transformation we did on the input.&lt;/p&gt;
&lt;p&gt;A special case of equivariance is &lt;em&gt;invariance&lt;/em&gt;, which is when this similar transformation is actually the identity. In other words, if we transform the input, the output will remain unchanged. For a simple example of this, if the hypothetical model in the image above were just a classifier saying whether the image is a cat or a dog, we’d expect it to be invariant: for both inputs on the left of the image, the outputs on the right should be “cat”.&lt;/p&gt;
&lt;p&gt;Requiring the model to be equivariant with respect to some transformation imposes some constraints on it, it decreases the freedom in the model, or the number of parameters. So as long as the equivariances we impose are also satisfied by the true solution we are trying to approximate with the model, it makes it more data efficient and easier to train. If we didn’t impose equivariance, the model could potentially have learned it from the data, but that would require more data, more time and more parameters. If we know this property beforehand, clearly it pays off to enforce it, preventing the model from the get go to make mistakes of this kind.&lt;/p&gt;
&lt;p&gt;There are many different transformations that the true interatomic potential must be equivariant to. We will discuss these one by one and use them to refine our model.&lt;/p&gt;
&lt;h3 id=&quot;permutations&quot;&gt;Permutations&lt;/h3&gt;
&lt;p&gt;In turning the positions of all nuclei into a 3N-dimensional input vector, we had to implicitly decide an order: which particle is the first particle, which is the second, etc. Clearly this is just a choice of labelling; if we pick a different order for the exact same configuration of particles, the potential shouldn’t change. So we want our model to be &lt;em&gt;invariant&lt;/em&gt; with respect to permutations.&lt;/p&gt;
&lt;p&gt;Currently it is not, it has no idea that the output should be the same, and so it would have to learn that by seeing lots of examples of identical configurations that are labelled differently, but with the same training label. Clearly this is a huge waste of time, and we want to avoid this.&lt;/p&gt;
&lt;p&gt;There are several common functions that do not depend on the order of their arguments, i.e. that are permutation invariant, such as the sum, or the mean, or the maximum. We will just take the sum, as it preserves more information than the maximum. So the very simplest permutation-invariant model would just take all of the nuclei’s positions and sum them. (Actually this would still leave us with 3 coordinates, so we’d need a 1 by 3 matrix at the end to turn it into a single number.)&lt;/p&gt;
&lt;p&gt;This is of course again much too simple, in fact even more so than what we started with. We can improve the situation while still taking permutations into account by having only the &lt;em&gt;last&lt;/em&gt; layer be invariant, and adding &lt;em&gt;equivariant&lt;/em&gt; layers in between.&lt;/p&gt;
&lt;p&gt;Any function that does exactly the same to every nucleus will be equivariant with respect to permutations: if we reorder the inputs, the outputs will be the same as the original, except that they are also reordered in exactly the same way. For this function we can use what we ended up with in the previous section: a fully connected neural network. So that takes a nucleus’s 3 coordinates, and does several matrix multiplications and activation functions on it to end up with a different amount of numbers for each atom, that we can choose.&lt;/p&gt;
&lt;p&gt;Note that if the intermediate layers were &lt;em&gt;not&lt;/em&gt; equivariant, there would be no way to guarantee invariance at the final layer. Furthermore, it also already makes the model more data efficient, as one training sample automatically teaches it about all the different orderings of that same sample.&lt;/p&gt;
&lt;p&gt;Another important consequence of this is that, unlike the fully connected level, we now have a model that works regardless of how many nuclei there are. This is great, because it will allow us to train the model on a small system, and then use it on a larger system.&lt;/p&gt;
&lt;h3 id=&quot;locality-graph-neural-networks&quot;&gt;Locality, graph neural networks&lt;/h3&gt;
&lt;p&gt;The above modification does impose permutation invariance, but it was still too restrictive. It treats all the nuclei independently, finally just summing “individual potentials” to obtain the total potential. This is not realistic, we expect the potential to depend also on the distance &lt;em&gt;between&lt;/em&gt; nuclei, something that this model cannot learn.&lt;/p&gt;
&lt;p&gt;We can relax this restriction and at the same time incorporate another physical prior by adding more structure to the input.&lt;/p&gt;
&lt;p&gt;The physical principle is locality: what happens at some point x only depends on things close to x. More concretely in this case, the Coulomb potential between two particles at a distance r decreases as 1/r. This means that the interaction between two nuclei that are very far from each other doesn’t have any significant contribution to the potential.&lt;/p&gt;
&lt;p&gt;So for nuclei closer to each other than some cutoff distance r_c, we want to take their interaction into account, and we can connect them by an edge. Those that are further away are not connected by an edge. This way we turn the original point cloud input into a graph.&lt;/p&gt;
&lt;p&gt;We then extend the operation that previously did the same to all nuclei, to allow it to depend on an atom’s neighbours as well. However, the number of neighbours will be different for different nuclei, and if we allow this to make the output shapes of each atom different things will quickly grow out of hand. So we need a way to combine the neighbours in such a way as to keep the shape independent of the number of neighbours. Furthermore we again have the issue of permutation invariance, now at a smaller local scale. The solution to both problems is the same: we sum over the features of the neighbours.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;692&quot; height=&quot;526&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6pHDwX0OUPtuHWqbD0vUJw-f0843c46.d1xFbZ-o_Z1ORWx7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Illustration of message passing in a graph neural network. An atom c receives “messages” from its neighbours n and updates its state using those. The neighbours at the same time do the same. Multiple steps of this allow the message to propagate further.&lt;/p&gt;
&lt;p&gt;This is another permutation equivariant operation, now on graph inputs. It is called message passing, because it can be thought of as all of an atom’s neighbours passing messages to the central atom, who adds them all up. Doing this multiple times for all nuclei increases the region to which an atom is sensitive, because in the second step it can indirectly receive messages from its neighbours’ neighbours.&lt;/p&gt;
&lt;p&gt;At the end we have to sum over all nuclei again to obtain something invariant to permutations. These types of models are called Graph Neural Networks (GNNs).&lt;/p&gt;
&lt;h3 id=&quot;spatial-invariances&quot;&gt;Spatial invariances&lt;/h3&gt;
&lt;p&gt;While permutation invariance was more about the way we describe the system, how we label the nuclei, the remaining ones are actual spatial transformations: translations, rotations and reflections.&lt;/p&gt;
&lt;p&gt;If we move (“translate”) all nuclei in the same direction by the same amount, the interatomic potential doesn’t change. That is, whether we perform an experiment in Amsterdam, or we perform the exact same experiment in New York, the outcome should be the same. And the same holds for rotations and reflections. (If there were any external influence like gravity this would be different, but that is insignificant at the atomic scale.)&lt;/p&gt;
&lt;p&gt;As the model is now, it doesn’t know any of this. Building this in to the model makes it a lot more data efficient. From just one training simulation it would learn automatically about all its translations, rotations and reflections.&lt;/p&gt;
&lt;p&gt;The simplest way to enforce this is to only give the model inputs that are themselves invariant to these transformations. Clearly, if the inputs are not affected, the output is also not affected.&lt;/p&gt;
&lt;p&gt;That means we cannot have an atom’s position as an input by itself, as clearly that is not invariant under any of the transformations. But since we now have a graph, we can focus on &lt;em&gt;pairs&lt;/em&gt; of nuclei, and take the difference of their positions as an input. That is already invariant with respect to translations: if we add the same vector to both positions, it will cancel out in the difference. It is not yet invariant with respect to rotations or reflections, but if we reduce it further to just the absolute value of the difference, it is.&lt;/p&gt;
&lt;p&gt;That does the job, but it is again quite restrictive. Note the parallel here with the permutations we discussed previously: the simplest is to make everything invariant from the start, but it will turn out to be unnecessarily restrictive.&lt;/p&gt;
&lt;p&gt;For an example of something that is missed in this approach, consider a central atom with two two of its neighbours. The vectors pointing from the central atom to those two neighbours make up a certain angle to each other. If you think about it, this angle is also invariant with respect to all of the transformations. And it might well be a useful feature that has an effect on the potential that we want the model to represent. But there is no way to reconstruct this angle just from the absolute value of the differences in positions. Had we not thrown away that much information so early on, we &lt;em&gt;would&lt;/em&gt; be able to recover this angle: it’s related to the inner product between the two vectors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;554&quot; height=&quot;437&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_a_4d0GaMmdDN6ZJ8s81Rqg-6d8dab71.BVg6UK_y_Z2daGhj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The angle φ is invariant to translations, rotations and reflections.&lt;/p&gt;
&lt;p&gt;We could of course add these angles to the input “by hand” and stick to imposing invariance from the start, and there are models that do this. But there are many more features that we are throwing away. A more systematic approach would again be to only impose invariance in the final layer, and keep the others equivariant.&lt;/p&gt;
&lt;h3 id=&quot;higher-representationsorbitals&quot;&gt;Higher representations/orbitals&lt;/h3&gt;
&lt;p&gt;It gets a bit more complicated though. The complication is that there are many ways that things can transform under rotations. Chemists know these as orbitals, physicists and mathematicians as different representations of the rotation group.&lt;/p&gt;
&lt;p&gt;I’ll give an idea that, while not mathematically rigorous, captures the intuition of what’s important for us here. Imagine we start with two vectors representing the positions of two nuclei, which are in what is called the L=1 representation or the p orbital; here, the vector remains unchanged when rotated along its own axis but changes its position when rotated in any other way.&lt;/p&gt;
&lt;p&gt;We can combine these two vectors by taking the length of their difference. As mentioned before, this is invariant, it is called the L=0 representation or the s orbital. It is a single number that doesn’t change under any rotation. We can also simply add them, then it remains a vector.&lt;/p&gt;
&lt;p&gt;The two vectors together define a plane, a two dimensional surface that they both lie in (assuming that they are not parallel). Or more concretely imagine one vector pointing out of the cockpit of an actual plane and one along one wing. The plane they define together would be the floor of the inside of the actual plane.&lt;/p&gt;
&lt;p&gt;Loosely speaking this is how the two vectors can be combined to a higher representation, this would be the L=2 representation or the d orbital. Note that this plane depends on both vectors: if we rotate along the wing of the plane, that vector doesn’t change, but the one pointing out the cockpit certainly does, and so does the floor of the plane.&lt;/p&gt;
&lt;p&gt;This pattern continues: every time we add a new vector into the mix, we can either lower the representation by one, keep it the same, or increase it by one. For example if we start with a plane and a vector, you can imagine projecting the vector into the plane, that gives us a new vector, lowering the representation by one.&lt;/p&gt;
&lt;p&gt;So, crucially, the more complex combinations can be reduced down to something that is invariant, as we require for the output of the model.&lt;/p&gt;
&lt;p&gt;If we are very precise in how a layer is allowed to combine its inputs to form its outputs (how it combines the orbitals/representations), we can have intermediate layers that are equivariant, and a final equivariant output. This will then not only automatically capture the angles we mentioned before, but also more complex structures.&lt;/p&gt;
&lt;p&gt;This again makes the model more data-efficient, without paying the price of oversimplifying the input and throwing away a lot of information.&lt;/p&gt;
&lt;p&gt;This is implemented in the &lt;a href=&quot;https://github.com/e3nn/e3nn&quot;&gt;e3nn&lt;/a&gt; library, and used for example in the molecular dynamics models &lt;a href=&quot;https://github.com/mir-group/nequip&quot;&gt;nequip&lt;/a&gt; and &lt;a href=&quot;https://github.com/mir-group/allegro&quot;&gt;allegro&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;By looking carefully at the structure of the problem, in particular how the true interatomic potential must transform under several transformations of its input, we have constructed a model that is very data efficient. The arguments to get here were very generic, and apply to any model that approximates an invariant function of particle positions.&lt;/p&gt;
&lt;p&gt;First we saw that we needed more than one layer in order to learn more than just linear functions. We used permutation invariance combined with locality to arrive at a graph neural network. On top of this we required invariance with respect to the spatial transformations of translations, rotations and reflections. This gives us what is called an E(3)-equivariant GNN (E(3) is the name for these transformations in 3-dimensional space).&lt;/p&gt;
&lt;p&gt;In the final part we will look at considerations that go into training this model.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_GVOnfCp1wScCos1_-b1c8ae9b.BJjMZttk.webp" medium="image"/><author>Aron</author></item><item><title>Ditching Docker Hub: serve research software with GHCR + Zenodo</title><link>https://blog2.esciencecenter.nl/posts/2023-04-06---ditching-docker-hub-serve-research-software-with-ghcr-zenodo</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-04-06---ditching-docker-hub-serve-research-software-with-ghcr-zenodo</guid><description>&lt;h2 id=&quot;or-pay-the-price-that-docker-hub-may-charge-you&quot;&gt;Or pay the price… that Docker Hub may charge you&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uLU5uRex4V9KagumXjzzpw-85a5ef6c.02ncUoQr_1ATE6R.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Scrooge McDuck who throws a Docker container in the trash in the style of Disney… according to Stable Diffusion.&lt;/p&gt;
&lt;p&gt;As a researcher, and especially as a research software engineer, you may find yourself writing software that needs to be shared with others in a &lt;strong&gt;reproducible&lt;/strong&gt; way. So, you containerize it. In the past, you might then have used Docker Hub to store your containerized software.&lt;/p&gt;
&lt;p&gt;However, recent attempts to change Docker Hub’s pricing model have made it less attractive as a long-term repository. Frankly, it has made us uncertain about Docker Hub’s reliability as a long-term archive. &lt;a href=&quot;https://devclass.com/2023/03/15/docker-to-users-of-free-team-orgs-one-month-to-pay-up-or-we-freeze-account-and-images-go/&quot;&gt;Docker’s recent trial balloon about deleting Docker images in “Free Team” accounts&lt;/a&gt; (which they apologized for the next day, and was completely reverted after 10 days, but still…) does not foster trust, to say the least.&lt;/p&gt;
&lt;p&gt;To minimize the risk of having to pay for Docker Hub use at any unexpected time, we now recommend using GitHub Container Registry (GHCR) for use during development and Zenodo for archiving.&lt;/p&gt;
&lt;h2 id=&quot;during-development-github-container-registry&quot;&gt;During development: GitHub Container Registry&lt;/h2&gt;
&lt;p&gt;GitHub Container Registry (GHCR) is a relatively new addition to the GitHub ecosystem, but it’s already proving to be a powerful tool for developers. As the name suggests, GHCR allows you to store and distribute Docker images directly from your GitHub repositories. This means that you can keep all of your code and its associated container images in one place, which makes it easier to manage and collaborate on.&lt;/p&gt;
&lt;p&gt;One of the biggest advantages of GHCR is that it integrates seamlessly with other GitHub tools, such as Actions and Packages, which can be used to automate workflows and improve collaboration. Also, it’s free (for public images; for private ones you have to pay, which should not pose an issue in this day and age of Open Science). GHCR is included as part of your GitHub account. This means that you can store as many Docker images as you like without worrying about the costs.&lt;/p&gt;
&lt;p&gt;At the eScience Center, we have been using GHCR for a while already, for instance for the &lt;a href=&quot;https://github.com/research-software-directory/RSD-as-a-service&quot;&gt;Research Software Directory&lt;/a&gt;. You can see in the right-hand panel the packages menu which lists a couple of the available images:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;329&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jixBfMoQwy4kUZB2OurKkg-6dc258e7.Cu6JU-rG_1n5qsE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Packages widget listing the Docker images stored in GHCR for the Research Software Directory.&lt;/p&gt;
&lt;p&gt;Clicking for instance on &lt;strong&gt;rsd-saas/database&lt;/strong&gt; brings you to the page where you get clear instructions on how to get the image on your machine using:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;docker pull ghcr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;research&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;software&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;directory&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;rsd&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;saas&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;database:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;18.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Couldn’t get much easier!&lt;/p&gt;
&lt;h2 id=&quot;long-term-archiving-zenodo&quot;&gt;Long term archiving: Zenodo&lt;/h2&gt;
&lt;p&gt;However, GHCR is not a long-term archiving solution. While it’s great for development and sharing with collaborators, you’ll still need to find a way to archive your software for the long term. This is where Zenodo comes in.&lt;/p&gt;
&lt;p&gt;Zenodo is a free, open-access repository that’s designed specifically for research outputs. This includes software, data, and other digital objects. By archiving your software on Zenodo, you’ll be ensuring that it’s accessible and discoverable for the long term. Zenodo also provides persistent identifiers (DOIs) for your software, which can be used to cite it in publications.&lt;/p&gt;
&lt;p&gt;To archive your software on Zenodo, simply &lt;a href=&quot;https://zenodo.org/deposit/new&quot;&gt;create a new record and upload your Docker image as a file&lt;/a&gt;. To create such a file from an image called &lt;code&gt;hello-world:latest&lt;/code&gt; you can create a zipped tarball like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;docker image save hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;world:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; gzip &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;world:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tar&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also include additional metadata, such as a description of your software and the research project it’s associated with. Once your record is published, it will be available for anyone to access and download. One project we came across that has been doing this already is &lt;a href=&quot;https://spex-xray.github.io/spex-help/getstarted/docker.html#step-2-download-the-spex-docker-image-from-zenodo&quot;&gt;Spex&lt;/a&gt;, a popular X-ray astronomy package. Following their lead, after someone downloads the &lt;code&gt;hello-world:latest.tar.gz&lt;/code&gt; file, firing your container back up with Docker is as easy as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;docker &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;world:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tar&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;one-repo-to-rule-them-all&quot;&gt;One repo to rule them all?&lt;/h2&gt;
&lt;p&gt;Why not use Zenodo for all images, you may wonder? For us, the reason is that GHCR is meant to be used together with GitHub Actions as well. It’s the fastest option for continuous integration and also for running tests locally. It is also a one-command option, as opposed to the Zenodo option where you have a manual download step to do before using the image.&lt;/p&gt;
&lt;p&gt;Why not use GHCR for all images, then? Zenodo is a dedicated research “artifact” storage repository. Like Docker Hub, GitHub, a commercial company, may change its policies at any time and start charging to preserve your containers. This would in fact be totally reasonable for them to do. We trust Zenodo to be a reliable long-term archiving solution for research.&lt;/p&gt;
&lt;p&gt;Of course, Docker Hub can still be an option for you, if you are willing to pay them. It is, after all, still the simplest way to use Docker. This requires long-term institutional funding, though, which unfortunately is rare in academia, especially for supporting research software. &lt;a href=&quot;https://dspace.library.uu.nl/handle/1874/424547&quot;&gt;An issue which is being worked on, by the way…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In conclusion, if you’re a researcher writing software that needs to be shared with others, we recommend using GitHub Container Registry for development and Zenodo for archiving. GHCR is a powerful and free tool that integrates seamlessly with GitHub, while Zenodo provides a long-term archiving solution that’s designed specifically for research outputs. By using these tools together, you can ensure that your software is both accessible and discoverable for the long term.&lt;/p&gt;
&lt;h2 id=&quot;credits--meta-sub-blogpost&quot;&gt;Credits / meta-sub-blogpost&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This article was written based on a discussion in the eScience Center’s Software Sustainability special interest group (SIG).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Actually, “written” is not fully accurate. I fed the SIG meeting notes into ChatGPT and asked it to process that into a blogpost; the above is mostly the result of that, with some minor edits from my side.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;939&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_40yq4tQyLhtUsNsmhZzH7Q-f0aaae37.DM2UbHWW_ZLkjAL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I didn’t really like the titles it proposed though:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;823&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RdBrqE58a6a00BnrXEw7hA-a0fc042c.DDvILlWh_ZuOXnv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Close enough, though!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Tom Bakker, Stefan Verhoeven, Luisa Orozco and Carlos Martinez for improving on ChatGPT’s draft!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1z7VDm5f7eSfYql5M4lZAw-dd23f63e.w9gtqVBa_Z1q4tkP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Same as above, but now in the style of Looney Tunes… You AIs, you!&lt;/p&gt;</description><pubDate>Thu, 06 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;or-pay-the-price-that-docker-hub-may-charge-you&quot;&gt;Or pay the price… that Docker Hub may charge you&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uLU5uRex4V9KagumXjzzpw-85a5ef6c.02ncUoQr_1ATE6R.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Scrooge McDuck who throws a Docker container in the trash in the style of Disney… according to Stable Diffusion.&lt;/p&gt;
&lt;p&gt;As a researcher, and especially as a research software engineer, you may find yourself writing software that needs to be shared with others in a &lt;strong&gt;reproducible&lt;/strong&gt; way. So, you containerize it. In the past, you might then have used Docker Hub to store your containerized software.&lt;/p&gt;
&lt;p&gt;However, recent attempts to change Docker Hub’s pricing model have made it less attractive as a long-term repository. Frankly, it has made us uncertain about Docker Hub’s reliability as a long-term archive. &lt;a href=&quot;https://devclass.com/2023/03/15/docker-to-users-of-free-team-orgs-one-month-to-pay-up-or-we-freeze-account-and-images-go/&quot;&gt;Docker’s recent trial balloon about deleting Docker images in “Free Team” accounts&lt;/a&gt; (which they apologized for the next day, and was completely reverted after 10 days, but still…) does not foster trust, to say the least.&lt;/p&gt;
&lt;p&gt;To minimize the risk of having to pay for Docker Hub use at any unexpected time, we now recommend using GitHub Container Registry (GHCR) for use during development and Zenodo for archiving.&lt;/p&gt;
&lt;h2 id=&quot;during-development-github-container-registry&quot;&gt;During development: GitHub Container Registry&lt;/h2&gt;
&lt;p&gt;GitHub Container Registry (GHCR) is a relatively new addition to the GitHub ecosystem, but it’s already proving to be a powerful tool for developers. As the name suggests, GHCR allows you to store and distribute Docker images directly from your GitHub repositories. This means that you can keep all of your code and its associated container images in one place, which makes it easier to manage and collaborate on.&lt;/p&gt;
&lt;p&gt;One of the biggest advantages of GHCR is that it integrates seamlessly with other GitHub tools, such as Actions and Packages, which can be used to automate workflows and improve collaboration. Also, it’s free (for public images; for private ones you have to pay, which should not pose an issue in this day and age of Open Science). GHCR is included as part of your GitHub account. This means that you can store as many Docker images as you like without worrying about the costs.&lt;/p&gt;
&lt;p&gt;At the eScience Center, we have been using GHCR for a while already, for instance for the &lt;a href=&quot;https://github.com/research-software-directory/RSD-as-a-service&quot;&gt;Research Software Directory&lt;/a&gt;. You can see in the right-hand panel the packages menu which lists a couple of the available images:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;329&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jixBfMoQwy4kUZB2OurKkg-6dc258e7.Cu6JU-rG_1n5qsE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Packages widget listing the Docker images stored in GHCR for the Research Software Directory.&lt;/p&gt;
&lt;p&gt;Clicking for instance on &lt;strong&gt;rsd-saas/database&lt;/strong&gt; brings you to the page where you get clear instructions on how to get the image on your machine using:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;docker pull ghcr.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;research&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;software&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;directory&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;rsd&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;saas&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;database:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;18.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Couldn’t get much easier!&lt;/p&gt;
&lt;h2 id=&quot;long-term-archiving-zenodo&quot;&gt;Long term archiving: Zenodo&lt;/h2&gt;
&lt;p&gt;However, GHCR is not a long-term archiving solution. While it’s great for development and sharing with collaborators, you’ll still need to find a way to archive your software for the long term. This is where Zenodo comes in.&lt;/p&gt;
&lt;p&gt;Zenodo is a free, open-access repository that’s designed specifically for research outputs. This includes software, data, and other digital objects. By archiving your software on Zenodo, you’ll be ensuring that it’s accessible and discoverable for the long term. Zenodo also provides persistent identifiers (DOIs) for your software, which can be used to cite it in publications.&lt;/p&gt;
&lt;p&gt;To archive your software on Zenodo, simply &lt;a href=&quot;https://zenodo.org/deposit/new&quot;&gt;create a new record and upload your Docker image as a file&lt;/a&gt;. To create such a file from an image called &lt;code&gt;hello-world:latest&lt;/code&gt; you can create a zipped tarball like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;docker image save hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;world:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; gzip &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;world:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tar&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also include additional metadata, such as a description of your software and the research project it’s associated with. Once your record is published, it will be available for anyone to access and download. One project we came across that has been doing this already is &lt;a href=&quot;https://spex-xray.github.io/spex-help/getstarted/docker.html#step-2-download-the-spex-docker-image-from-zenodo&quot;&gt;Spex&lt;/a&gt;, a popular X-ray astronomy package. Following their lead, after someone downloads the &lt;code&gt;hello-world:latest.tar.gz&lt;/code&gt; file, firing your container back up with Docker is as easy as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;docker &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;load&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;i hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;world:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;tar&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;one-repo-to-rule-them-all&quot;&gt;One repo to rule them all?&lt;/h2&gt;
&lt;p&gt;Why not use Zenodo for all images, you may wonder? For us, the reason is that GHCR is meant to be used together with GitHub Actions as well. It’s the fastest option for continuous integration and also for running tests locally. It is also a one-command option, as opposed to the Zenodo option where you have a manual download step to do before using the image.&lt;/p&gt;
&lt;p&gt;Why not use GHCR for all images, then? Zenodo is a dedicated research “artifact” storage repository. Like Docker Hub, GitHub, a commercial company, may change its policies at any time and start charging to preserve your containers. This would in fact be totally reasonable for them to do. We trust Zenodo to be a reliable long-term archiving solution for research.&lt;/p&gt;
&lt;p&gt;Of course, Docker Hub can still be an option for you, if you are willing to pay them. It is, after all, still the simplest way to use Docker. This requires long-term institutional funding, though, which unfortunately is rare in academia, especially for supporting research software. &lt;a href=&quot;https://dspace.library.uu.nl/handle/1874/424547&quot;&gt;An issue which is being worked on, by the way…&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In conclusion, if you’re a researcher writing software that needs to be shared with others, we recommend using GitHub Container Registry for development and Zenodo for archiving. GHCR is a powerful and free tool that integrates seamlessly with GitHub, while Zenodo provides a long-term archiving solution that’s designed specifically for research outputs. By using these tools together, you can ensure that your software is both accessible and discoverable for the long term.&lt;/p&gt;
&lt;h2 id=&quot;credits--meta-sub-blogpost&quot;&gt;Credits / meta-sub-blogpost&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This article was written based on a discussion in the eScience Center’s Software Sustainability special interest group (SIG).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Actually, “written” is not fully accurate. I fed the SIG meeting notes into ChatGPT and asked it to process that into a blogpost; the above is mostly the result of that, with some minor edits from my side.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;939&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_40yq4tQyLhtUsNsmhZzH7Q-f0aaae37.DM2UbHWW_ZLkjAL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I didn’t really like the titles it proposed though:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;823&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RdBrqE58a6a00BnrXEw7hA-a0fc042c.DDvILlWh_ZuOXnv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Close enough, though!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Tom Bakker, Stefan Verhoeven, Luisa Orozco and Carlos Martinez for improving on ChatGPT’s draft!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1z7VDm5f7eSfYql5M4lZAw-dd23f63e.w9gtqVBa_Z1q4tkP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Same as above, but now in the style of Looney Tunes… You AIs, you!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_jixBfMoQwy4kUZB2OurKkg-6dc258e7.Cu6JU-rG.png" medium="image"/><author>Patrick Bos</author></item><item><title>Molecular Simulations using Machine Learning, Part 1</title><link>https://blog2.esciencecenter.nl/posts/2023-03-31---molecular-simulations-using-machine-learning-part-1</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-03-31---molecular-simulations-using-machine-learning-part-1</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;270&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YCtoB6VF8ntOvbyl4Oy5OQ-c1205a48.DO7ORMD9_ZlzXvd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simulation of water molecules from Wikipedia.&lt;/p&gt;
&lt;p&gt;Are you curious about how scientists study the properties of materials, proteins, and drugs? It all starts with molecular simulation. By creating virtual models and running simulations at the molecular level, researchers can unlock the secrets of these substances and design new ones. The gif above shows a short such simulation, in this case simply of water.&lt;/p&gt;
&lt;p&gt;In this three-part blog series, we’ll explore the exciting world of molecular simulation and how machine learning is revolutionizing the field. This first part is purely about the physics. If you have a somewhat technical background and an interest in the topic, it might be interesting to you. If it becomes too technical, the next two parts about machine learning will be relatively stand-alone, and should be interesting also to scientists thinking about applying machine learning to their own fields.&lt;/p&gt;
&lt;p&gt;Here we’ll look at the fundamental theory of quantum mechanics, which underpins molecular simulation. But simulating molecules using this theory directly is too difficult computationally. So, we’ll explore how physicists and chemists have simplified the theory to make it workable for simulation.&lt;/p&gt;
&lt;p&gt;While simplifying the theory makes it more efficient, it also creates some gaps that need to be filled. That’s where the machine learning will come in, allowing us to learn these from data.&lt;/p&gt;
&lt;h2 id=&quot;quantum-mechanics-and-the-schrödinger-equation&quot;&gt;Quantum Mechanics and the Schrödinger Equation&lt;/h2&gt;
&lt;p&gt;We will start with quantum mechanics in a simplified setting where the system we study is in equilibrium. This is described by the time-independent Schrödinger equation:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;562&quot; height=&quot;182&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7i7tcw7VNt8GURTaOs1P6g-3a40b70c.3E80kelT_2axLfz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Schrödinger equation in its simplest form.&lt;/p&gt;
&lt;p&gt;Here m is the mass, p the momentum, V the potential energy, and E the total energy of the system.&lt;/p&gt;
&lt;p&gt;What we want to solve this equation for is ψ, which is called the wave function. It encodes the density of the particles we are studying, at every point in space.&lt;/p&gt;
&lt;p&gt;While superficially this may look quite short and simple, it hides a lot of complexity, both conceptual and computational. In this blog I will focus on the computational complexity.&lt;/p&gt;
&lt;p&gt;One thing I have swept under the rug in the equation above is that our system has not just one but many particles. Each of them has their own momentum and their own mass (although electrons all have the same mass, and for simplicity we can think of the nuclei all being the same, so having the same mass as well). So actually there should be a sum over all particles in the left most term.&lt;/p&gt;
&lt;p&gt;The momentum p is actually a derivative with respect to the position in quantum mechanics. More precisely, p = — i ℏ ∂, where ℏ is a very small number called Planck’s constant. Its smallness is the reason we can get through everyday life without thinking about quantum mechanics.&lt;/p&gt;
&lt;p&gt;This leads to something more problematic that I have also swept under the rug. Since the momentum is a derivative with respect to the position, acting on the wave function, and each particle has its own momentum, the wave function is not just a function of the position, it is a function of &lt;em&gt;the positions of every single particle&lt;/em&gt;. A block of material the size of your smartphone has about 10²⁵ electrons and nuclei, that’s a lot of arguments!&lt;/p&gt;
&lt;p&gt;The potential by the way is the Coulomb potential that charged particles exert on each other, so that also depends on all of the coordinates.&lt;/p&gt;
&lt;p&gt;To understand the computational complexity better it is insightful to look at how we would solve this numerically. Basically, the way most numerical methods go about solving a differential equation is to evaluate the equation itself on a certain number of points. This allows translating the differential equation into linear algebra, a matrix equation essentially of the form A x = b, where A is a matrix and b a vector that we both obtain from this procedure, and if we solve this for the vector x we get an approximation of the solution we’re after on this same set of points.&lt;/p&gt;
&lt;p&gt;How many points we need depends heavily on the details, but let’s say for simplicity the system is constrained to be on a single line, in other words space is only 1-dimensional. Let’s also restrict it to the interval between 0 and 1, and say we use K points, located at the positions x_i = i /K on the interval.&lt;/p&gt;
&lt;p&gt;Maybe K=20 could be sufficient in some very simple situation, so that doesn’t seem too bad. Remember though that every single particle has a position, and the wave function depends on all of them. So we need all &lt;em&gt;combinations&lt;/em&gt; of positions. So for a system with 10²⁵ particles that amounts to 20 &lt;em&gt;to the power&lt;/em&gt; 10²⁵ points.&lt;/p&gt;
&lt;p&gt;Another way to think about this is that if we add only a single electron to our system, we’d now need to solve the original system once for every possible location of the added electron. So in our example this would make the problem a 20 times larger, this is known as exponential complexity.&lt;/p&gt;
&lt;p&gt;These ridiculous numbers come from the combination of the exponential complexity of the problem with the already huge number of particles involved.&lt;/p&gt;
&lt;p&gt;This means that using this equation directly is only feasible for the smallest of systems, which really means practically only the hydrogen atom: a single nucleus with a single electron.&lt;/p&gt;
&lt;h2 id=&quot;approximations&quot;&gt;Approximations&lt;/h2&gt;
&lt;p&gt;Clearly then we need to do some approximations to this equation. I will illustrate conceptually a series of explanations that is very standard.&lt;/p&gt;
&lt;p&gt;The first and simplest step follows from the observation that the proton is much heavier than the electron, by a factor of about 1000. So even for hydrogen, whose nucleus is just a single proton, this is a significant factor, and for bigger cores the ratio is even larger, for example carbon contains 12 protons and neutrons (which have similar mass to protons), so their mass is about 10⁴ times that of an electron.&lt;/p&gt;
&lt;p&gt;Now heavy things tend to move more slowly than light things, this is the essence of what is called the &lt;em&gt;clamped nuclei approximation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;From the point of view of an electron, on the typical timescale at which it itself moves, the nuclei are basically standing still. So assuming we know the positions of all the nuclei, we can treat those as fixed, and we can compute the force they exert on the electrons, and solve for the electrons separately.&lt;/p&gt;
&lt;p&gt;Conversely, from the point of view of a nucleus, by the time it itself moves, all the electrons will have had enough time to settle down to their equilibrium positions, into what is called their ground state.&lt;/p&gt;
&lt;p&gt;So this allows us to in a sense decouple the electrons from the nuclei. By itself this doesn’t give a significant improvement yet, so we need to simplify each part separately.&lt;/p&gt;
&lt;h3 id=&quot;the-electrons-density-functional-theory-dft&quot;&gt;The electrons: Density Functional Theory (DFT)&lt;/h3&gt;
&lt;p&gt;First we’ll look at the electrons. The difficulty of the problem lies in the interactions between them. If they were all independent it would be a much simpler problem, but clearly that is too crude of an approximation: they exert a Coulomb force on each other, so they are not independent. There are additional quantum mechanical effects that make them even less independent.&lt;/p&gt;
&lt;p&gt;What we &lt;em&gt;can&lt;/em&gt; do is to simplify all interactions to just interactions between each individual particle and some kind of averaged out particle, this is known as the mean field approximation. That is, we imagine that all of the electrons contribute to an average electron density. This density creates some potential energy that is felt by every electron. If that sounds recursive, that’s because it is. That is the price we pay for this approximation: we get a simpler problem, but we have to solve it many times until it is self consistent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;663&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_nYX_YbciZm8swnTDX1AJ5g-0177e0e1.Dg_ExSH0_2eueTy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Adapted in simplified form from Materials Modelling using Density Functional Theory, Feliciano Giustino.&lt;/p&gt;
&lt;p&gt;The process is illustrated in the figure above. Assume we know where the nuclei are, that gives a potential coming from the nuclei which is the input to the problem. Then we make a guess for this electron density, and use that to compute another potential, caused by the electrons themselves. Now we know the equation for every electron separately, which we can then solve independently from each other. But the total density should be the sum over the individual electron densities, so we compute that. Likely we won’t get the same as the density we started with, and we have to repeat this whole procedure until we do.&lt;/p&gt;
&lt;p&gt;This approach is called Density Functional Theory (DFT).&lt;/p&gt;
&lt;p&gt;What I’ve glossed over is what this potential is that each electron feels due to the total density. This is what gives this theory its name: the density functional. A functional is just what mathematicians call a function whose argument is itself a function. In this case the potential is a function of the electron density, which itself is a function of the position (a single position this time!).&lt;/p&gt;
&lt;p&gt;The interesting situation is that this whole “approximation” is known to be &lt;em&gt;exact&lt;/em&gt;. So at this point it is not an approximation at all, we do not lose any accuracy by doing this. There is a catch however. The theory only tells us that an appropriate density functional &lt;em&gt;exists&lt;/em&gt;, that makes it exact in any situation, but it does not tell us &lt;em&gt;what&lt;/em&gt; &lt;em&gt;it is&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So the actual approximation comes in the form of a guess of the density functional. Coming up with density functionals that perform well in certain situations is a whole field of research, and there is a whole zoo of density functionals out there.&lt;/p&gt;
&lt;p&gt;In terms of the computational complexity, the bottleneck lies in solving for the individual electrons, combined with the fact that we have to keep doing this until convergence. ==The time taken scales roughly with the third power of the number of electrons==. This is not great, but still much better than the exponential scaling we started with!&lt;/p&gt;
&lt;p&gt;Concretely, in the example where we used 10 grid points, going from 100 to 101 particles made using the Schrödinger equation directly 10 times slower, whereas DFT only becomes it 3% slower. You see how important these scalings of computational complexities are.&lt;/p&gt;
&lt;p&gt;In practice, whereas the Schrödinger equation could almost only be applied to the simplest of atoms, DFT can be used not just for single atoms, but for molecules and even multiple molecules together. It is still very expensive computationally though, not something you can run on your laptop, rather on a cluster and potentially having to wait a few weeks depending on the problem. From where we started though, this is already a big step up.&lt;/p&gt;
&lt;h3 id=&quot;the-nuclei-molecular-dynamics-md&quot;&gt;The nuclei: Molecular Dynamics (MD)&lt;/h3&gt;
&lt;p&gt;Now we turn back to the nuclei. Here the most important source of approximation is their mass. We already used this to decouple them from the electrons, as their mass is much larger. We can now use this in another way.&lt;/p&gt;
&lt;p&gt;Quantum mechanics only becomes necessary to describe a system if it is very small and light. For the movement of billiard balls on a pool table, we can fortunately just use classical mechanics. Formally this is a limit of quantum mechanics, prosaically known as the classical limit. Remember that in the Schrödinger equation I said that the momentum is actually a derivative with respect to the position, and the wave function encodes the probability of finding a particle somewhere. In the classical limit, the momentum goes back to being just a number, and the probability goes away, so that a particle is just described by its position and its momentum.&lt;/p&gt;
&lt;p&gt;Perhaps surprisingly, even for something as small as a nucleus, this is a good approximation. That is true for all but the smallest nuclei, such as hydrogen.&lt;/p&gt;
&lt;p&gt;This leads to a very simple system, where we have a potential coming from the electrons in addition to the Coulomb potential between the nuclei themselves. We obtain the forces just by taking the derivative of the potential, and with these forces we can evolve the nuclei in time.&lt;/p&gt;
&lt;p&gt;This approach is called &lt;em&gt;Molecular Dynamics (MD)&lt;/em&gt;, and is illustrated in the flowchart below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;771&quot; height=&quot;393&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0xhgXYMhL1XVf6LXSjUsMg-4bf2a6ea.D64hjsCJ_uEIJK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Adapted in simplified form from Materials Modelling using Density Functional Theory, Feliciano Giustino.&lt;/p&gt;
&lt;p&gt;Here again we had to introduce an unknown potential, in this case called the &lt;em&gt;interatomic potential&lt;/em&gt;. This captures the effect of the electrons on the nuclei. And again this is a priori unknown, so we have to guess it.&lt;/p&gt;
&lt;p&gt;In this case, there is a very natural candidate. We have just discussed a way to compute the electron density for any configuration of nuclei, namely DFT. So we could do that, and then simply use the Coulomb potential coming from this electron density. This is known as &lt;em&gt;ab-initio Molecular Dynamics (aiMD)&lt;/em&gt;, because we didn’t need to make another guess on a potential.&lt;/p&gt;
&lt;p&gt;The good thing about aiMD is that it is usually very accurate. However it requires a full DFT computation for every step of MD, making it very expensive computationally.&lt;/p&gt;
&lt;p&gt;The alternative is to come up with a simple form of the interatomic potential that is very fast to evaluate, and may be accurate for certain systems. Many such guesses exist.&lt;/p&gt;
&lt;p&gt;So here the computational complexity is very strongly dependent on the interatomic potential used, the other steps are usually negligible in comparison. Less expensive potentials can be used to simulate millions of atoms, for example in large proteins or crystal structures.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;The diagram below summarizes what we have discussed.&lt;br&gt;
Through a series of physically motivated, and for many situations very accurate, approximations we have reduced the elegant but computationally intractable formulation of the Schrödinger equation into two parts: density functional theory (DFT) for the electrons and molecular dynamics (MD) for the nuclei.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1131&quot; height=&quot;894&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zwvn0X4z6_mG4zyQ4acULw-036d0626.CR6qfiv9_5UqRY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simplified illustration of the approximations done to go from quantum mechanics to Density Functional Theory (DFT) describing the electrons and Molecular Dynamics (MD) describing the nuclei. The clouds contain the ingredients that need to be specified to complete each theory.&lt;/p&gt;
&lt;p&gt;For both parts, this required the introduction of a priori unknown potentials: the density functional for DFT and the interatomic potential for MD. For both of these, a whole zoo of guesses exist, each of varying accuracy depending on the system at hand.&lt;/p&gt;
&lt;p&gt;This is where machine learning comes into the picture: rather than guessing these potentials ourselves, we can let a machine learning model learn them from data. We will discuss this in part 2 of this series.&lt;/p&gt;</description><pubDate>Fri, 31 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;270&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YCtoB6VF8ntOvbyl4Oy5OQ-c1205a48.DO7ORMD9_ZlzXvd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simulation of water molecules from Wikipedia.&lt;/p&gt;
&lt;p&gt;Are you curious about how scientists study the properties of materials, proteins, and drugs? It all starts with molecular simulation. By creating virtual models and running simulations at the molecular level, researchers can unlock the secrets of these substances and design new ones. The gif above shows a short such simulation, in this case simply of water.&lt;/p&gt;
&lt;p&gt;In this three-part blog series, we’ll explore the exciting world of molecular simulation and how machine learning is revolutionizing the field. This first part is purely about the physics. If you have a somewhat technical background and an interest in the topic, it might be interesting to you. If it becomes too technical, the next two parts about machine learning will be relatively stand-alone, and should be interesting also to scientists thinking about applying machine learning to their own fields.&lt;/p&gt;
&lt;p&gt;Here we’ll look at the fundamental theory of quantum mechanics, which underpins molecular simulation. But simulating molecules using this theory directly is too difficult computationally. So, we’ll explore how physicists and chemists have simplified the theory to make it workable for simulation.&lt;/p&gt;
&lt;p&gt;While simplifying the theory makes it more efficient, it also creates some gaps that need to be filled. That’s where the machine learning will come in, allowing us to learn these from data.&lt;/p&gt;
&lt;h2 id=&quot;quantum-mechanics-and-the-schrödinger-equation&quot;&gt;Quantum Mechanics and the Schrödinger Equation&lt;/h2&gt;
&lt;p&gt;We will start with quantum mechanics in a simplified setting where the system we study is in equilibrium. This is described by the time-independent Schrödinger equation:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;562&quot; height=&quot;182&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7i7tcw7VNt8GURTaOs1P6g-3a40b70c.3E80kelT_2axLfz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Schrödinger equation in its simplest form.&lt;/p&gt;
&lt;p&gt;Here m is the mass, p the momentum, V the potential energy, and E the total energy of the system.&lt;/p&gt;
&lt;p&gt;What we want to solve this equation for is ψ, which is called the wave function. It encodes the density of the particles we are studying, at every point in space.&lt;/p&gt;
&lt;p&gt;While superficially this may look quite short and simple, it hides a lot of complexity, both conceptual and computational. In this blog I will focus on the computational complexity.&lt;/p&gt;
&lt;p&gt;One thing I have swept under the rug in the equation above is that our system has not just one but many particles. Each of them has their own momentum and their own mass (although electrons all have the same mass, and for simplicity we can think of the nuclei all being the same, so having the same mass as well). So actually there should be a sum over all particles in the left most term.&lt;/p&gt;
&lt;p&gt;The momentum p is actually a derivative with respect to the position in quantum mechanics. More precisely, p = — i ℏ ∂, where ℏ is a very small number called Planck’s constant. Its smallness is the reason we can get through everyday life without thinking about quantum mechanics.&lt;/p&gt;
&lt;p&gt;This leads to something more problematic that I have also swept under the rug. Since the momentum is a derivative with respect to the position, acting on the wave function, and each particle has its own momentum, the wave function is not just a function of the position, it is a function of &lt;em&gt;the positions of every single particle&lt;/em&gt;. A block of material the size of your smartphone has about 10²⁵ electrons and nuclei, that’s a lot of arguments!&lt;/p&gt;
&lt;p&gt;The potential by the way is the Coulomb potential that charged particles exert on each other, so that also depends on all of the coordinates.&lt;/p&gt;
&lt;p&gt;To understand the computational complexity better it is insightful to look at how we would solve this numerically. Basically, the way most numerical methods go about solving a differential equation is to evaluate the equation itself on a certain number of points. This allows translating the differential equation into linear algebra, a matrix equation essentially of the form A x = b, where A is a matrix and b a vector that we both obtain from this procedure, and if we solve this for the vector x we get an approximation of the solution we’re after on this same set of points.&lt;/p&gt;
&lt;p&gt;How many points we need depends heavily on the details, but let’s say for simplicity the system is constrained to be on a single line, in other words space is only 1-dimensional. Let’s also restrict it to the interval between 0 and 1, and say we use K points, located at the positions x_i = i /K on the interval.&lt;/p&gt;
&lt;p&gt;Maybe K=20 could be sufficient in some very simple situation, so that doesn’t seem too bad. Remember though that every single particle has a position, and the wave function depends on all of them. So we need all &lt;em&gt;combinations&lt;/em&gt; of positions. So for a system with 10²⁵ particles that amounts to 20 &lt;em&gt;to the power&lt;/em&gt; 10²⁵ points.&lt;/p&gt;
&lt;p&gt;Another way to think about this is that if we add only a single electron to our system, we’d now need to solve the original system once for every possible location of the added electron. So in our example this would make the problem a 20 times larger, this is known as exponential complexity.&lt;/p&gt;
&lt;p&gt;These ridiculous numbers come from the combination of the exponential complexity of the problem with the already huge number of particles involved.&lt;/p&gt;
&lt;p&gt;This means that using this equation directly is only feasible for the smallest of systems, which really means practically only the hydrogen atom: a single nucleus with a single electron.&lt;/p&gt;
&lt;h2 id=&quot;approximations&quot;&gt;Approximations&lt;/h2&gt;
&lt;p&gt;Clearly then we need to do some approximations to this equation. I will illustrate conceptually a series of explanations that is very standard.&lt;/p&gt;
&lt;p&gt;The first and simplest step follows from the observation that the proton is much heavier than the electron, by a factor of about 1000. So even for hydrogen, whose nucleus is just a single proton, this is a significant factor, and for bigger cores the ratio is even larger, for example carbon contains 12 protons and neutrons (which have similar mass to protons), so their mass is about 10⁴ times that of an electron.&lt;/p&gt;
&lt;p&gt;Now heavy things tend to move more slowly than light things, this is the essence of what is called the &lt;em&gt;clamped nuclei approximation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;From the point of view of an electron, on the typical timescale at which it itself moves, the nuclei are basically standing still. So assuming we know the positions of all the nuclei, we can treat those as fixed, and we can compute the force they exert on the electrons, and solve for the electrons separately.&lt;/p&gt;
&lt;p&gt;Conversely, from the point of view of a nucleus, by the time it itself moves, all the electrons will have had enough time to settle down to their equilibrium positions, into what is called their ground state.&lt;/p&gt;
&lt;p&gt;So this allows us to in a sense decouple the electrons from the nuclei. By itself this doesn’t give a significant improvement yet, so we need to simplify each part separately.&lt;/p&gt;
&lt;h3 id=&quot;the-electrons-density-functional-theory-dft&quot;&gt;The electrons: Density Functional Theory (DFT)&lt;/h3&gt;
&lt;p&gt;First we’ll look at the electrons. The difficulty of the problem lies in the interactions between them. If they were all independent it would be a much simpler problem, but clearly that is too crude of an approximation: they exert a Coulomb force on each other, so they are not independent. There are additional quantum mechanical effects that make them even less independent.&lt;/p&gt;
&lt;p&gt;What we &lt;em&gt;can&lt;/em&gt; do is to simplify all interactions to just interactions between each individual particle and some kind of averaged out particle, this is known as the mean field approximation. That is, we imagine that all of the electrons contribute to an average electron density. This density creates some potential energy that is felt by every electron. If that sounds recursive, that’s because it is. That is the price we pay for this approximation: we get a simpler problem, but we have to solve it many times until it is self consistent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;663&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_nYX_YbciZm8swnTDX1AJ5g-0177e0e1.Dg_ExSH0_2eueTy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Adapted in simplified form from Materials Modelling using Density Functional Theory, Feliciano Giustino.&lt;/p&gt;
&lt;p&gt;The process is illustrated in the figure above. Assume we know where the nuclei are, that gives a potential coming from the nuclei which is the input to the problem. Then we make a guess for this electron density, and use that to compute another potential, caused by the electrons themselves. Now we know the equation for every electron separately, which we can then solve independently from each other. But the total density should be the sum over the individual electron densities, so we compute that. Likely we won’t get the same as the density we started with, and we have to repeat this whole procedure until we do.&lt;/p&gt;
&lt;p&gt;This approach is called Density Functional Theory (DFT).&lt;/p&gt;
&lt;p&gt;What I’ve glossed over is what this potential is that each electron feels due to the total density. This is what gives this theory its name: the density functional. A functional is just what mathematicians call a function whose argument is itself a function. In this case the potential is a function of the electron density, which itself is a function of the position (a single position this time!).&lt;/p&gt;
&lt;p&gt;The interesting situation is that this whole “approximation” is known to be &lt;em&gt;exact&lt;/em&gt;. So at this point it is not an approximation at all, we do not lose any accuracy by doing this. There is a catch however. The theory only tells us that an appropriate density functional &lt;em&gt;exists&lt;/em&gt;, that makes it exact in any situation, but it does not tell us &lt;em&gt;what&lt;/em&gt; &lt;em&gt;it is&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So the actual approximation comes in the form of a guess of the density functional. Coming up with density functionals that perform well in certain situations is a whole field of research, and there is a whole zoo of density functionals out there.&lt;/p&gt;
&lt;p&gt;In terms of the computational complexity, the bottleneck lies in solving for the individual electrons, combined with the fact that we have to keep doing this until convergence. ==The time taken scales roughly with the third power of the number of electrons==. This is not great, but still much better than the exponential scaling we started with!&lt;/p&gt;
&lt;p&gt;Concretely, in the example where we used 10 grid points, going from 100 to 101 particles made using the Schrödinger equation directly 10 times slower, whereas DFT only becomes it 3% slower. You see how important these scalings of computational complexities are.&lt;/p&gt;
&lt;p&gt;In practice, whereas the Schrödinger equation could almost only be applied to the simplest of atoms, DFT can be used not just for single atoms, but for molecules and even multiple molecules together. It is still very expensive computationally though, not something you can run on your laptop, rather on a cluster and potentially having to wait a few weeks depending on the problem. From where we started though, this is already a big step up.&lt;/p&gt;
&lt;h3 id=&quot;the-nuclei-molecular-dynamics-md&quot;&gt;The nuclei: Molecular Dynamics (MD)&lt;/h3&gt;
&lt;p&gt;Now we turn back to the nuclei. Here the most important source of approximation is their mass. We already used this to decouple them from the electrons, as their mass is much larger. We can now use this in another way.&lt;/p&gt;
&lt;p&gt;Quantum mechanics only becomes necessary to describe a system if it is very small and light. For the movement of billiard balls on a pool table, we can fortunately just use classical mechanics. Formally this is a limit of quantum mechanics, prosaically known as the classical limit. Remember that in the Schrödinger equation I said that the momentum is actually a derivative with respect to the position, and the wave function encodes the probability of finding a particle somewhere. In the classical limit, the momentum goes back to being just a number, and the probability goes away, so that a particle is just described by its position and its momentum.&lt;/p&gt;
&lt;p&gt;Perhaps surprisingly, even for something as small as a nucleus, this is a good approximation. That is true for all but the smallest nuclei, such as hydrogen.&lt;/p&gt;
&lt;p&gt;This leads to a very simple system, where we have a potential coming from the electrons in addition to the Coulomb potential between the nuclei themselves. We obtain the forces just by taking the derivative of the potential, and with these forces we can evolve the nuclei in time.&lt;/p&gt;
&lt;p&gt;This approach is called &lt;em&gt;Molecular Dynamics (MD)&lt;/em&gt;, and is illustrated in the flowchart below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;771&quot; height=&quot;393&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0xhgXYMhL1XVf6LXSjUsMg-4bf2a6ea.D64hjsCJ_uEIJK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Adapted in simplified form from Materials Modelling using Density Functional Theory, Feliciano Giustino.&lt;/p&gt;
&lt;p&gt;Here again we had to introduce an unknown potential, in this case called the &lt;em&gt;interatomic potential&lt;/em&gt;. This captures the effect of the electrons on the nuclei. And again this is a priori unknown, so we have to guess it.&lt;/p&gt;
&lt;p&gt;In this case, there is a very natural candidate. We have just discussed a way to compute the electron density for any configuration of nuclei, namely DFT. So we could do that, and then simply use the Coulomb potential coming from this electron density. This is known as &lt;em&gt;ab-initio Molecular Dynamics (aiMD)&lt;/em&gt;, because we didn’t need to make another guess on a potential.&lt;/p&gt;
&lt;p&gt;The good thing about aiMD is that it is usually very accurate. However it requires a full DFT computation for every step of MD, making it very expensive computationally.&lt;/p&gt;
&lt;p&gt;The alternative is to come up with a simple form of the interatomic potential that is very fast to evaluate, and may be accurate for certain systems. Many such guesses exist.&lt;/p&gt;
&lt;p&gt;So here the computational complexity is very strongly dependent on the interatomic potential used, the other steps are usually negligible in comparison. Less expensive potentials can be used to simulate millions of atoms, for example in large proteins or crystal structures.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;The diagram below summarizes what we have discussed.&lt;br&gt;
Through a series of physically motivated, and for many situations very accurate, approximations we have reduced the elegant but computationally intractable formulation of the Schrödinger equation into two parts: density functional theory (DFT) for the electrons and molecular dynamics (MD) for the nuclei.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1131&quot; height=&quot;894&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zwvn0X4z6_mG4zyQ4acULw-036d0626.CR6qfiv9_5UqRY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simplified illustration of the approximations done to go from quantum mechanics to Density Functional Theory (DFT) describing the electrons and Molecular Dynamics (MD) describing the nuclei. The clouds contain the ingredients that need to be specified to complete each theory.&lt;/p&gt;
&lt;p&gt;For both parts, this required the introduction of a priori unknown potentials: the density functional for DFT and the interatomic potential for MD. For both of these, a whole zoo of guesses exist, each of varying accuracy depending on the system at hand.&lt;/p&gt;
&lt;p&gt;This is where machine learning comes into the picture: rather than guessing these potentials ourselves, we can let a machine learning model learn them from data. We will discuss this in part 2 of this series.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_7i7tcw7VNt8GURTaOs1P6g-3a40b70c.3E80kelT.png" medium="image"/><author>Aron</author></item><item><title>Defining the roles of research software</title><link>https://blog2.esciencecenter.nl/posts/2023-03-21---defining-the-roles-of-research-software</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-03-21---defining-the-roles-of-research-software</guid><description>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Examples: In the biochemistry realm, software is used for modeling molecules for use in a next-gen diagnostics or therapeutics: we want to design some molecule in software with some characteristics that we can experimentally validate later. Other examples include designing and modeling medical devices, devices to help with environmental monitoring or cleanup, CAD tools, or designing new compute hardware [suggested by Jonathan Romano].&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-cf81259f.BB-6dpt2_Z1caRgP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-analyses-research-data&quot;&gt;Research software analyses research data&lt;/h2&gt;
&lt;p&gt;Research software is important for analysing research data as well. Sometimes this analysis is automated, such as data access and processing, model fitting, filtering, aggregation, and search. In other cases, the software supports and facilitates researchers in doing the analysis, for example, for qualitative data analysis. Other examples of software-supported analysis include natural language processing pipelines, data science tools (a concrete example could be &lt;a href=&quot;https://www.esmvaltool.org/&quot;&gt;ESMValTool&lt;/a&gt;), software notebooks (Jupyter), machine learning pipelines for classification and anomaly detection, etc.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-4d883c98.BN3fiPoa_ZN0wsg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-presents-research-results&quot;&gt;Research software presents research results&lt;/h2&gt;
&lt;p&gt;Research software can also be used to explain data, or to present research results. Scientific visualizations are a prime example, but so is software with the specific purpose of generating plots in research papers, or interactive visualizations on websites. Note that software is used to disseminate research in general, not only to researchers but also to a broader audience. It also is applicable for transitioning the research from academia to industrial applications. Having well-written software can help encourage the adoption of the research software in companies [suggested by Ian McInerney].&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-21d8eeff.Bk9-_V2M_WE9Cv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-assembles-or-integrates-existing-components-into-a-working-whole&quot;&gt;Research software assembles or integrates existing components into a working whole&lt;/h2&gt;
&lt;p&gt;[suggested by Mark Hoemmen] An important, but often overlooked purpose of research software is integration and automation. This includes making efficient use of infrastructure, as well as repetition and scaling of experiments or analysis. A growing number of experimental systems (more than just an instrument) need to be run simultaneously in an orchestrated manner [suggested by Ian Cosden]. The research software performing these tasks is becoming ever more complex. Software supporting workflows, for example, can help in structured and reproducible automation and repetition.&lt;/p&gt;
&lt;p&gt;Another form of integration is the coupling of different computational models, combining computational models with data-driven models (AI-based surrogate models), potentially while assimilating observational data. Consider the construction of digital twins, for example. Specifically designed research software in the form of model-coupling frameworks can facilitate this, helping with the coupling and deployment, but also for example with the propagation of uncertainty quantification between models.&lt;/p&gt;
&lt;p&gt;A third class of integration software also deserves attention: Python or shell scripts that automate things, connect components and tools, or let data flow between different executables. Note that small scripts especially often are not adequately tested and maintained, even though they are critical to reproducing scientific results.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-0660c420.CcaN3mCe_ZS2bON.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-is-infrastructure-or-an-underlying-tool&quot;&gt;Research software is infrastructure or an underlying tool&lt;/h2&gt;
&lt;p&gt;[suggested by Jed Brown] In all areas of research, there is a role for “infrastructure software,” which sometimes is not unique to research-oriented organizations, but is heavily relied upon [suggested by Jordan Perr-Sauer]. Some lower-level software was created specifically for research (i.e., known as research software,) while other software infrastructure is meant for general utility and happens to be important for research (i.e., software in research.) Examples include compilers and programming languages, generic software libraries, code repositories, data repositories, and open source software in general. (Note that this is discipline-dependent, as a compiler would likely be research software within computer science research on programming languages.) As described by the Ford Foundation: “Free, publicly available source code is the infrastructure on which all of digital society relies. It is vital to the functioning of governments, private companies, and individual lives.” (See &lt;a href=&quot;https://www.fordfoundation.org/work/learning/research-reports/roads-and-bridges-the-unseen-labor-behind-our-digital-infrastructure/&quot;&gt;Roads and Bridges: The Unseen Labor Behind Our Digital Infrastructure / Ford Foundation&lt;/a&gt;.) It is equally vital to research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-ab3a3c28.BvdY8_PI_EgGJJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-facilitates-distinctively-research-oriented-collaboration&quot;&gt;Research software facilitates distinctively research-oriented collaboration&lt;/h2&gt;
&lt;p&gt;[suggested by Lee Liming] A lot of software and services have been specifically designed to facilitate research-oriented collaboration. Although sometimes not considered research software as such, this class certainly is important in research, and deserves a mention. With research becoming more and more open, team-based, interdisciplinary, collaborative, and inclusive (e.g., citizen science,) the usage and value of software facilitating collaboration is exploding. Examples include platforms to collaborate on software (GitHub, GitLab, Stack Overflow,) papers (Overleaf, ORCID, Zotero,) data (Zenodo, HUBzero, CyVerse,) computing (SciTokens, SciGaP,) software that is employed in citizen science [suggested by Chris Erdman] and many others.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;It is clear that there are many different types of research software, fulfilling many different roles and functions. This huge variety makes it hard to come up with a good classification that captures all aspects and does justice to all the hard work done by the developers of the software. Nevertheless, we hope that we have succeeded in providing a bit more insight into the value of research software, the importance of sustaining said software, and recognizing the people involved in developing the software.&lt;/p&gt;
&lt;p&gt;You can contact us at &lt;a href=&quot;mailto:R.vanNieuwpoort@esciencecenter.nl&quot;&gt;R.vanNieuwpoort@esciencecenter.nl&lt;/a&gt; and &lt;a href=&quot;mailto:%22Daniel%20S.%20Katz%22%20%3Cd.katz%40ieee.org%3E&quot;&gt;d.katz@ieee.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Copyright © 2023 Rob van Nieuwpoort, Daniel S. Katz. Distributed under the terms of the &lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/legalcode&quot;&gt;Creative Commons Attribution 4.0 License.&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 21 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Examples: In the biochemistry realm, software is used for modeling molecules for use in a next-gen diagnostics or therapeutics: we want to design some molecule in software with some characteristics that we can experimentally validate later. Other examples include designing and modeling medical devices, devices to help with environmental monitoring or cleanup, CAD tools, or designing new compute hardware [suggested by Jonathan Romano].&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-cf81259f.BB-6dpt2_Z1caRgP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-analyses-research-data&quot;&gt;Research software analyses research data&lt;/h2&gt;
&lt;p&gt;Research software is important for analysing research data as well. Sometimes this analysis is automated, such as data access and processing, model fitting, filtering, aggregation, and search. In other cases, the software supports and facilitates researchers in doing the analysis, for example, for qualitative data analysis. Other examples of software-supported analysis include natural language processing pipelines, data science tools (a concrete example could be &lt;a href=&quot;https://www.esmvaltool.org/&quot;&gt;ESMValTool&lt;/a&gt;), software notebooks (Jupyter), machine learning pipelines for classification and anomaly detection, etc.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-4d883c98.BN3fiPoa_ZN0wsg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-presents-research-results&quot;&gt;Research software presents research results&lt;/h2&gt;
&lt;p&gt;Research software can also be used to explain data, or to present research results. Scientific visualizations are a prime example, but so is software with the specific purpose of generating plots in research papers, or interactive visualizations on websites. Note that software is used to disseminate research in general, not only to researchers but also to a broader audience. It also is applicable for transitioning the research from academia to industrial applications. Having well-written software can help encourage the adoption of the research software in companies [suggested by Ian McInerney].&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-21d8eeff.Bk9-_V2M_WE9Cv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-assembles-or-integrates-existing-components-into-a-working-whole&quot;&gt;Research software assembles or integrates existing components into a working whole&lt;/h2&gt;
&lt;p&gt;[suggested by Mark Hoemmen] An important, but often overlooked purpose of research software is integration and automation. This includes making efficient use of infrastructure, as well as repetition and scaling of experiments or analysis. A growing number of experimental systems (more than just an instrument) need to be run simultaneously in an orchestrated manner [suggested by Ian Cosden]. The research software performing these tasks is becoming ever more complex. Software supporting workflows, for example, can help in structured and reproducible automation and repetition.&lt;/p&gt;
&lt;p&gt;Another form of integration is the coupling of different computational models, combining computational models with data-driven models (AI-based surrogate models), potentially while assimilating observational data. Consider the construction of digital twins, for example. Specifically designed research software in the form of model-coupling frameworks can facilitate this, helping with the coupling and deployment, but also for example with the propagation of uncertainty quantification between models.&lt;/p&gt;
&lt;p&gt;A third class of integration software also deserves attention: Python or shell scripts that automate things, connect components and tools, or let data flow between different executables. Note that small scripts especially often are not adequately tested and maintained, even though they are critical to reproducing scientific results.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-0660c420.CcaN3mCe_ZS2bON.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-is-infrastructure-or-an-underlying-tool&quot;&gt;Research software is infrastructure or an underlying tool&lt;/h2&gt;
&lt;p&gt;[suggested by Jed Brown] In all areas of research, there is a role for “infrastructure software,” which sometimes is not unique to research-oriented organizations, but is heavily relied upon [suggested by Jordan Perr-Sauer]. Some lower-level software was created specifically for research (i.e., known as research software,) while other software infrastructure is meant for general utility and happens to be important for research (i.e., software in research.) Examples include compilers and programming languages, generic software libraries, code repositories, data repositories, and open source software in general. (Note that this is discipline-dependent, as a compiler would likely be research software within computer science research on programming languages.) As described by the Ford Foundation: “Free, publicly available source code is the infrastructure on which all of digital society relies. It is vital to the functioning of governments, private companies, and individual lives.” (See &lt;a href=&quot;https://www.fordfoundation.org/work/learning/research-reports/roads-and-bridges-the-unseen-labor-behind-our-digital-infrastructure/&quot;&gt;Roads and Bridges: The Unseen Labor Behind Our Digital Infrastructure / Ford Foundation&lt;/a&gt;.) It is equally vital to research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Defining the roles of research software&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-ab3a3c28.BvdY8_PI_EgGJJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;research-software-facilitates-distinctively-research-oriented-collaboration&quot;&gt;Research software facilitates distinctively research-oriented collaboration&lt;/h2&gt;
&lt;p&gt;[suggested by Lee Liming] A lot of software and services have been specifically designed to facilitate research-oriented collaboration. Although sometimes not considered research software as such, this class certainly is important in research, and deserves a mention. With research becoming more and more open, team-based, interdisciplinary, collaborative, and inclusive (e.g., citizen science,) the usage and value of software facilitating collaboration is exploding. Examples include platforms to collaborate on software (GitHub, GitLab, Stack Overflow,) papers (Overleaf, ORCID, Zotero,) data (Zenodo, HUBzero, CyVerse,) computing (SciTokens, SciGaP,) software that is employed in citizen science [suggested by Chris Erdman] and many others.&lt;/p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;It is clear that there are many different types of research software, fulfilling many different roles and functions. This huge variety makes it hard to come up with a good classification that captures all aspects and does justice to all the hard work done by the developers of the software. Nevertheless, we hope that we have succeeded in providing a bit more insight into the value of research software, the importance of sustaining said software, and recognizing the people involved in developing the software.&lt;/p&gt;
&lt;p&gt;You can contact us at &lt;a href=&quot;mailto:R.vanNieuwpoort@esciencecenter.nl&quot;&gt;R.vanNieuwpoort@esciencecenter.nl&lt;/a&gt; and &lt;a href=&quot;mailto:%22Daniel%20S.%20Katz%22%20%3Cd.katz%40ieee.org%3E&quot;&gt;d.katz@ieee.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Copyright © 2023 Rob van Nieuwpoort, Daniel S. Katz. Distributed under the terms of the &lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/legalcode&quot;&gt;Creative Commons Attribution 4.0 License.&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/defining-the-roles-of-research-software-cf81259f.BB-6dpt2.jpg" medium="image"/><author>Rob van Nieuwpoort</author></item><item><title>The bike and the laptop</title><link>https://blog2.esciencecenter.nl/posts/2023-03-16---the-bike-and-the-laptop</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-03-16---the-bike-and-the-laptop</guid><description>&lt;p&gt;Reflections on machines that help you&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_JHZz_VHUJPss2HCC-d181572b.BCi5rSHQ_Z1hBWrq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Cale Weaver on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;students-pay-attention-sometimes&quot;&gt;Students pay attention (sometimes)&lt;/h2&gt;
&lt;p&gt;I was 17, my face was covered in acne and my hair was (awkwardly) long. I was sitting in a high school lecture room. For some reason, I still remember the topic of the day: the efficiency of different transportation means. There was this figure in our natural sciences book comparing several of them. Something along the lines of how much energy per kilometer and person was consumed by a plane, a car, a train, …&lt;/p&gt;
&lt;p&gt;Unsurprisingly, airplanes and cars were marked as less efficient than a bus or a train. The figure seemed pretty obvious and boring, but there was something that surprised me to the point I still remember it today: a bike was more efficient than… walking!&lt;/p&gt;
&lt;p&gt;A decade later, I came across an old pal from my high school years. Our paths diverged at university: he chose a career in computer science, and I did in physics. As often happens, we ended up talking about the (arguably) good-old teenage years. To my surprise, he mentioned the bicycle figure from that day’s lecture. He told me that it was that figure that convinced him to study computer science. I was puzzled… what? how?!&lt;/p&gt;
&lt;p&gt;His reasoning was the following: &lt;em&gt;“I immediately made the link to computers. If a bike can improve your legs’ efficiency, a computer can improve your brain’s”&lt;/em&gt;. Sounds a bit far-fetched… but I cannot disagree. Furthermore, 20 years and many lines of code later I want to stretch this analogy even further.&lt;/p&gt;
&lt;h2 id=&quot;laptops-and-bikes-a-far-fetched-analogy&quot;&gt;Laptops and bikes. A far-fetched analogy&lt;/h2&gt;
&lt;p&gt;Let’s start with two obvious statements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bike can help you move faster and more efficiently than you would achieve walking or running.&lt;/li&gt;
&lt;li&gt;A laptop (or any computer) can perform calculations and manage information in ways your brain cannot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But as Uncle Ben said to Peter Parker: &lt;em&gt;“with great power comes great responsibility”.&lt;/em&gt; I mean… superpowers come with their own dangers and disadvantages. For instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bike can increase your chances of getting involved in an accident, or, less dramatically, hurt your knees if you don’t properly adjust the saddle.&lt;/li&gt;
&lt;li&gt;A laptop can flood your brain with distractions and multitasking to the point of paralyzing your workflow. Less dramatically, you can use it in a way so inefficient that it just doesn’t scale, turning your tasks into a painful experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is another obvious, yet subtler similarity: both a bike and a laptop require learning how to use them. I remember very well how I learned to ride my bike as a kid: by driving in circles inside a parking lot with my dad running by my side. I was terrified, and he needed a lot of patience, but eventually, it worked out.&lt;/p&gt;
&lt;p&gt;Ironically, I don’t have such a clear and well-defined memory of how I learned to program and efficiently use my personal computer. Not my dad, nor anyone, seems to have been my mentor. I had to learn by myself. Too often, I had these &lt;em&gt;“Eureka”&lt;/em&gt; moments… shortly followed by a &lt;em&gt;“how in the world has nobody told me about this before?”.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;my-eureka-moments&quot;&gt;My “Eureka” moments&lt;/h2&gt;
&lt;p&gt;If my computer had been a bike, those &lt;em&gt;“Eureka”&lt;/em&gt; moments felt like discovering I had been riding it backward for years. Let me share some of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up an environment that works for you, that helps you keep focused and minimizes the time searching for information, maps to adapting the bike saddle to your length.&lt;/li&gt;
&lt;li&gt;Learning how to debug is like learning how to fix a punctured tire or a loose chain.&lt;/li&gt;
&lt;li&gt;Starting using version control is like installing a GPS holder on your bike. Now you know where you come from, and also where are you going!&lt;/li&gt;
&lt;li&gt;Getting started with unit tests is like learning, sometimes the hard way, that it is a good idea to wear a helmet if you are race-biking.&lt;/li&gt;
&lt;li&gt;Incorporating multiple best practices together, such as unit tests, linting, etc… is like discovering that your bike has different gears and you don’t need to suffer that much every time you want to climb a slope.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know. Laptops and bikes. A bit of an odd analogy but… what did you expect? After all, this is a Dutch Software center.&lt;/p&gt;
&lt;p&gt;PS: are you interested in experiencing some of those &lt;em&gt;“Eureka”&lt;/em&gt; moments? Take a look at our &lt;strong&gt;free&lt;/strong&gt; &lt;a href=&quot;https://www.esciencecenter.nl/training-materials/&quot;&gt;training materials&lt;/a&gt; and courses.&lt;/p&gt;</description><pubDate>Thu, 16 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Reflections on machines that help you&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_JHZz_VHUJPss2HCC-d181572b.BCi5rSHQ_Z1hBWrq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Cale Weaver on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;students-pay-attention-sometimes&quot;&gt;Students pay attention (sometimes)&lt;/h2&gt;
&lt;p&gt;I was 17, my face was covered in acne and my hair was (awkwardly) long. I was sitting in a high school lecture room. For some reason, I still remember the topic of the day: the efficiency of different transportation means. There was this figure in our natural sciences book comparing several of them. Something along the lines of how much energy per kilometer and person was consumed by a plane, a car, a train, …&lt;/p&gt;
&lt;p&gt;Unsurprisingly, airplanes and cars were marked as less efficient than a bus or a train. The figure seemed pretty obvious and boring, but there was something that surprised me to the point I still remember it today: a bike was more efficient than… walking!&lt;/p&gt;
&lt;p&gt;A decade later, I came across an old pal from my high school years. Our paths diverged at university: he chose a career in computer science, and I did in physics. As often happens, we ended up talking about the (arguably) good-old teenage years. To my surprise, he mentioned the bicycle figure from that day’s lecture. He told me that it was that figure that convinced him to study computer science. I was puzzled… what? how?!&lt;/p&gt;
&lt;p&gt;His reasoning was the following: &lt;em&gt;“I immediately made the link to computers. If a bike can improve your legs’ efficiency, a computer can improve your brain’s”&lt;/em&gt;. Sounds a bit far-fetched… but I cannot disagree. Furthermore, 20 years and many lines of code later I want to stretch this analogy even further.&lt;/p&gt;
&lt;h2 id=&quot;laptops-and-bikes-a-far-fetched-analogy&quot;&gt;Laptops and bikes. A far-fetched analogy&lt;/h2&gt;
&lt;p&gt;Let’s start with two obvious statements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bike can help you move faster and more efficiently than you would achieve walking or running.&lt;/li&gt;
&lt;li&gt;A laptop (or any computer) can perform calculations and manage information in ways your brain cannot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But as Uncle Ben said to Peter Parker: &lt;em&gt;“with great power comes great responsibility”.&lt;/em&gt; I mean… superpowers come with their own dangers and disadvantages. For instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bike can increase your chances of getting involved in an accident, or, less dramatically, hurt your knees if you don’t properly adjust the saddle.&lt;/li&gt;
&lt;li&gt;A laptop can flood your brain with distractions and multitasking to the point of paralyzing your workflow. Less dramatically, you can use it in a way so inefficient that it just doesn’t scale, turning your tasks into a painful experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is another obvious, yet subtler similarity: both a bike and a laptop require learning how to use them. I remember very well how I learned to ride my bike as a kid: by driving in circles inside a parking lot with my dad running by my side. I was terrified, and he needed a lot of patience, but eventually, it worked out.&lt;/p&gt;
&lt;p&gt;Ironically, I don’t have such a clear and well-defined memory of how I learned to program and efficiently use my personal computer. Not my dad, nor anyone, seems to have been my mentor. I had to learn by myself. Too often, I had these &lt;em&gt;“Eureka”&lt;/em&gt; moments… shortly followed by a &lt;em&gt;“how in the world has nobody told me about this before?”.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;my-eureka-moments&quot;&gt;My “Eureka” moments&lt;/h2&gt;
&lt;p&gt;If my computer had been a bike, those &lt;em&gt;“Eureka”&lt;/em&gt; moments felt like discovering I had been riding it backward for years. Let me share some of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up an environment that works for you, that helps you keep focused and minimizes the time searching for information, maps to adapting the bike saddle to your length.&lt;/li&gt;
&lt;li&gt;Learning how to debug is like learning how to fix a punctured tire or a loose chain.&lt;/li&gt;
&lt;li&gt;Starting using version control is like installing a GPS holder on your bike. Now you know where you come from, and also where are you going!&lt;/li&gt;
&lt;li&gt;Getting started with unit tests is like learning, sometimes the hard way, that it is a good idea to wear a helmet if you are race-biking.&lt;/li&gt;
&lt;li&gt;Incorporating multiple best practices together, such as unit tests, linting, etc… is like discovering that your bike has different gears and you don’t need to suffer that much every time you want to climb a slope.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know. Laptops and bikes. A bit of an odd analogy but… what did you expect? After all, this is a Dutch Software center.&lt;/p&gt;
&lt;p&gt;PS: are you interested in experiencing some of those &lt;em&gt;“Eureka”&lt;/em&gt; moments? Take a look at our &lt;strong&gt;free&lt;/strong&gt; &lt;a href=&quot;https://www.esciencecenter.nl/training-materials/&quot;&gt;training materials&lt;/a&gt; and courses.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_JHZz_VHUJPss2HCC-d181572b.BCi5rSHQ.webp" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>eWaterCycle: Anecdotes of a FAIR expedition</title><link>https://blog2.esciencecenter.nl/posts/2023-03-09---ewatercycle-anecdotes-of-a-fair-expedition</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-03-09---ewatercycle-anecdotes-of-a-fair-expedition</guid><description>&lt;p&gt;The journey of a group of hydrologists and research software engineers after FAIRer research software.&lt;/p&gt;
&lt;h2 id=&quot;a-grand-challenge&quot;&gt;A grand challenge&lt;/h2&gt;
&lt;p&gt;This story begins in April, 2019. A group of hydrologists and research software engineers had &lt;a href=&quot;https://www.lorentzcenter.nl/fair-hydrological-models-automated-comparisons-using-escience-tools.html&quot;&gt;gathered in Leiden&lt;/a&gt; to discuss one of the grand challenges in contemporary research: &lt;em&gt;how to make our scientific endeavors reproducible and easier to reuse?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The problem was obvious. Hydrological modeling studies had grown complex. So complex, in fact, that it was virtually impossible to reproduce them from scratch. The only way to keep up was to maintain your own virtual research environment, with your own model, your own copy of input data, and your own computational facilities.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VVhO3G5VtX4HqlFP6LaJvQ-1f1f952a.eX_J8oUt_Z1p0soh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An unFAIR landscape: silo structure prohibits the exchange of models and their input/output data&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note: a characteristic figure in hydrological modeling studies is a hydrograph. This chart displays river discharge over time. To produce it, you simulate how the precipitation over a certain region propagates through the landscape: seeping into the soils, collecting into rivers, and flowing towards the sea. Hydrographs provide insight in the hydrology of a certain area and can serve to evaluate (and compare) the quality of your simulations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Despite the recent push towards more openly sharing datasets and model source code, this had minimal effect. Even with access to the source code, it remained difficult to compile each others’ models. And because modeling choices had diverged, it was not straightforward to swap out components or input datasets, or simply compare outputs of different models. Something had to change.&lt;/p&gt;
&lt;p&gt;A few years earlier, a set of &lt;a href=&quot;https://www.go-fair.org/fair-principles/&quot;&gt;“FAIR” principles&lt;/a&gt; had been formulated with the ultimate goal of making scientific datasets &lt;em&gt;Findable, Accessible, Interoperable, and Reusable&lt;/em&gt;. Intuitively, these concepts could be applied to other aspects of the research process as well. It was the right idea at the right time. Thus &lt;a href=&quot;https://www.lorentzcenter.nl/fair-hydrological-models-automated-comparisons-using-escience-tools.html&quot;&gt;the workshop in Leiden&lt;/a&gt; marked the start of our FAIR expedition.&lt;/p&gt;
&lt;h2 id=&quot;fair-models&quot;&gt;FAIR models&lt;/h2&gt;
&lt;p&gt;The first uncharted territory was that of models, the core substance of every modeling study. Hydrological models come in many flavours. They differ in the physical processes they include or in the way in which they describe these processes mathematically. They use different methods to discretize the equations, and different programming languages to implement them. How could such diversity ever be more FAIR?&lt;/p&gt;
&lt;p&gt;We found there was an interesting initiative from Boulder, Colorado: the &lt;a href=&quot;https://csdms.colorado.edu/wiki/BMI&quot;&gt;&lt;em&gt;Basic Model Interface&lt;/em&gt;&lt;/a&gt; (BMI). Even if models work differently under the hood, we could standardize the way users interact with them. Such a familiar interface would make it easier to reuse and exchange each others’ models.&lt;/p&gt;
&lt;p&gt;At that time, this standard had not been broadly embraced. But we were ambitious and we wanted to set an example of FAIR scientific conduct. So we decided to complement the participating models with a BMI. To top it off, we packaged them in Docker containers and made software to use them in a Python scripting environment.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CO5kblmYtR5qGYAcvuIbHg-3a474f0c.CybOecgc_ZX6AYk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Different models, but to the user they look the same. We decided to embrace Basic Model Interface (BMI).&lt;/p&gt;
&lt;h2 id=&quot;fair-forcing-data&quot;&gt;FAIR forcing data&lt;/h2&gt;
&lt;p&gt;Next, we entered the realm of forcing data: the weather that’s fed into the models. Here we discovered a very good standard with the only downside that it didn’t quite fit. Generations of coordinated climate research programmes had established conventions known as &lt;a href=&quot;https://cfconventions.org/&quot;&gt;CF&lt;/a&gt; and &lt;a href=&quot;https://pcmdi.llnl.gov/software/cmorTable/index.html&quot;&gt;CMOR&lt;/a&gt;. They describe how climate model output should be stored, including variable names, filename patterns, file formats, units, et cetera.&lt;/p&gt;
&lt;p&gt;There was also this software called &lt;a href=&quot;https://docs.esmvaltool.org/en/latest/&quot;&gt;ESMValTool&lt;/a&gt; that made working with these datasets more FAIR. You describe your workflow in relatively plain language, and the software takes care of finding the data and executing the specified tasks, such as cropping out a specific area. What’s great is that you can easily share your “recipes” so others can repeat and build upon your work.&lt;/p&gt;
&lt;p&gt;Another great aspect of ESMValTool is its extensibility. By writing so-called &lt;em&gt;CMORizers&lt;/em&gt;, we could “teach” the software to also understand the other datasets we wanted to support. At the other end of the workflow, we could write custom code snippets to incorporate model-specific quirks, such as deviating file formats. This allowed us to adopt the existing standards and software for our FAIR hydrological forcing module.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pCv3lwGmPzeENax9hIhuww-3a4f874f.GGg5g29G_hkEqR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;ESMValTool’s extensibility allowed us to adopt it for our FAIR hydrological forcing data module.&lt;/p&gt;
&lt;h2 id=&quot;fair-parameter-sets&quot;&gt;FAIR parameter sets?!&lt;/h2&gt;
&lt;p&gt;So far, our journey had been quite a feat. We’d seen adopting a standard even if it wasn’t widespread, and being pragmatic if it didn’t quite fit. But what if there is no suitable standard?&lt;/p&gt;
&lt;p&gt;We would soon discover it as we set foot in the land of parameter sets: home to all kinds of maps, from land use, soil types, elevation, you name it. We had envisioned and half-expected something similar to ESMValTool. But our disappointment grew quickly. Apparently, there was no clear authoritative source of parameter sets. No controlled vocabulary, a wild growth of file formats and software to manipulate them, and no consensus on what to use in hydrological models. We felt disoriented and washed out.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PKcxGe1AcIoAu1_Wf44XAw-561d6116.29N-g9by_Z1g83p1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;By imagining how we would use a standard if there had been one, we were able to “pretend” it exists.&lt;/p&gt;
&lt;p&gt;So we entered upon a game trail. Out of the control and out of time, we headed straight toward our goal: being able to load parameter sets from within our unified modeling environment. We quickly collected example parameter sets for our set of models and dreamed up a minimal set of metadata to describe them: a name, a directory path, the name of a configuration file, and the name of the model for which it was to be used. That was all we needed to load an existing parameter set that we had magically obtained. We added a DOI field, empty for now, so we could eventually publish the datasets and retrieve them again. FAIR enough.&lt;/p&gt;
&lt;h2 id=&quot;a-fair-platform&quot;&gt;A FAIR platform&lt;/h2&gt;
&lt;p&gt;Anecdotes are nice, but experience is nicer. To help you get started, we collected our models, forcing data, parameter sets, and software stack on a dedicated platform. Even if all these components are more FAIR than they’ve ever been, it’s still a bit of work to collect and configure all that. Clearly, we haven’t yet reached transcendence.&lt;/p&gt;
&lt;p&gt;The eWaterCycle demo platform gives a taste of what FAIR can bring in terms of user experience. Simply visit the URL, log in with your credentials, and enter a JupyterLab environment that is ready to go. On top of it, we build a graphical explorer where you can set up a basic experiment with a few clicks — a corresponding notebook will be generated and you can start modeling right away. Notebooks are great for exploratory research and disseminating experiments. Also, there are nice tools to help with things like auto-formatting and version control.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-2EFy2k5Gwj7OXMkZgwQGg-957d5fa9.DjOcac-q_ZM41jT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A dedicated platform makes all of its components more FAIR and helps to show the merits of FAIR&lt;/p&gt;
&lt;p&gt;While the platform is not necessarily FAIR in itself, we find that it greatly enhances the FAIRness of its components. Technical aspects are hidden from the users, so they can focus on conducting experiments. Models and parameter sets can easily be discovered and used. Our guidelines for adding new models or parameter sets are like a step-by-step guide to making them (more) FAIR.&lt;/p&gt;
&lt;p&gt;With eWaterCycle we hope to inspire a new paradigm for conducting hydrological modeling studies. The flowchart draws our FAIR journey in retrospect. It contains valuable insights, but it is by no means an all-encompassing wisdom chart. Now it is time for your expedition.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6MXyXLQhvkjN7PL6Jp4gcw-79a28e46.DabdNPLv_Z2hClb9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our FAIR journey in retrospect (not an all-encompassing wisdom chart)&lt;/p&gt;
&lt;p&gt;For more information on eWaterCycle, see the &lt;a href=&quot;https://doi.org/10.5194/gmd-15-5371-2022&quot;&gt;publication in Geoscientific Model Development&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 09 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The journey of a group of hydrologists and research software engineers after FAIRer research software.&lt;/p&gt;
&lt;h2 id=&quot;a-grand-challenge&quot;&gt;A grand challenge&lt;/h2&gt;
&lt;p&gt;This story begins in April, 2019. A group of hydrologists and research software engineers had &lt;a href=&quot;https://www.lorentzcenter.nl/fair-hydrological-models-automated-comparisons-using-escience-tools.html&quot;&gt;gathered in Leiden&lt;/a&gt; to discuss one of the grand challenges in contemporary research: &lt;em&gt;how to make our scientific endeavors reproducible and easier to reuse?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The problem was obvious. Hydrological modeling studies had grown complex. So complex, in fact, that it was virtually impossible to reproduce them from scratch. The only way to keep up was to maintain your own virtual research environment, with your own model, your own copy of input data, and your own computational facilities.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VVhO3G5VtX4HqlFP6LaJvQ-1f1f952a.eX_J8oUt_Z1p0soh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An unFAIR landscape: silo structure prohibits the exchange of models and their input/output data&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Side note: a characteristic figure in hydrological modeling studies is a hydrograph. This chart displays river discharge over time. To produce it, you simulate how the precipitation over a certain region propagates through the landscape: seeping into the soils, collecting into rivers, and flowing towards the sea. Hydrographs provide insight in the hydrology of a certain area and can serve to evaluate (and compare) the quality of your simulations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Despite the recent push towards more openly sharing datasets and model source code, this had minimal effect. Even with access to the source code, it remained difficult to compile each others’ models. And because modeling choices had diverged, it was not straightforward to swap out components or input datasets, or simply compare outputs of different models. Something had to change.&lt;/p&gt;
&lt;p&gt;A few years earlier, a set of &lt;a href=&quot;https://www.go-fair.org/fair-principles/&quot;&gt;“FAIR” principles&lt;/a&gt; had been formulated with the ultimate goal of making scientific datasets &lt;em&gt;Findable, Accessible, Interoperable, and Reusable&lt;/em&gt;. Intuitively, these concepts could be applied to other aspects of the research process as well. It was the right idea at the right time. Thus &lt;a href=&quot;https://www.lorentzcenter.nl/fair-hydrological-models-automated-comparisons-using-escience-tools.html&quot;&gt;the workshop in Leiden&lt;/a&gt; marked the start of our FAIR expedition.&lt;/p&gt;
&lt;h2 id=&quot;fair-models&quot;&gt;FAIR models&lt;/h2&gt;
&lt;p&gt;The first uncharted territory was that of models, the core substance of every modeling study. Hydrological models come in many flavours. They differ in the physical processes they include or in the way in which they describe these processes mathematically. They use different methods to discretize the equations, and different programming languages to implement them. How could such diversity ever be more FAIR?&lt;/p&gt;
&lt;p&gt;We found there was an interesting initiative from Boulder, Colorado: the &lt;a href=&quot;https://csdms.colorado.edu/wiki/BMI&quot;&gt;&lt;em&gt;Basic Model Interface&lt;/em&gt;&lt;/a&gt; (BMI). Even if models work differently under the hood, we could standardize the way users interact with them. Such a familiar interface would make it easier to reuse and exchange each others’ models.&lt;/p&gt;
&lt;p&gt;At that time, this standard had not been broadly embraced. But we were ambitious and we wanted to set an example of FAIR scientific conduct. So we decided to complement the participating models with a BMI. To top it off, we packaged them in Docker containers and made software to use them in a Python scripting environment.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CO5kblmYtR5qGYAcvuIbHg-3a474f0c.CybOecgc_ZX6AYk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Different models, but to the user they look the same. We decided to embrace Basic Model Interface (BMI).&lt;/p&gt;
&lt;h2 id=&quot;fair-forcing-data&quot;&gt;FAIR forcing data&lt;/h2&gt;
&lt;p&gt;Next, we entered the realm of forcing data: the weather that’s fed into the models. Here we discovered a very good standard with the only downside that it didn’t quite fit. Generations of coordinated climate research programmes had established conventions known as &lt;a href=&quot;https://cfconventions.org/&quot;&gt;CF&lt;/a&gt; and &lt;a href=&quot;https://pcmdi.llnl.gov/software/cmorTable/index.html&quot;&gt;CMOR&lt;/a&gt;. They describe how climate model output should be stored, including variable names, filename patterns, file formats, units, et cetera.&lt;/p&gt;
&lt;p&gt;There was also this software called &lt;a href=&quot;https://docs.esmvaltool.org/en/latest/&quot;&gt;ESMValTool&lt;/a&gt; that made working with these datasets more FAIR. You describe your workflow in relatively plain language, and the software takes care of finding the data and executing the specified tasks, such as cropping out a specific area. What’s great is that you can easily share your “recipes” so others can repeat and build upon your work.&lt;/p&gt;
&lt;p&gt;Another great aspect of ESMValTool is its extensibility. By writing so-called &lt;em&gt;CMORizers&lt;/em&gt;, we could “teach” the software to also understand the other datasets we wanted to support. At the other end of the workflow, we could write custom code snippets to incorporate model-specific quirks, such as deviating file formats. This allowed us to adopt the existing standards and software for our FAIR hydrological forcing module.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pCv3lwGmPzeENax9hIhuww-3a4f874f.GGg5g29G_hkEqR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;ESMValTool’s extensibility allowed us to adopt it for our FAIR hydrological forcing data module.&lt;/p&gt;
&lt;h2 id=&quot;fair-parameter-sets&quot;&gt;FAIR parameter sets?!&lt;/h2&gt;
&lt;p&gt;So far, our journey had been quite a feat. We’d seen adopting a standard even if it wasn’t widespread, and being pragmatic if it didn’t quite fit. But what if there is no suitable standard?&lt;/p&gt;
&lt;p&gt;We would soon discover it as we set foot in the land of parameter sets: home to all kinds of maps, from land use, soil types, elevation, you name it. We had envisioned and half-expected something similar to ESMValTool. But our disappointment grew quickly. Apparently, there was no clear authoritative source of parameter sets. No controlled vocabulary, a wild growth of file formats and software to manipulate them, and no consensus on what to use in hydrological models. We felt disoriented and washed out.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PKcxGe1AcIoAu1_Wf44XAw-561d6116.29N-g9by_Z1g83p1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;By imagining how we would use a standard if there had been one, we were able to “pretend” it exists.&lt;/p&gt;
&lt;p&gt;So we entered upon a game trail. Out of the control and out of time, we headed straight toward our goal: being able to load parameter sets from within our unified modeling environment. We quickly collected example parameter sets for our set of models and dreamed up a minimal set of metadata to describe them: a name, a directory path, the name of a configuration file, and the name of the model for which it was to be used. That was all we needed to load an existing parameter set that we had magically obtained. We added a DOI field, empty for now, so we could eventually publish the datasets and retrieve them again. FAIR enough.&lt;/p&gt;
&lt;h2 id=&quot;a-fair-platform&quot;&gt;A FAIR platform&lt;/h2&gt;
&lt;p&gt;Anecdotes are nice, but experience is nicer. To help you get started, we collected our models, forcing data, parameter sets, and software stack on a dedicated platform. Even if all these components are more FAIR than they’ve ever been, it’s still a bit of work to collect and configure all that. Clearly, we haven’t yet reached transcendence.&lt;/p&gt;
&lt;p&gt;The eWaterCycle demo platform gives a taste of what FAIR can bring in terms of user experience. Simply visit the URL, log in with your credentials, and enter a JupyterLab environment that is ready to go. On top of it, we build a graphical explorer where you can set up a basic experiment with a few clicks — a corresponding notebook will be generated and you can start modeling right away. Notebooks are great for exploratory research and disseminating experiments. Also, there are nice tools to help with things like auto-formatting and version control.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-2EFy2k5Gwj7OXMkZgwQGg-957d5fa9.DjOcac-q_ZM41jT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A dedicated platform makes all of its components more FAIR and helps to show the merits of FAIR&lt;/p&gt;
&lt;p&gt;While the platform is not necessarily FAIR in itself, we find that it greatly enhances the FAIRness of its components. Technical aspects are hidden from the users, so they can focus on conducting experiments. Models and parameter sets can easily be discovered and used. Our guidelines for adding new models or parameter sets are like a step-by-step guide to making them (more) FAIR.&lt;/p&gt;
&lt;p&gt;With eWaterCycle we hope to inspire a new paradigm for conducting hydrological modeling studies. The flowchart draws our FAIR journey in retrospect. It contains valuable insights, but it is by no means an all-encompassing wisdom chart. Now it is time for your expedition.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6MXyXLQhvkjN7PL6Jp4gcw-79a28e46.DabdNPLv_Z2hClb9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our FAIR journey in retrospect (not an all-encompassing wisdom chart)&lt;/p&gt;
&lt;p&gt;For more information on eWaterCycle, see the &lt;a href=&quot;https://doi.org/10.5194/gmd-15-5371-2022&quot;&gt;publication in Geoscientific Model Development&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_VVhO3G5VtX4HqlFP6LaJvQ-1f1f952a.eX_J8oUt.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Minds for Mobile Agents: speeding up social distancing simulations</title><link>https://blog2.esciencecenter.nl/posts/2023-03-02---minds-for-mobile-agents-speeding-up-social-distancing-simula</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-03-02---minds-for-mobile-agents-speeding-up-social-distancing-simula</guid><description>&lt;p&gt;&lt;em&gt;This blog post is written by University of Amsterdam researchers Charlotte Tanis and Andrew Heathcote, who participated in the Small-Scale Initiative for Software Performance Optimization. Their team’s project: predicting the movement patterns of pedestrians, which can help governments and policy-makers in pandemics and crisis situations.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;928&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_b6gDKVX25ZdxuAHl-4d41c263.CMh6ba9d_SyxMU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Forest Simon on Unsplash&lt;/p&gt;
&lt;p&gt;During the COVID-19 pandemic, a group of researchers from the University of Amsterdam started the &lt;a href=&quot;https://dataversuscorona.com/&quot;&gt;Data vs. Corona&lt;/a&gt; initiative. Their mission: to create a community of data scientists who make their skills available in society’s battle against the coronavirus. One of the projects that emerged out of the initiative was our &lt;a href=&quot;https://www.ampl-psych.com/projects/minds-for-mobile-agents/&quot;&gt;Minds for Mobile Agents&lt;/a&gt; project. Minds for Mobile Agents uses real-life data to help governments implement effective physical distancing guidelines. In order to do so, it is key to accurately simulate, explain and predict how individuals move when going grocery shopping or visiting restaurants.&lt;/p&gt;
&lt;p&gt;Understanding how individuals move in such so-called &lt;em&gt;low to medium density settings&lt;/em&gt; has much wider applications than social distancing measures alone. Security authorities benefit from research like this too, because it helps them make realistic vulnerability assessments in crisis situations. This improves the safety and preparedness in the case of, for example, attacks on public spaces. &lt;a href=&quot;https://www.telegraaf.nl/nieuws/1822382862/supermarktproef-stoplicht-bij-ingang-paaseitjesbij-%20%20uitgang%20and%20https:/nos.nl/video/2374282-hoe-houd-je-het-beste-afstand-in-de-supermarktdat-%20%20onderzoeken-ze-in-veldhoven&quot;&gt;The elaborate media coverage&lt;/a&gt; we received in national media during our initial experiments showed that understanding and predicting pedestrian behavior in small but complex environments is a topic of great current interest.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_fAhjsTdZBGzQPQvc-92fcaac7.K954mqDK_Z2wFrtw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Franki Chamaki on Unsplash&lt;/p&gt;
&lt;p&gt;Our research objective is to make accurate predictions about the movement patterns of a group of individuals, which means that we need to be able to simulate the fact that individuals move around in their environment for different reasons. That is exactly what the mathematical “Predictive Pedestrian” model does. The model simulates a set of pedestrians in a supermarket or restaurant and predicts each simulated pedestrian’s step choices. The choices a simulated pedestrian makes are based on predictions that simulated pedestrian would make about the behaviour of other pedestrians in the space. Each agent’s “mind” can be flexibly specified using parameters that have clear psychological interpretations, making the behaviour of the model explainable.&lt;/p&gt;
&lt;p&gt;Our team incorporated complex series of goals and individual differences in the way in which pedestrians move around and interact with each other according to the model (see &lt;a href=&quot;https://www.ampl-psych.com/projects/minds-for-mobile-agents/&quot;&gt;here&lt;/a&gt; for background and illustrations). As you may be able to imagine, the computational cost associated with these simulations is high. Our approach requires us to develop methods that can estimate the distributions of many model parameters that can characterize realistic scenarios.&lt;/p&gt;
&lt;h3 id=&quot;escience-center-support&quot;&gt;eScience Center support&lt;/h3&gt;
&lt;p&gt;We participated in the eScience Center Small-Scale Initiative (SSI) in Software Performance Optimization. The goal of our SSI project was to optimize the computational efficiency of the Predictive Pedestrian model. Our team worked together with eScience Center Research Software Engineers Eva Viviani and Malte Luken. We started off profiling the Predictive Pedestrian model code to identify computational bottlenecks. We then ported a selection of functions to &lt;a href=&quot;https://github.com/m4ma&quot;&gt;an R package we dubbed M4MA&lt;/a&gt;, and added the option to perform the associated computations in C++ through the &lt;a href=&quot;https://www.rcpp.org/&quot;&gt;Rcpp&lt;/a&gt; framework. This resulted in the code running approximately ten times faster. The M4MA package puts us one step closer to realizing the promise of the Predictive Pedestrian model: to quantitatively characterize and simulate pedestrian behaviour in a wide range of scenarios in real time.&lt;/p&gt;
&lt;p&gt;In the next step of the project, the M4MA package will be used to analyse the results of experiments in various settings using ultra-wide band technology to precisely measure the locations of real pedestrians, and to guide the design of new experiments. The experimental results will be used to estimate the model parameters, enabling the first thorough investigation of when individual differences in pedestrian behavior matter and how they change across different scenarios. Models that are calibrated for these environments offer exciting possibilities: they may result in more accurate simulations of how people move around, and can provide meaningful data that can be used to make changes without needing expensive calibration studies in every case. This in turn facilitates policy advice and the better design of environments that achieve a wide variety of goals related to, for example, safety (e.g., maintaining physical distance) and commerce (e.g., encouraging smooth flows through targeted areas).&lt;/p&gt;
&lt;p&gt;Edited by &lt;em&gt;Lieke de Boer.&lt;/em&gt; Thanks to &lt;em&gt;Eva Viviani&lt;/em&gt; for fact checking.&lt;/p&gt;</description><pubDate>Thu, 02 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This blog post is written by University of Amsterdam researchers Charlotte Tanis and Andrew Heathcote, who participated in the Small-Scale Initiative for Software Performance Optimization. Their team’s project: predicting the movement patterns of pedestrians, which can help governments and policy-makers in pandemics and crisis situations.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;928&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_b6gDKVX25ZdxuAHl-4d41c263.CMh6ba9d_SyxMU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Forest Simon on Unsplash&lt;/p&gt;
&lt;p&gt;During the COVID-19 pandemic, a group of researchers from the University of Amsterdam started the &lt;a href=&quot;https://dataversuscorona.com/&quot;&gt;Data vs. Corona&lt;/a&gt; initiative. Their mission: to create a community of data scientists who make their skills available in society’s battle against the coronavirus. One of the projects that emerged out of the initiative was our &lt;a href=&quot;https://www.ampl-psych.com/projects/minds-for-mobile-agents/&quot;&gt;Minds for Mobile Agents&lt;/a&gt; project. Minds for Mobile Agents uses real-life data to help governments implement effective physical distancing guidelines. In order to do so, it is key to accurately simulate, explain and predict how individuals move when going grocery shopping or visiting restaurants.&lt;/p&gt;
&lt;p&gt;Understanding how individuals move in such so-called &lt;em&gt;low to medium density settings&lt;/em&gt; has much wider applications than social distancing measures alone. Security authorities benefit from research like this too, because it helps them make realistic vulnerability assessments in crisis situations. This improves the safety and preparedness in the case of, for example, attacks on public spaces. &lt;a href=&quot;https://www.telegraaf.nl/nieuws/1822382862/supermarktproef-stoplicht-bij-ingang-paaseitjesbij-%20%20uitgang%20and%20https:/nos.nl/video/2374282-hoe-houd-je-het-beste-afstand-in-de-supermarktdat-%20%20onderzoeken-ze-in-veldhoven&quot;&gt;The elaborate media coverage&lt;/a&gt; we received in national media during our initial experiments showed that understanding and predicting pedestrian behavior in small but complex environments is a topic of great current interest.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_fAhjsTdZBGzQPQvc-92fcaac7.K954mqDK_Z2wFrtw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Franki Chamaki on Unsplash&lt;/p&gt;
&lt;p&gt;Our research objective is to make accurate predictions about the movement patterns of a group of individuals, which means that we need to be able to simulate the fact that individuals move around in their environment for different reasons. That is exactly what the mathematical “Predictive Pedestrian” model does. The model simulates a set of pedestrians in a supermarket or restaurant and predicts each simulated pedestrian’s step choices. The choices a simulated pedestrian makes are based on predictions that simulated pedestrian would make about the behaviour of other pedestrians in the space. Each agent’s “mind” can be flexibly specified using parameters that have clear psychological interpretations, making the behaviour of the model explainable.&lt;/p&gt;
&lt;p&gt;Our team incorporated complex series of goals and individual differences in the way in which pedestrians move around and interact with each other according to the model (see &lt;a href=&quot;https://www.ampl-psych.com/projects/minds-for-mobile-agents/&quot;&gt;here&lt;/a&gt; for background and illustrations). As you may be able to imagine, the computational cost associated with these simulations is high. Our approach requires us to develop methods that can estimate the distributions of many model parameters that can characterize realistic scenarios.&lt;/p&gt;
&lt;h3 id=&quot;escience-center-support&quot;&gt;eScience Center support&lt;/h3&gt;
&lt;p&gt;We participated in the eScience Center Small-Scale Initiative (SSI) in Software Performance Optimization. The goal of our SSI project was to optimize the computational efficiency of the Predictive Pedestrian model. Our team worked together with eScience Center Research Software Engineers Eva Viviani and Malte Luken. We started off profiling the Predictive Pedestrian model code to identify computational bottlenecks. We then ported a selection of functions to &lt;a href=&quot;https://github.com/m4ma&quot;&gt;an R package we dubbed M4MA&lt;/a&gt;, and added the option to perform the associated computations in C++ through the &lt;a href=&quot;https://www.rcpp.org/&quot;&gt;Rcpp&lt;/a&gt; framework. This resulted in the code running approximately ten times faster. The M4MA package puts us one step closer to realizing the promise of the Predictive Pedestrian model: to quantitatively characterize and simulate pedestrian behaviour in a wide range of scenarios in real time.&lt;/p&gt;
&lt;p&gt;In the next step of the project, the M4MA package will be used to analyse the results of experiments in various settings using ultra-wide band technology to precisely measure the locations of real pedestrians, and to guide the design of new experiments. The experimental results will be used to estimate the model parameters, enabling the first thorough investigation of when individual differences in pedestrian behavior matter and how they change across different scenarios. Models that are calibrated for these environments offer exciting possibilities: they may result in more accurate simulations of how people move around, and can provide meaningful data that can be used to make changes without needing expensive calibration studies in every case. This in turn facilitates policy advice and the better design of environments that achieve a wide variety of goals related to, for example, safety (e.g., maintaining physical distance) and commerce (e.g., encouraging smooth flows through targeted areas).&lt;/p&gt;
&lt;p&gt;Edited by &lt;em&gt;Lieke de Boer.&lt;/em&gt; Thanks to &lt;em&gt;Eva Viviani&lt;/em&gt; for fact checking.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_b6gDKVX25ZdxuAHl-4d41c263.CMh6ba9d.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>The hidden dangers of using XAI carelessly</title><link>https://blog2.esciencecenter.nl/posts/2023-02-23---the-hidden-dangers-of-using-xai-carelessly</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-02-23---the-hidden-dangers-of-using-xai-carelessly</guid><description>&lt;p&gt;&lt;em&gt;Congrats! Your ML model is finally XAI-ready. But before you start patting yourself on the back, have you pre-processed your features? If so, watch out for those SHAP values, they might have been “processed”, too&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2097&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_s3LlcenurDp-MxDA-e6102adf.BIelJepI_Z2p3GPn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mind the gap. Photo by Sammie Chaffin on Unsplash&lt;/p&gt;
&lt;p&gt;A very desirable property of machine learning models is explainability. This means being able to attribute the predictions to each input feature. SHAP (SHapley Additive exPlanations) is one of the most popular methods for getting feature importance, and it’s pretty much the state-of-the-art in explainable AI. It’s so popular because (1) it doesn’t matter what kind of model you use (random forest, SVM, neural network), (2) in certain aspects unifies other explainability methods, and (3) it has some great properties, including &lt;em&gt;additivity:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The sum of the SHAP values of each feature for a given observation gives the difference between the full model prediction and the prediction of the null model (a model without features).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a crucial property that makes SHAP believable. If the numbers from an explainability method have no physical meaning, no one is going to believe the method explains the model.&lt;/p&gt;
&lt;p&gt;Now, here’s the catch. A popular way to train high-performing neural nets is to pre-process the data (features), for example, using Principal Compenent Analysis (PCA) or whitening or log transforming or… If you’ve trained a neurals network before, you’ve probably used some kind of feature pre-processing to improve the model’s predictions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;559&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_u1Wxxn-nmbcVKzVO-a0eaa844.hMILayCi_Z109Vwk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Standardization. Photo by Philippe Krief on Unsplash&lt;/p&gt;
&lt;p&gt;But here’s the problem. When it’s time to uncover the importance of individual features with SHAP, all is good as long as you’re playing with the pre-processed features. But for SHAP to serve its purpose, it needs to show the relevance of the &lt;em&gt;original&lt;/em&gt; features. Imagine that you have pre-processed the features in a different way. That &lt;em&gt;other&lt;/em&gt; pre-processing would have led to an entirely different model, with different predictions. Different predictions mostly lead to different SHAP values.&lt;/p&gt;
&lt;p&gt;This means that in general, we can’t use the SHAP values of pre-processed features to represent the importance of the original features. (&lt;em&gt;In general&lt;/em&gt;: to be precise, specific variants of SHAP, like &lt;a href=&quot;https://arxiv.org/pdf/1908.08474.pdf&quot;&gt;BShap&lt;/a&gt;, do allow for specific &lt;em&gt;affine&lt;/em&gt; transformations of the features — like transforming Celsius to Fahrenheit — a property called &lt;em&gt;affine scale invariance.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With multi-variate transformations like PCA, the original features are even gone.&lt;/p&gt;
&lt;p&gt;You might be tempted to play with the SHAP values of the pre-processed features to get “SHAPpy” values for the original features.&lt;/p&gt;
&lt;p&gt;But what about the additivity property? Will the sum of the post-processed “SHAPpy” values of each feature for a given observation give the difference between the full model prediction and the null model prediction? Probably not.&lt;/p&gt;
&lt;p&gt;This means that the “SHAPpy” values lose their original meaning. So,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;using SHAP or XAI while pre-processing features is risky business!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Does this mean there’s something wrong with SHAP? No, not at all. The point of this post is to give you a heads up that when you pre-process features in a non-affine way, you can’t count on explainability in advance. And in reality, most of the time, features are pre-processed to get good results with training, unless you use tree-based models that don’t require pre-processing.&lt;/p&gt;
&lt;p&gt;Does this mean SHAP is at a disadvantage compared to other feature importance methods? Nope, not at all. This post didn’t even scratch the surface of the specifics of SHAP. So stay tuned, we might do a follow-up post on another method!&lt;/p&gt;
&lt;p&gt;p.s. This post was inspired by a productive discussion with the &lt;a href=&quot;http://tps.phys.tue.nl/janssen&quot;&gt;&lt;em&gt;Non-equilibrium soft matter&lt;/em&gt;&lt;/a&gt; group in Eindhoven, within a &lt;a href=&quot;https://blog.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;collaboration&lt;/a&gt; with the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to Meiert Willem Grootes, Christiaan Meijer, Candace Moore and Patrick Bos for improving the blog post!&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 23 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Congrats! Your ML model is finally XAI-ready. But before you start patting yourself on the back, have you pre-processed your features? If so, watch out for those SHAP values, they might have been “processed”, too&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2097&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_s3LlcenurDp-MxDA-e6102adf.BIelJepI_Z2p3GPn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mind the gap. Photo by Sammie Chaffin on Unsplash&lt;/p&gt;
&lt;p&gt;A very desirable property of machine learning models is explainability. This means being able to attribute the predictions to each input feature. SHAP (SHapley Additive exPlanations) is one of the most popular methods for getting feature importance, and it’s pretty much the state-of-the-art in explainable AI. It’s so popular because (1) it doesn’t matter what kind of model you use (random forest, SVM, neural network), (2) in certain aspects unifies other explainability methods, and (3) it has some great properties, including &lt;em&gt;additivity:&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The sum of the SHAP values of each feature for a given observation gives the difference between the full model prediction and the prediction of the null model (a model without features).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a crucial property that makes SHAP believable. If the numbers from an explainability method have no physical meaning, no one is going to believe the method explains the model.&lt;/p&gt;
&lt;p&gt;Now, here’s the catch. A popular way to train high-performing neural nets is to pre-process the data (features), for example, using Principal Compenent Analysis (PCA) or whitening or log transforming or… If you’ve trained a neurals network before, you’ve probably used some kind of feature pre-processing to improve the model’s predictions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;559&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_u1Wxxn-nmbcVKzVO-a0eaa844.hMILayCi_Z109Vwk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Standardization. Photo by Philippe Krief on Unsplash&lt;/p&gt;
&lt;p&gt;But here’s the problem. When it’s time to uncover the importance of individual features with SHAP, all is good as long as you’re playing with the pre-processed features. But for SHAP to serve its purpose, it needs to show the relevance of the &lt;em&gt;original&lt;/em&gt; features. Imagine that you have pre-processed the features in a different way. That &lt;em&gt;other&lt;/em&gt; pre-processing would have led to an entirely different model, with different predictions. Different predictions mostly lead to different SHAP values.&lt;/p&gt;
&lt;p&gt;This means that in general, we can’t use the SHAP values of pre-processed features to represent the importance of the original features. (&lt;em&gt;In general&lt;/em&gt;: to be precise, specific variants of SHAP, like &lt;a href=&quot;https://arxiv.org/pdf/1908.08474.pdf&quot;&gt;BShap&lt;/a&gt;, do allow for specific &lt;em&gt;affine&lt;/em&gt; transformations of the features — like transforming Celsius to Fahrenheit — a property called &lt;em&gt;affine scale invariance.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With multi-variate transformations like PCA, the original features are even gone.&lt;/p&gt;
&lt;p&gt;You might be tempted to play with the SHAP values of the pre-processed features to get “SHAPpy” values for the original features.&lt;/p&gt;
&lt;p&gt;But what about the additivity property? Will the sum of the post-processed “SHAPpy” values of each feature for a given observation give the difference between the full model prediction and the null model prediction? Probably not.&lt;/p&gt;
&lt;p&gt;This means that the “SHAPpy” values lose their original meaning. So,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;using SHAP or XAI while pre-processing features is risky business!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Does this mean there’s something wrong with SHAP? No, not at all. The point of this post is to give you a heads up that when you pre-process features in a non-affine way, you can’t count on explainability in advance. And in reality, most of the time, features are pre-processed to get good results with training, unless you use tree-based models that don’t require pre-processing.&lt;/p&gt;
&lt;p&gt;Does this mean SHAP is at a disadvantage compared to other feature importance methods? Nope, not at all. This post didn’t even scratch the surface of the specifics of SHAP. So stay tuned, we might do a follow-up post on another method!&lt;/p&gt;
&lt;p&gt;p.s. This post was inspired by a productive discussion with the &lt;a href=&quot;http://tps.phys.tue.nl/janssen&quot;&gt;&lt;em&gt;Non-equilibrium soft matter&lt;/em&gt;&lt;/a&gt; group in Eindhoven, within a &lt;a href=&quot;https://blog.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;collaboration&lt;/a&gt; with the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to Meiert Willem Grootes, Christiaan Meijer, Candace Moore and Patrick Bos for improving the blog post!&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_u1Wxxn-nmbcVKzVO-a0eaa844.hMILayCi.webp" medium="image"/><author>Sonja Georgievska</author></item><item><title>The medical chatbot will not see you now</title><link>https://blog2.esciencecenter.nl/posts/2023-02-16---the-medical-chatbot-will-not-see-you-now</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-02-16---the-medical-chatbot-will-not-see-you-now</guid><description>&lt;h2 id=&quot;dr-candace-makeda-moore-rse-and-medical-doctor-lays-out-what-she-believes-the-potential-pitfalls-and-problems-of-ai-chatbots-in-medicine-are-closed-source-discrimination-irreproducibility-and-hype&quot;&gt;Dr. Candace Makeda Moore, RSE and medical doctor, lays out what she believes the potential pitfalls and problems of AI chatbots in medicine are: closed source, discrimination, (ir)reproducibility and hype&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_iu5EgTq1-GfUgnHK-a5b4977d.CxSbe3Dz_1vKyRD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by National Cancer Institute on Unsplash&lt;/p&gt;
&lt;p&gt;In a recent conversation with other physicians on AI in healthcare, I noticed they seemed hyped up about &lt;a href=&quot;https://chat.openai.com/&quot;&gt;ChatGPT&lt;/a&gt;. In their happy enthusiasm, they sounded as if they had not thought through some of the implications of things they themselves were saying. Several of them asked many questions about how it worked. While we know ChatGPT is a large language model, it is closed-source. That means that even people like myself, who have worked with the code on healthcare-related chatbots, cannot tell you the exact mechanisms of how each part works unless they happen to work on the product itself.&lt;/p&gt;
&lt;p&gt;Many physicians today use their computers as operators, close to the way they use cars. They never open up the hood and figure out what is going on underneath. Closed source code is essentially a car where the hood has been nailed and glued shut with a legal mechanism. It doesn’t matter that most particular physicians can’t read the code behind ChatGPT. After all, no one needs programming knowledge to become a medical doctor. What really matters is that no engineer or statistician in their hospital can read closed source code either, because it’s not public.&lt;/p&gt;
&lt;p&gt;The last decades have seen a real revolution in terms of moving away from closed-source code. In our work at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center,&lt;/a&gt; we help scientific researchers create and use open code to create reproducible results. We push scientists to make both data and code available. Open-source chatbots for healthcare issues are under development in our center (like &lt;a href=&quot;https://github.com/PerfectFit-project/&quot;&gt;PerfectFit&lt;/a&gt;) and beyond. In healthcare, patient data protection is critical and in some cases the data powering algorithms needs anonymization. But in the case of a machine learning algorithm, until you can examine the code behind it, you can’t really know whether the data used to train the algorithm has been subjected to the same standards. If you deploy a closed-source product, you have to take on blind faith that it works in a way that won’t harm people.&lt;/p&gt;
&lt;p&gt;Here I must point out that it is likely that ChatGPT can harm people. The real hero to warn the public about this was Steven T. Piantadosi, a Berkeley neuroscience professor, who tweeted some fascinating results that I wish more people had seen. We may not know what is under the hood of ChatGPT, but thanks in part to Piantadosi’s prompts, we know it is capable of producing results that are racist and sexist. Less than three months ago, in December 2022, Piantadosi Tweeted ChatGPT’s response when he prompted the program to write programs about issues such as which child’s life should be saved based on their race and gender.&lt;/p&gt;
&lt;h3 id=&quot;automated-racism&quot;&gt;Automated racism&lt;/h3&gt;
&lt;p&gt;The program, if cued in a certain way, &lt;a href=&quot;https://twitter.com/spiantado/status/1599462375887114240&quot;&gt;would not suggest saving the life of a black male child, and but would suggest saving a white one&lt;/a&gt;. This &lt;a href=&quot;https://twitter.com/spiantado/status/1599462375887114240&quot;&gt;program algorithm&lt;/a&gt; was not an ironic joke or even a fluke. On prompts about race, the results were sadly expectable for someone like me who researches these issues. Sharing the results with the broader public allows everyone to see the dangers for themselves. ChatGPT is trained on a large corpus of text, gigabytes large, which clearly had some biases in it.&lt;/p&gt;
&lt;p&gt;The full conversation with ChatGPT contains more examples of ChatGPT’s biases at the time.&lt;/p&gt;
&lt;p&gt;What Piantadosi did in technical terms was a type of adversarial testing, and it is worth pointing out that it did not require him to be a computer scientist or even to write code. What I’m getting at, by pointing to Piantadosi’s academic provenance, is that even a scientist, nurse, or medical doctor with zero computer science knowledge, but perhaps some awareness of the dangers of such algorithms, could have done the same out of concern for patients. And at this point, we should all know to expect these outcomes, as countless researchers (even &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S2666521222000205&quot;&gt;including myself&lt;/a&gt;) have been working and publishing on issues like these for years.&lt;/p&gt;
&lt;p&gt;In the conversation with fellow doctors, the author of a forthcoming book on ChatGPT in healthcare declared it would get better and better. The man was an accomplished physician, but unfortunately, that does not imply someone who actually builds such systems line by line of code (specifically including the test code) and sees the results at scale. Only someone who doesn’t write the code on such systems could be so optimistic. The algorithm will get better or worse depending upon the data that it is fed, and the code that is added or removed from it. If you are counting on engineers to only do better and more careful work, you may want to consider how many software failures in healthcare come not from original products but from upgrades.&lt;/p&gt;
&lt;p&gt;To their credit, the staff over at &lt;a href=&quot;https://openai.com/&quot;&gt;OpenAI&lt;/a&gt; must be watching the internet, because they seem to have put guardrails on in terms of the exact kind of cues Piantadosi fed the algorithm. When I tested it on a recent morning, I got different results (screenshot shared below).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-f1dub97Cihvht4NPrwU7w-d0fbf5f0.u5IsbUkK_Z25Pm02.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Did I get different results based on a new algorithm, or just by chance? We can’t know. I do know it is very easy to hard-code over answers to certain questions while leaving bias in a general algorithm. I can imagine, that for legal reasons alone, anyone using ChatGPT might apply some kind of adversarial training layer on top of the closed algorithm results to eliminate racist statements.&lt;/p&gt;
&lt;p&gt;Even if this were the case, there are at least a couple more fundamental issues with the algorithm than its potential for producing racially biased answers. One issue is that the algorithm can return incorrect text about fairly obvious facts in medicine. Below is a screenshot from its response when I asked it a question about fabellae (a fabella is an accessory ossicle in the knee present in a minority of the population) in the way I thought a patient might ask it i.e. without fancy Latin orthography.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PuAvhRAwOe91akA3VkefJA-b1150312.BO04i_pB_1eg7Fl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The program returns something I consider symbolic of many of its problems. The program actually produced the correct spelling of fabellae, but got the facts wrong. Text produced can look right, and if you incorrectly attribute human qualities to the program, the program and text can seem ‘smarter’ than your average patient, but it can simultaneously not actually &lt;strong&gt;be&lt;/strong&gt; right. I guess ChatGPT won’t be replacing anatomists or radiologists (who know &lt;a href=&quot;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6075638/&quot;&gt;most of the population have zero fabellae&lt;/a&gt;) anytime soon. Some enthusiasts might argue that these little bugs could be fixed with hardcoded information about obvious facts. Even if that were possible, there are simple facts, and then there are assumptions based on the interpretation of data. For example, if I were to ask ChatGPT about the ideal diet for me to optimize my health, the answer is not truly an undebated ‘fact’ in the medical community. And here again, the machine can go in unwanted directions.&lt;/p&gt;
&lt;h3 id=&quot;reproducibility-the-scientific-dilemma-of-our-decade&quot;&gt;Reproducibility: the scientific dilemma of our decade&lt;/h3&gt;
&lt;p&gt;In my recent conversation with physicians, one marveled at how the chatbot had given two logical yet different answers to questions posed to it about a complex text. The doctor was wowed by the human and intellectual sound of the answers. In my head alarm bells were going off. If the same algorithm produces different answers at different times of the day, you have a problem with medical and scientific research, let alone medical applications. Algorithms can be programmed to look spontaneous and not reproducible, but fundamentally, many algorithms create exactly reproducible results even if they appear not to.&lt;/p&gt;
&lt;p&gt;Computers are not random, in fact, they can’t even make truly random outputs. If you actually program, you know this, as the functions used to make ‘random’ numbers rely on things like the machine time as input to pseudorandomized output. It takes a lot of work and code to make a simple algorithm, like a decision tree, not reproducible. But the more complex an algorithm is, the easier it is to get results that appear random, and not be truly reproducible in important ways. An algorithm that was trained on gigabytes of input can become pseudo-random in ways humans simply can’t comprehend, as we cannot read a corpus of gigabytes of text. Such an algorithm’s outputs can become, for our purposes, not reproducible from one patient to the next, and that is simply unacceptable in modern medicine.&lt;/p&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h3&gt;
&lt;p&gt;I am always surprised at how many of my fellow physicians seem to think algorithms fall from the sky perfect (the technical term here is automation bias). As someone who actually writes code on algorithms, I can tell you that to get a very complex large computer program that is perfect, you need a perfect group of perfect programmers (and no such thing exists). Code reflects the people who wrote it in general, and when it comes to machine learning it reflects the thought process of those people, and the people who curated the data the particular algorithm was based on.&lt;/p&gt;
&lt;p&gt;One argument for using chatbots in medicine is that they could help people who can’t access doctors. As someone who has spent time in places like Haiti and Lesvos, Greece, voluntarily practicing medicine towards humanitarian aims, this sounds appealing. But as someone whose work is to write code, I know better. There is a highly paid workforce behind complex algorithms and any medical AI system needs constant surveillance, monitoring, and upgrades. The work of ten dedicated high-level biomedical engineers and programmers isn’t necessarily any cheaper or better than that of ten physicians. Perhaps the true path forward is more physician education on such matters because in each specific situation, some combination of physicians and engineers is optimal to get the best healthcare to the most people at the lowest price.&lt;/p&gt;
&lt;p&gt;Chatbots are a tool we should embrace towards these great aims, but the hype around a closed-source product shows how far we have to go before we in medicine are truly ready to use such powerful tools.&lt;/p&gt;</description><pubDate>Thu, 16 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;dr-candace-makeda-moore-rse-and-medical-doctor-lays-out-what-she-believes-the-potential-pitfalls-and-problems-of-ai-chatbots-in-medicine-are-closed-source-discrimination-irreproducibility-and-hype&quot;&gt;Dr. Candace Makeda Moore, RSE and medical doctor, lays out what she believes the potential pitfalls and problems of AI chatbots in medicine are: closed source, discrimination, (ir)reproducibility and hype&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_iu5EgTq1-GfUgnHK-a5b4977d.CxSbe3Dz_1vKyRD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by National Cancer Institute on Unsplash&lt;/p&gt;
&lt;p&gt;In a recent conversation with other physicians on AI in healthcare, I noticed they seemed hyped up about &lt;a href=&quot;https://chat.openai.com/&quot;&gt;ChatGPT&lt;/a&gt;. In their happy enthusiasm, they sounded as if they had not thought through some of the implications of things they themselves were saying. Several of them asked many questions about how it worked. While we know ChatGPT is a large language model, it is closed-source. That means that even people like myself, who have worked with the code on healthcare-related chatbots, cannot tell you the exact mechanisms of how each part works unless they happen to work on the product itself.&lt;/p&gt;
&lt;p&gt;Many physicians today use their computers as operators, close to the way they use cars. They never open up the hood and figure out what is going on underneath. Closed source code is essentially a car where the hood has been nailed and glued shut with a legal mechanism. It doesn’t matter that most particular physicians can’t read the code behind ChatGPT. After all, no one needs programming knowledge to become a medical doctor. What really matters is that no engineer or statistician in their hospital can read closed source code either, because it’s not public.&lt;/p&gt;
&lt;p&gt;The last decades have seen a real revolution in terms of moving away from closed-source code. In our work at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center,&lt;/a&gt; we help scientific researchers create and use open code to create reproducible results. We push scientists to make both data and code available. Open-source chatbots for healthcare issues are under development in our center (like &lt;a href=&quot;https://github.com/PerfectFit-project/&quot;&gt;PerfectFit&lt;/a&gt;) and beyond. In healthcare, patient data protection is critical and in some cases the data powering algorithms needs anonymization. But in the case of a machine learning algorithm, until you can examine the code behind it, you can’t really know whether the data used to train the algorithm has been subjected to the same standards. If you deploy a closed-source product, you have to take on blind faith that it works in a way that won’t harm people.&lt;/p&gt;
&lt;p&gt;Here I must point out that it is likely that ChatGPT can harm people. The real hero to warn the public about this was Steven T. Piantadosi, a Berkeley neuroscience professor, who tweeted some fascinating results that I wish more people had seen. We may not know what is under the hood of ChatGPT, but thanks in part to Piantadosi’s prompts, we know it is capable of producing results that are racist and sexist. Less than three months ago, in December 2022, Piantadosi Tweeted ChatGPT’s response when he prompted the program to write programs about issues such as which child’s life should be saved based on their race and gender.&lt;/p&gt;
&lt;h3 id=&quot;automated-racism&quot;&gt;Automated racism&lt;/h3&gt;
&lt;p&gt;The program, if cued in a certain way, &lt;a href=&quot;https://twitter.com/spiantado/status/1599462375887114240&quot;&gt;would not suggest saving the life of a black male child, and but would suggest saving a white one&lt;/a&gt;. This &lt;a href=&quot;https://twitter.com/spiantado/status/1599462375887114240&quot;&gt;program algorithm&lt;/a&gt; was not an ironic joke or even a fluke. On prompts about race, the results were sadly expectable for someone like me who researches these issues. Sharing the results with the broader public allows everyone to see the dangers for themselves. ChatGPT is trained on a large corpus of text, gigabytes large, which clearly had some biases in it.&lt;/p&gt;
&lt;p&gt;The full conversation with ChatGPT contains more examples of ChatGPT’s biases at the time.&lt;/p&gt;
&lt;p&gt;What Piantadosi did in technical terms was a type of adversarial testing, and it is worth pointing out that it did not require him to be a computer scientist or even to write code. What I’m getting at, by pointing to Piantadosi’s academic provenance, is that even a scientist, nurse, or medical doctor with zero computer science knowledge, but perhaps some awareness of the dangers of such algorithms, could have done the same out of concern for patients. And at this point, we should all know to expect these outcomes, as countless researchers (even &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S2666521222000205&quot;&gt;including myself&lt;/a&gt;) have been working and publishing on issues like these for years.&lt;/p&gt;
&lt;p&gt;In the conversation with fellow doctors, the author of a forthcoming book on ChatGPT in healthcare declared it would get better and better. The man was an accomplished physician, but unfortunately, that does not imply someone who actually builds such systems line by line of code (specifically including the test code) and sees the results at scale. Only someone who doesn’t write the code on such systems could be so optimistic. The algorithm will get better or worse depending upon the data that it is fed, and the code that is added or removed from it. If you are counting on engineers to only do better and more careful work, you may want to consider how many software failures in healthcare come not from original products but from upgrades.&lt;/p&gt;
&lt;p&gt;To their credit, the staff over at &lt;a href=&quot;https://openai.com/&quot;&gt;OpenAI&lt;/a&gt; must be watching the internet, because they seem to have put guardrails on in terms of the exact kind of cues Piantadosi fed the algorithm. When I tested it on a recent morning, I got different results (screenshot shared below).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-f1dub97Cihvht4NPrwU7w-d0fbf5f0.u5IsbUkK_Z25Pm02.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Did I get different results based on a new algorithm, or just by chance? We can’t know. I do know it is very easy to hard-code over answers to certain questions while leaving bias in a general algorithm. I can imagine, that for legal reasons alone, anyone using ChatGPT might apply some kind of adversarial training layer on top of the closed algorithm results to eliminate racist statements.&lt;/p&gt;
&lt;p&gt;Even if this were the case, there are at least a couple more fundamental issues with the algorithm than its potential for producing racially biased answers. One issue is that the algorithm can return incorrect text about fairly obvious facts in medicine. Below is a screenshot from its response when I asked it a question about fabellae (a fabella is an accessory ossicle in the knee present in a minority of the population) in the way I thought a patient might ask it i.e. without fancy Latin orthography.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PuAvhRAwOe91akA3VkefJA-b1150312.BO04i_pB_1eg7Fl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The program returns something I consider symbolic of many of its problems. The program actually produced the correct spelling of fabellae, but got the facts wrong. Text produced can look right, and if you incorrectly attribute human qualities to the program, the program and text can seem ‘smarter’ than your average patient, but it can simultaneously not actually &lt;strong&gt;be&lt;/strong&gt; right. I guess ChatGPT won’t be replacing anatomists or radiologists (who know &lt;a href=&quot;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6075638/&quot;&gt;most of the population have zero fabellae&lt;/a&gt;) anytime soon. Some enthusiasts might argue that these little bugs could be fixed with hardcoded information about obvious facts. Even if that were possible, there are simple facts, and then there are assumptions based on the interpretation of data. For example, if I were to ask ChatGPT about the ideal diet for me to optimize my health, the answer is not truly an undebated ‘fact’ in the medical community. And here again, the machine can go in unwanted directions.&lt;/p&gt;
&lt;h3 id=&quot;reproducibility-the-scientific-dilemma-of-our-decade&quot;&gt;Reproducibility: the scientific dilemma of our decade&lt;/h3&gt;
&lt;p&gt;In my recent conversation with physicians, one marveled at how the chatbot had given two logical yet different answers to questions posed to it about a complex text. The doctor was wowed by the human and intellectual sound of the answers. In my head alarm bells were going off. If the same algorithm produces different answers at different times of the day, you have a problem with medical and scientific research, let alone medical applications. Algorithms can be programmed to look spontaneous and not reproducible, but fundamentally, many algorithms create exactly reproducible results even if they appear not to.&lt;/p&gt;
&lt;p&gt;Computers are not random, in fact, they can’t even make truly random outputs. If you actually program, you know this, as the functions used to make ‘random’ numbers rely on things like the machine time as input to pseudorandomized output. It takes a lot of work and code to make a simple algorithm, like a decision tree, not reproducible. But the more complex an algorithm is, the easier it is to get results that appear random, and not be truly reproducible in important ways. An algorithm that was trained on gigabytes of input can become pseudo-random in ways humans simply can’t comprehend, as we cannot read a corpus of gigabytes of text. Such an algorithm’s outputs can become, for our purposes, not reproducible from one patient to the next, and that is simply unacceptable in modern medicine.&lt;/p&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h3&gt;
&lt;p&gt;I am always surprised at how many of my fellow physicians seem to think algorithms fall from the sky perfect (the technical term here is automation bias). As someone who actually writes code on algorithms, I can tell you that to get a very complex large computer program that is perfect, you need a perfect group of perfect programmers (and no such thing exists). Code reflects the people who wrote it in general, and when it comes to machine learning it reflects the thought process of those people, and the people who curated the data the particular algorithm was based on.&lt;/p&gt;
&lt;p&gt;One argument for using chatbots in medicine is that they could help people who can’t access doctors. As someone who has spent time in places like Haiti and Lesvos, Greece, voluntarily practicing medicine towards humanitarian aims, this sounds appealing. But as someone whose work is to write code, I know better. There is a highly paid workforce behind complex algorithms and any medical AI system needs constant surveillance, monitoring, and upgrades. The work of ten dedicated high-level biomedical engineers and programmers isn’t necessarily any cheaper or better than that of ten physicians. Perhaps the true path forward is more physician education on such matters because in each specific situation, some combination of physicians and engineers is optimal to get the best healthcare to the most people at the lowest price.&lt;/p&gt;
&lt;p&gt;Chatbots are a tool we should embrace towards these great aims, but the hype around a closed-source product shows how far we have to go before we in medicine are truly ready to use such powerful tools.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_-f1dub97Cihvht4NPrwU7w-d0fbf5f0.u5IsbUkK.png" medium="image"/><author>Candace Moore</author></item><item><title>Diversity in Software: four ways to think different</title><link>https://blog2.esciencecenter.nl/posts/2023-02-02---diversity-in-software-four-ways-to-think-different</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-02-02---diversity-in-software-four-ways-to-think-different</guid><description>&lt;p&gt;&lt;img alt=&quot;Diversity in Software: four ways to think different&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;511&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/diversity-in-software-four-ways-to-think-4a16eeee.CsqEyq-x_W46iH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@steve_j?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Steve Johnson&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;diversity-in-software-four-ways-to-think-different&quot;&gt;Diversity in Software: four ways to think different&lt;/h1&gt;
&lt;p&gt;Diversity is a hot topic. Let’s talk about diversity in Software. Hackers need to wake up and face the truth: a lot of programming paradigms are underrepresented in the mainstream media. All the talk is about Python, Rust, Kotlin, and Julia. All of them are imperative languages. This just leaves no room for us wayward farers to express ourselves and be ourselves!&lt;/p&gt;
&lt;p&gt;People who know me now think the rest of this piece is going to cover the other side of the isle: functional programming, but they’re wrong. Just two approaches to programming are not enough. The funny thing is, you will have heard of most of the languages that I will talk about. I’ll just teach you to treat them with a little more respect.&lt;/p&gt;
&lt;h3 id=&quot;make&quot;&gt;Make&lt;/h3&gt;
&lt;p&gt;Make is a dependency-based programming language. You state a set of requirements, then other requirements for those, and so on. Then Make figures out a way to meet this cascade of requirements until your original goal is reached. This is a radical departure from imperative-style programming, where you have to be more explicit in what order you would like things to happen.&lt;/p&gt;
&lt;h3 id=&quot;awk&quot;&gt;Awk&lt;/h3&gt;
&lt;p&gt;Awk is a data streaming language. Given that you have some input file, Awk triggers actions on some regular expressions that you provide. This is ideal for processing text files. Because Regexes play a central role in the execution model of Awk, programs tend to suffer in readability. What you need to realize is how awesome the concept of Awk is. The rule-based control flow makes your program context-aware.&lt;/p&gt;
&lt;h3 id=&quot;sql&quot;&gt;SQL&lt;/h3&gt;
&lt;p&gt;In a landscape where the increasingly popular databases are graph-based or NoSQL, we need to champion our old hero: SQL. There’s nothing quite like juggling tables and inner joining them in holy matrimony. There’s a good reason why most databases work with tables and relations: for most cases, it is very efficient. The little extra effort of designing a table layout and indexing your data at strategic points is always well spent, as you gain insight into your problem.&lt;/p&gt;
&lt;h3 id=&quot;excel&quot;&gt;Excel&lt;/h3&gt;
&lt;p&gt;Say what!?! Excel is at its core a functional reactive programming language. Your data is a signal. Every time the signal changes all the depending cells are notified and updated live. Frameworks that generalize on this concept are known as functional reactive. I know Excel has its share of problems: cells that are not included in the computation, bad type heuristics, poor scaling… However, at its core Excel is a beautiful diamond that needs to be celebrated.&lt;/p&gt;
&lt;p&gt;Ok, those were some very famous languages. What you need to understand is how they are different. Their diversity can teach you not to take the mainstream general-purpose programming sludge for granted.&lt;/p&gt;
&lt;p&gt;In fact, the particular way that these languages or systems are different may teach you how to think about some problems on a higher level. The primitives of SQL are available in Python (and many other languages): for small things, you can use iterator comprehensions or the &lt;code&gt;itertools&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;If your problem has a complex set of interlocking dependent tasks (like you’d have in Make), consider writing the dependencies down in a data structure and evaluate them using Asyncio or Dask. This helps separate the core logic from implementation details, giving you cleaner, i.e. more readable and better maintainable code.&lt;/p&gt;
&lt;p&gt;The same goes for Awky problems: if you need to filter through a lot of text, write down some rules for a little state machine. Your life will improve!&lt;/p&gt;
&lt;p&gt;As for Excel: (functional) reactive programming is a topic I can’t possibly do justice to here. For those interested: &lt;a href=&quot;https://blog.oakbits.com/introduction-to-rxpy.html&quot;&gt;Introduction to RxPy&lt;/a&gt;, or more generally &lt;a href=&quot;https://www.manning.com/books/functional-reactive-programming&quot;&gt;Introduction to Functional Reactive Programming&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What these languages have in common, is that they have a different control flow* from what you’re used to. Knowing how to work with these tools can be an invaluable addition to your skill set. Did I miss out on any? Please comment below!&lt;/p&gt;
&lt;p&gt;If you’re interested in programming language history, check out this video.&lt;/p&gt;</description><pubDate>Thu, 02 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Diversity in Software: four ways to think different&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;511&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/diversity-in-software-four-ways-to-think-4a16eeee.CsqEyq-x_W46iH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@steve_j?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Steve Johnson&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;diversity-in-software-four-ways-to-think-different&quot;&gt;Diversity in Software: four ways to think different&lt;/h1&gt;
&lt;p&gt;Diversity is a hot topic. Let’s talk about diversity in Software. Hackers need to wake up and face the truth: a lot of programming paradigms are underrepresented in the mainstream media. All the talk is about Python, Rust, Kotlin, and Julia. All of them are imperative languages. This just leaves no room for us wayward farers to express ourselves and be ourselves!&lt;/p&gt;
&lt;p&gt;People who know me now think the rest of this piece is going to cover the other side of the isle: functional programming, but they’re wrong. Just two approaches to programming are not enough. The funny thing is, you will have heard of most of the languages that I will talk about. I’ll just teach you to treat them with a little more respect.&lt;/p&gt;
&lt;h3 id=&quot;make&quot;&gt;Make&lt;/h3&gt;
&lt;p&gt;Make is a dependency-based programming language. You state a set of requirements, then other requirements for those, and so on. Then Make figures out a way to meet this cascade of requirements until your original goal is reached. This is a radical departure from imperative-style programming, where you have to be more explicit in what order you would like things to happen.&lt;/p&gt;
&lt;h3 id=&quot;awk&quot;&gt;Awk&lt;/h3&gt;
&lt;p&gt;Awk is a data streaming language. Given that you have some input file, Awk triggers actions on some regular expressions that you provide. This is ideal for processing text files. Because Regexes play a central role in the execution model of Awk, programs tend to suffer in readability. What you need to realize is how awesome the concept of Awk is. The rule-based control flow makes your program context-aware.&lt;/p&gt;
&lt;h3 id=&quot;sql&quot;&gt;SQL&lt;/h3&gt;
&lt;p&gt;In a landscape where the increasingly popular databases are graph-based or NoSQL, we need to champion our old hero: SQL. There’s nothing quite like juggling tables and inner joining them in holy matrimony. There’s a good reason why most databases work with tables and relations: for most cases, it is very efficient. The little extra effort of designing a table layout and indexing your data at strategic points is always well spent, as you gain insight into your problem.&lt;/p&gt;
&lt;h3 id=&quot;excel&quot;&gt;Excel&lt;/h3&gt;
&lt;p&gt;Say what!?! Excel is at its core a functional reactive programming language. Your data is a signal. Every time the signal changes all the depending cells are notified and updated live. Frameworks that generalize on this concept are known as functional reactive. I know Excel has its share of problems: cells that are not included in the computation, bad type heuristics, poor scaling… However, at its core Excel is a beautiful diamond that needs to be celebrated.&lt;/p&gt;
&lt;p&gt;Ok, those were some very famous languages. What you need to understand is how they are different. Their diversity can teach you not to take the mainstream general-purpose programming sludge for granted.&lt;/p&gt;
&lt;p&gt;In fact, the particular way that these languages or systems are different may teach you how to think about some problems on a higher level. The primitives of SQL are available in Python (and many other languages): for small things, you can use iterator comprehensions or the &lt;code&gt;itertools&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;If your problem has a complex set of interlocking dependent tasks (like you’d have in Make), consider writing the dependencies down in a data structure and evaluate them using Asyncio or Dask. This helps separate the core logic from implementation details, giving you cleaner, i.e. more readable and better maintainable code.&lt;/p&gt;
&lt;p&gt;The same goes for Awky problems: if you need to filter through a lot of text, write down some rules for a little state machine. Your life will improve!&lt;/p&gt;
&lt;p&gt;As for Excel: (functional) reactive programming is a topic I can’t possibly do justice to here. For those interested: &lt;a href=&quot;https://blog.oakbits.com/introduction-to-rxpy.html&quot;&gt;Introduction to RxPy&lt;/a&gt;, or more generally &lt;a href=&quot;https://www.manning.com/books/functional-reactive-programming&quot;&gt;Introduction to Functional Reactive Programming&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What these languages have in common, is that they have a different control flow* from what you’re used to. Knowing how to work with these tools can be an invaluable addition to your skill set. Did I miss out on any? Please comment below!&lt;/p&gt;
&lt;p&gt;If you’re interested in programming language history, check out this video.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/diversity-in-software-four-ways-to-think-4a16eeee.CsqEyq-x.jpg" medium="image"/><author>Johan Hidding</author></item><item><title>Build a mass spectrometry analysis pipeline in Python using matchms — part II: Spec2Vec</title><link>https://blog2.esciencecenter.nl/posts/2023-01-31---build-a-mass-spectrometry-analysis-pipeline-in-python-using-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-01-31---build-a-mass-spectrometry-analysis-pipeline-in-python-using-</guid><description>&lt;h2 id=&quot;after-part-i-which-gave-an-introduction-on-how-to-import-process-and-analyze-a-tandem-mass-spectra-dataset-using-python-and-matchms-part-ii-will-add-spec2vec-to-the-game-a-machine-learning-tool-to-assess-spectrum-similarities&quot;&gt;After “part I” which gave an introduction on how to import, process, and analyze a tandem mass spectra dataset using Python and matchms, “part II” will add Spec2Vec to the game, a machine learning tool to assess spectrum similarities.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Feb 17, 2021&lt;/p&gt;
&lt;p&gt;Instead of looking at a few individual query spectra, lets have a look at the “bigger picture” by plotting part of the similarity score matrix we just computed to generate Figure 2**.&lt;/p&gt;
&lt;p&gt;from matplotlib import pyplot as pltscores_array = scores.scores.to_array()  # for matchms &gt;= 0.18.0plt.figure(figsize=(6,6), dpi=150)&lt;strong&gt;plt.imshow(scores_array[:50, :50], cmap=“viridis”)
plt.colorbar(shrink=0.7)
plt.title(“Spec2Vec spectra similarities”)
plt.xlabel(“Spectrum #ID”)
plt.ylabel(“Spectrum #ID”)
plt.clim(0, 1)  # Spec2Vec scores can be between -1 and 1
#plt.savefig(“spec2vec_scores.png”)
Figure 2&lt;/strong&gt;. Show the first 50 x 50 Spec2Vec similarity scores. The diagonal are scores between spectra and themselves, hence always = 1.0 (boring). But the few brighter (green/yellowish) dots here and there point out some apparently related spectra, according to Spec2Vec. Those might be worth a closer look.&lt;/p&gt;
&lt;h2 id=&quot;2-train-a-new-spec2vec-model-from-scratch&quot;&gt;2. Train a new Spec2Vec model from scratch&lt;/h2&gt;
&lt;p&gt;Training a Spec2Vec model is fairly straightforward and relatively fast (usually minutes to one hour max). In general, training a new model from scratch makes sense when a lot a data is present to train on as it gives more options to optimize the results when compared to simply using a pretrained model as done above.&lt;/p&gt;
&lt;p&gt;First, the spectrum data has to be converted into “documents” where peaks and neutral losses have become “words” (e.g. &lt;code&gt;peak@289.29&lt;/code&gt;). This can be done by running:&lt;/p&gt;
&lt;p&gt;from spec2vec import SpectrumDocumentspectrum_documents = [SpectrumDocument(s, n_decimals=2) for s in spectrums]Then, a new model can simply be trained by using &lt;code&gt;train_new_word2vec_model&lt;/code&gt;. The following code will create a new model which is trained for 25 iterations (for machine learning people: that is ”epochs”) on 2 workers (you can change this, e.g. to 4 if you have 4 cores, the difference is not drastic though). Depending on your hardware, the training of this model should not take longer than a couple of minutes.&lt;/p&gt;
&lt;p&gt;from spec2vec.model_building import train_new_word2vec_modelmodel_file = “tutorial_model.model”**model = train_new_word2vec_model(spectrum_documents, iterations=[25], filename=model_file,
workers=2, progress_logger=True)The above code snippet will automatically save the model under the name &lt;code&gt;tutorial_model.model&lt;/code&gt;, which could later load again by running &lt;code&gt;model = gensim.models.Word2Vec.load(&quot;tutorial_model.model&quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;calculate-spectrum-similarities&quot;&gt;Calculate spectrum similarities&lt;/h3&gt;
&lt;p&gt;Once we have our trained model we can again (as above with the pretrained model) compute spectrum similarities.&lt;/p&gt;
&lt;p&gt;from matchms import calculate_scores
from spec2vec import Spec2Vecspec2vec_similarity = Spec2Vec(model=model, intensity_weighting_power=0.5,
allowed_missing_percentage=5.0)scores = calculate_scores(spectrum_documents, spectrum_documents, spec2vec_similarity, is_symmetric=True)Here again we can search for the best matching compounds according to Spec2Vec.&lt;/p&gt;
&lt;p&gt;best_matches = scores.scores_by_query(spectrum_documents[11], sort=True)[:10]
[x[0].get(“smiles”) for x in best_matches]And we can plot the resulting smiles to .png files by running:&lt;/p&gt;
&lt;p&gt;from rdkit import Chem
from rdkit.Chem import Drawfor i, smiles in enumerate([x[0].get(“smiles”) for x in best_matches]):
m = Chem.MolFromSmiles(smiles)
Draw.MolToFile(m, f”compound_{i}.png”)The best 8 matches are plotted in Figure 3**.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Figure 3.&lt;/strong&gt; Compounds of the highest 9 Spec2Vec similarity scores within the dataset with respect to spectrums[11], the first being the spectrum of interest itself (hence “query compound”).This example in figure 3 looks already quiet promising and all selected candidates clearly show chemical similarities! But this is of course just one mostly random pick out of many spectra. In our &lt;a href=&quot;https://www.biorxiv.org/content/10.1101/2020.08.11.245928v2&quot;&gt;Spec2Vec paper&lt;/a&gt; we compared the different similarity scores (Cosine, modified Cosine, Spec2Vec) in much more detail and found that Spec2Vec often — but not always — outperformed the classical scores. We also found a general trend that such scores are generally more reliable for larger compounds, supposedly because those will come with a higher number of chemically meaningful fragments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Figure 4.&lt;/strong&gt; Working with different datasets from GNPS we evaluated the quality of Spec2Vec based spectrum suggestions and found that they get better with increasing compound mass. Taken from &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008724&quot;&gt;Spec2Vec article&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OK. Done for now. Really curious to see what you can get out of Spec2Vec!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;other-parts-of-this-tutorial&quot;&gt;Other parts of this tutorial&lt;/h2&gt;
&lt;h3 id=&quot;part-i--build-you-own-mass-spectrometry-pipeline&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-your-own-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-i-d96c718c68ee&quot;&gt;part I — Build you own mass spectrometry pipeline&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-ii--compute-spectra-similarities-using-spec2vec&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-ii-spec2vec-8aa639571018&quot;&gt;part II — Compute spectra similarities using Spec2Vec&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-iii--network-analysis-based-on-spectra-similarities&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-iii-molecular-91891248ee34&quot;&gt;part III — Network analysis based on spectra similarities&lt;/a&gt;&lt;/h3&gt;
&lt;h2 id=&quot;matchms-library&quot;&gt;matchms library&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;matchms&lt;/strong&gt;* is freely available and open-source. You can find the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;code on Github&lt;/a&gt;, the package is available as &lt;a href=&quot;https://anaconda.org/nlesc/matchms&quot;&gt;conda package&lt;/a&gt; (recommended) or &lt;a href=&quot;https://pypi.org/project/matchms/&quot;&gt;from pypi&lt;/a&gt;. It was developed by a bunch of very nice people (see &lt;a href=&quot;https://github.com/matchms/matchms/blob/master/CITATION.cff&quot;&gt;here&lt;/a&gt;) and is &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;published in Joss&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;spec2vec-library&quot;&gt;spec2vec library&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Spec2Vec&lt;/strong&gt; is of course also freely available and open-source. You can find the &lt;a href=&quot;https://github.com/iomega/spec2vec&quot;&gt;code on Github&lt;/a&gt;, the package is available as &lt;a href=&quot;https://anaconda.org/nlesc/spec2vec&quot;&gt;conda package&lt;/a&gt; (recommended) or &lt;a href=&quot;https://pypi.org/project/spec2vec/&quot;&gt;from pypi&lt;/a&gt;. The &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008724&quot;&gt;article published in PLOS Computational Biology can be found here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can find more information in the &lt;a href=&quot;https://matchms.readthedocs.io/en/latest/&quot;&gt;matchms documentation&lt;/a&gt; and the &lt;a href=&quot;https://spec2vec.readthedocs.io/en/latest/?badge=latest&quot;&gt;spec2vec documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;
&lt;p&gt;The code shown in this blog post can also be found &lt;a href=&quot;https://github.com/matchms/matchms/blob/tutorial/tutorial/matchms_tutorial_02_compute_similarities_with_Spec2Vec.ipynb&quot;&gt;as Jupyter notebook on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;help-us-develop-matchms-and-spec2vec-further&quot;&gt;Help us develop matchms and spec2vec further!&lt;/h2&gt;
&lt;p&gt;We really hope that matchms will help people to build new, better analysis pipelines and that spec2vec can improve your analysis results. So, please help us to further improve matchms and spec2vec. You can help us by &lt;strong&gt;(1)&lt;/strong&gt; Cite our work if you use our package for your research: &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;matchms article in JOSS,&lt;/a&gt; &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008724&quot;&gt;spec2vec article in PLOS Computational Biology&lt;/a&gt;.&lt;strong&gt;(2)&lt;/strong&gt; Let us know if you run into any issues using matchms and/or spec2vec, or if you are missing any key functionalities! You can simply do so by starting a new issue on the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;matchms GitHub repository,&lt;/a&gt; or contact me on twitter &lt;a href=&quot;https://twitter.com/me_datapoint?lang=en&quot;&gt;@me_datapoint&lt;/a&gt;.&lt;strong&gt;You are of course more than welcome to also become an active contributor to the package and help extend its functionality!
(3)&lt;/strong&gt; Please let us know if you successfully applied matchms and/or spec2vec in your research project (makes us happy + we can maybe share the good news!).&lt;/p&gt;
&lt;p&gt;Thanks a lot!&lt;/p&gt;
&lt;p&gt;I would like to thank [Carlos Martinez-Ortiz], [Justin van der Hooft] and [Kontoueftychia] for helpful comments and suggestions on this blog post.&lt;/p&gt;</description><pubDate>Tue, 31 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;after-part-i-which-gave-an-introduction-on-how-to-import-process-and-analyze-a-tandem-mass-spectra-dataset-using-python-and-matchms-part-ii-will-add-spec2vec-to-the-game-a-machine-learning-tool-to-assess-spectrum-similarities&quot;&gt;After “part I” which gave an introduction on how to import, process, and analyze a tandem mass spectra dataset using Python and matchms, “part II” will add Spec2Vec to the game, a machine learning tool to assess spectrum similarities.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Feb 17, 2021&lt;/p&gt;
&lt;p&gt;Instead of looking at a few individual query spectra, lets have a look at the “bigger picture” by plotting part of the similarity score matrix we just computed to generate Figure 2**.&lt;/p&gt;
&lt;p&gt;from matplotlib import pyplot as pltscores_array = scores.scores.to_array()  # for matchms &gt;= 0.18.0plt.figure(figsize=(6,6), dpi=150)&lt;strong&gt;plt.imshow(scores_array[:50, :50], cmap=“viridis”)
plt.colorbar(shrink=0.7)
plt.title(“Spec2Vec spectra similarities”)
plt.xlabel(“Spectrum #ID”)
plt.ylabel(“Spectrum #ID”)
plt.clim(0, 1)  # Spec2Vec scores can be between -1 and 1
#plt.savefig(“spec2vec_scores.png”)
Figure 2&lt;/strong&gt;. Show the first 50 x 50 Spec2Vec similarity scores. The diagonal are scores between spectra and themselves, hence always = 1.0 (boring). But the few brighter (green/yellowish) dots here and there point out some apparently related spectra, according to Spec2Vec. Those might be worth a closer look.&lt;/p&gt;
&lt;h2 id=&quot;2-train-a-new-spec2vec-model-from-scratch&quot;&gt;2. Train a new Spec2Vec model from scratch&lt;/h2&gt;
&lt;p&gt;Training a Spec2Vec model is fairly straightforward and relatively fast (usually minutes to one hour max). In general, training a new model from scratch makes sense when a lot a data is present to train on as it gives more options to optimize the results when compared to simply using a pretrained model as done above.&lt;/p&gt;
&lt;p&gt;First, the spectrum data has to be converted into “documents” where peaks and neutral losses have become “words” (e.g. &lt;code&gt;peak@289.29&lt;/code&gt;). This can be done by running:&lt;/p&gt;
&lt;p&gt;from spec2vec import SpectrumDocumentspectrum_documents = [SpectrumDocument(s, n_decimals=2) for s in spectrums]Then, a new model can simply be trained by using &lt;code&gt;train_new_word2vec_model&lt;/code&gt;. The following code will create a new model which is trained for 25 iterations (for machine learning people: that is ”epochs”) on 2 workers (you can change this, e.g. to 4 if you have 4 cores, the difference is not drastic though). Depending on your hardware, the training of this model should not take longer than a couple of minutes.&lt;/p&gt;
&lt;p&gt;from spec2vec.model_building import train_new_word2vec_modelmodel_file = “tutorial_model.model”**model = train_new_word2vec_model(spectrum_documents, iterations=[25], filename=model_file,
workers=2, progress_logger=True)The above code snippet will automatically save the model under the name &lt;code&gt;tutorial_model.model&lt;/code&gt;, which could later load again by running &lt;code&gt;model = gensim.models.Word2Vec.load(&quot;tutorial_model.model&quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;calculate-spectrum-similarities&quot;&gt;Calculate spectrum similarities&lt;/h3&gt;
&lt;p&gt;Once we have our trained model we can again (as above with the pretrained model) compute spectrum similarities.&lt;/p&gt;
&lt;p&gt;from matchms import calculate_scores
from spec2vec import Spec2Vecspec2vec_similarity = Spec2Vec(model=model, intensity_weighting_power=0.5,
allowed_missing_percentage=5.0)scores = calculate_scores(spectrum_documents, spectrum_documents, spec2vec_similarity, is_symmetric=True)Here again we can search for the best matching compounds according to Spec2Vec.&lt;/p&gt;
&lt;p&gt;best_matches = scores.scores_by_query(spectrum_documents[11], sort=True)[:10]
[x[0].get(“smiles”) for x in best_matches]And we can plot the resulting smiles to .png files by running:&lt;/p&gt;
&lt;p&gt;from rdkit import Chem
from rdkit.Chem import Drawfor i, smiles in enumerate([x[0].get(“smiles”) for x in best_matches]):
m = Chem.MolFromSmiles(smiles)
Draw.MolToFile(m, f”compound_{i}.png”)The best 8 matches are plotted in Figure 3**.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Figure 3.&lt;/strong&gt; Compounds of the highest 9 Spec2Vec similarity scores within the dataset with respect to spectrums[11], the first being the spectrum of interest itself (hence “query compound”).This example in figure 3 looks already quiet promising and all selected candidates clearly show chemical similarities! But this is of course just one mostly random pick out of many spectra. In our &lt;a href=&quot;https://www.biorxiv.org/content/10.1101/2020.08.11.245928v2&quot;&gt;Spec2Vec paper&lt;/a&gt; we compared the different similarity scores (Cosine, modified Cosine, Spec2Vec) in much more detail and found that Spec2Vec often — but not always — outperformed the classical scores. We also found a general trend that such scores are generally more reliable for larger compounds, supposedly because those will come with a higher number of chemically meaningful fragments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Figure 4.&lt;/strong&gt; Working with different datasets from GNPS we evaluated the quality of Spec2Vec based spectrum suggestions and found that they get better with increasing compound mass. Taken from &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008724&quot;&gt;Spec2Vec article&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OK. Done for now. Really curious to see what you can get out of Spec2Vec!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;other-parts-of-this-tutorial&quot;&gt;Other parts of this tutorial&lt;/h2&gt;
&lt;h3 id=&quot;part-i--build-you-own-mass-spectrometry-pipeline&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-your-own-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-i-d96c718c68ee&quot;&gt;part I — Build you own mass spectrometry pipeline&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-ii--compute-spectra-similarities-using-spec2vec&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-ii-spec2vec-8aa639571018&quot;&gt;part II — Compute spectra similarities using Spec2Vec&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-iii--network-analysis-based-on-spectra-similarities&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-iii-molecular-91891248ee34&quot;&gt;part III — Network analysis based on spectra similarities&lt;/a&gt;&lt;/h3&gt;
&lt;h2 id=&quot;matchms-library&quot;&gt;matchms library&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;matchms&lt;/strong&gt;* is freely available and open-source. You can find the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;code on Github&lt;/a&gt;, the package is available as &lt;a href=&quot;https://anaconda.org/nlesc/matchms&quot;&gt;conda package&lt;/a&gt; (recommended) or &lt;a href=&quot;https://pypi.org/project/matchms/&quot;&gt;from pypi&lt;/a&gt;. It was developed by a bunch of very nice people (see &lt;a href=&quot;https://github.com/matchms/matchms/blob/master/CITATION.cff&quot;&gt;here&lt;/a&gt;) and is &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;published in Joss&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;spec2vec-library&quot;&gt;spec2vec library&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Spec2Vec&lt;/strong&gt; is of course also freely available and open-source. You can find the &lt;a href=&quot;https://github.com/iomega/spec2vec&quot;&gt;code on Github&lt;/a&gt;, the package is available as &lt;a href=&quot;https://anaconda.org/nlesc/spec2vec&quot;&gt;conda package&lt;/a&gt; (recommended) or &lt;a href=&quot;https://pypi.org/project/spec2vec/&quot;&gt;from pypi&lt;/a&gt;. The &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008724&quot;&gt;article published in PLOS Computational Biology can be found here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can find more information in the &lt;a href=&quot;https://matchms.readthedocs.io/en/latest/&quot;&gt;matchms documentation&lt;/a&gt; and the &lt;a href=&quot;https://spec2vec.readthedocs.io/en/latest/?badge=latest&quot;&gt;spec2vec documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;code&quot;&gt;Code&lt;/h2&gt;
&lt;p&gt;The code shown in this blog post can also be found &lt;a href=&quot;https://github.com/matchms/matchms/blob/tutorial/tutorial/matchms_tutorial_02_compute_similarities_with_Spec2Vec.ipynb&quot;&gt;as Jupyter notebook on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;help-us-develop-matchms-and-spec2vec-further&quot;&gt;Help us develop matchms and spec2vec further!&lt;/h2&gt;
&lt;p&gt;We really hope that matchms will help people to build new, better analysis pipelines and that spec2vec can improve your analysis results. So, please help us to further improve matchms and spec2vec. You can help us by &lt;strong&gt;(1)&lt;/strong&gt; Cite our work if you use our package for your research: &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;matchms article in JOSS,&lt;/a&gt; &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1008724&quot;&gt;spec2vec article in PLOS Computational Biology&lt;/a&gt;.&lt;strong&gt;(2)&lt;/strong&gt; Let us know if you run into any issues using matchms and/or spec2vec, or if you are missing any key functionalities! You can simply do so by starting a new issue on the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;matchms GitHub repository,&lt;/a&gt; or contact me on twitter &lt;a href=&quot;https://twitter.com/me_datapoint?lang=en&quot;&gt;@me_datapoint&lt;/a&gt;.&lt;strong&gt;You are of course more than welcome to also become an active contributor to the package and help extend its functionality!
(3)&lt;/strong&gt; Please let us know if you successfully applied matchms and/or spec2vec in your research project (makes us happy + we can maybe share the good news!).&lt;/p&gt;
&lt;p&gt;Thanks a lot!&lt;/p&gt;
&lt;p&gt;I would like to thank [Carlos Martinez-Ortiz], [Justin van der Hooft] and [Kontoueftychia] for helpful comments and suggestions on this blog post.&lt;/p&gt;</content:encoded><author>Florian Huber</author></item><item><title>Build your own mass spectrometry analysis pipeline in Python using matchms — part I</title><link>https://blog2.esciencecenter.nl/posts/2023-01-31---build-your-own-mass-spectrometry-analysis-pipeline-in-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-01-31---build-your-own-mass-spectrometry-analysis-pipeline-in-python</guid><description>&lt;h2 id=&quot;python-is-a-very-powerful-language-and-brings-the-potential-for-designing-computational-mass-spectrometry-analysis-workflows-of-any-desired-type-and-complexity-here-you-can-find-a-quick-introduction-on-how-to-import-process-and-analyze-a-tandem-mass-spectra-dataset-using-python-and-matchms&quot;&gt;Python is a very powerful language and brings the potential for designing computational mass spectrometry analysis workflows of any desired type and complexity. Here, you can find a quick introduction on how to import, process, and analyze a tandem mass spectra dataset using Python and matchms.&lt;/h2&gt;
&lt;p&gt;Let’s first inspect what scores we have by running:&lt;/p&gt;
&lt;p&gt;scores.score_namesLet’s inspect some of the number of matching peaks by first converting our sparse score array into a regular Numpy array and then slicing the first 5x5 entries:&lt;/p&gt;
&lt;p&gt;scores_array = scores.scores.to_array()
scores_array[:5, :5][“CosineGreedy_score”]or access the corresponding number of matching peaks by running:&lt;/p&gt;
&lt;p&gt;scores_array = scores.scores.to_array()
scores_array[:5, :5][“CosineGreedy_matches”]&lt;/p&gt;
&lt;h3 id=&quot;get-most-similar-spectra-for-spectrum-of-interest&quot;&gt;Get most similar spectra for spectrum of interest&lt;/h3&gt;
&lt;p&gt;If we want to see which spectra are most similar to the i-th spectrum (according to the here used Cosine score), then we can call:&lt;/p&gt;
&lt;p&gt;best_matches = scores.scores_by_query(spectrums[5], name=“CosineGreedy_score”, sort=True)[:10]
print([x[1] for x in best_matches])which returns the scores for the top-10 candidates (Cosine score + number of matching peaks):&lt;/p&gt;
&lt;p&gt;Out[]:[(1., 30),
(0.99711049, 2),
(0.99534901, 2),
(0.99214557, 2),
(0.98748381, 2),
(0.98461111, 3),
(0.98401833, 2),
(0.97598497, 2),
(0.9757458, 2),
(0.97547771, 2)]The first, highest ranked results is the spectrum itself, but what are those other candidates, all with pretty high Cosine scores? Let’s find out by looking at the respective smiles (&lt;a href=&quot;https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system&quot;&gt;smiles&lt;/a&gt; are notations for the chemical structure of the compounds):&lt;/p&gt;
&lt;p&gt;[x[0].get(“smiles”) for x in best_matches]which here returns:&lt;/p&gt;
&lt;p&gt;Out[]:[‘OC(COC(=O)c1ccccc1)C(O)C(O)COC(=O)c2ccccc2’,
‘Cc1cc(=O)oc2cc(OC(=O)c3ccccc3)ccc12’,
‘O=C(Nc1ccccc1OC(=O)c2ccccc2)c3ccccc3’,
‘COc1cc(CC=C)ccc1OC(=O)c2ccccc2’,
‘O=C(OCC1OC(C(OC(=O)c2ccccc2)C1OC(=O)c3ccccc3)n4ncc(=O)[nH]c4=O)c5ccccc5’,
‘O=C(Oc1cccc2ccccc12)c3ccccc3’,
‘O=C(N1&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C#N&quot;&gt;C@@H&lt;/a&gt;C2OC2c3ccccc13)c4ccccc4’,
‘COC(=O)CNC(=O)c1ccccc1’,
‘COc1c2OCOc2cc(CCN(C)C(=O)c3ccccc3)c1C=C4C(=O)NC(=O)NC4=O’,
‘COc1c2OCOc2cc(CCN(C)C(=O)c3ccccc3)c1/C=C\4/C(=O)NC(=O)N(C)C4=O’]For those who are not used to reading smiles all the time (like me), let’s display the structures. There are many online and offline tools for plotting structures from smiles. Here, I used the Python package &lt;a href=&quot;https://www.rdkit.org/&quot;&gt;rdkit&lt;/a&gt; for it by running:&lt;/p&gt;
&lt;p&gt;from rdkit import Chem
from rdkit.Chem import Drawfor i, smiles in enumerate([x[0].get(“smiles”) for x in    best_matches]):
m = Chem.MolFromSmiles(smiles)
Draw.MolToFile(m, f”compound_{i}.png”)
&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-b73e3c5e.DXzNQPN6_2fRDxG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4.** Compounds of the highest 9 Cosine scores within the dataset with respect to spectrums[5], the first being the spectrum of interest itself (hence named “query compound”).&lt;/p&gt;
&lt;h3 id=&quot;alternative-get-best-matches-above-min_match-threshold&quot;&gt;Alternative: Get best matches above ‘min_match’ threshold&lt;/h3&gt;
&lt;p&gt;Maybe having two matching peaks is not good enough and you want to be more certain of your Cosine score based candidates. Let’s then only consider the best Cosine scores for which we have at least min_match* matches:&lt;/p&gt;
&lt;p&gt;min_match = 5**sorted_matches = scores.scores_by_query(spectrums[5], name=“CosineGreedy_score”, sort=True)
best_matches = [x for x in sorted_matches if x[1][“CosineGreedy_matches”] &gt;= min_match][:10][x[1] for x in best_matches]which will give a very different result than the previous run. Here we do not find any other spectrum in the dataset that shows a very high Cosine score (again, except the first entry which is the similarity of the spectrum with itself and hence obviously = 1):&lt;/p&gt;
&lt;p&gt;Out[]:[(1., 30),
(0.44857215, 6),
(0.39605775, 5),
(0.33880658, 5),
(0.03942863, 6),
(0.03429136, 5),
(0.03028157, 5),
(0.02845932, 5),
(0.01924283, 7),
(0.01890612, 5)]&lt;/p&gt;
&lt;h2 id=&quot;4-compute-spectra-similarities-modified-cosine-score&quot;&gt;4. Compute spectra similarities: Modified Cosine score&lt;/h2&gt;
&lt;p&gt;The modified cosine score aims at quantifying the similarity between two mass spectra. Unlike the Cosine score it does not only look at nearly identical spectra, but also considers the mass shift between two compounds. The score is calculated by finding best possible matches between peaks of two spectra. Two peaks are considered a potential match if their m/z ratios lie within the given ‘tolerance’, or if their m/z ratios lie within the tolerance once a mass-shift is applied. The mass shift is simply the difference in precursor-m/z between the two spectra. See &lt;a href=&quot;https://www.pnas.org/content/109/26/E1743&quot;&gt;Watrous et al. (PNAS, 2012)&lt;/a&gt; for further details.&lt;/p&gt;
&lt;p&gt;As done above for the Cosine score, we can calculate the similarities for all possible spectrum pairs by running:&lt;/p&gt;
&lt;p&gt;from matchms.similarity import ModifiedCosinesimilarity_measure = ModifiedCosine(tolerance=0.005)
scores = calculate_scores(spectrums, spectrums, similarity_measure,
is_symmetric=True)Let’s then visualize the results for the first 50 x 50 spectrum pairs.&lt;/p&gt;
&lt;p&gt;scores_array = scores.scores.to_array()plt.figure(figsize=(6,6), dpi=150)
plt.imshow(scores_array[:50, :50][“score”], cmap=“viridis”)
plt.colorbar(shrink=0.7)
plt.title(“Modified Cosine spectra similarities”)
plt.xlabel(“Spectrum #ID”)
plt.ylabel(“Spectrum #ID”)
&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;584&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-b0ee4396.TFNu_jSz_ZuxCvP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 5.** Modified Cosine scores for all possible pairs between the first 50 imported spectrums. As to be expected, the diagonal is always =1 (score for spectrum with itself). But also several other very high Modified Cosine scores stick out suggesting highly related spectra.Now, let’s accept Modified Cosine scores for a minimum number of matching peaks (min_match).&lt;/p&gt;
&lt;p&gt;min_match = 5plt.figure(figsize=(6,6), dpi=150)**plt.imshow(scores_array[:50, :50][“ModifiedCosine_score”] &lt;br&gt;
* (scores_array[:50, :50][“ModifiedCosine_matches”] &gt;= min_match), cmap=“viridis”)
plt.colorbar(shrink=0.7)
plt.title(“Modified Cosine spectra similarities (min_match=5)”)
plt.xlabel(“Spectrum #ID”)
plt.ylabel(“Spectrum #ID”)
&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;607&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-5d737491.DuPLDQy9_ZJDWiI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 6.** Modified Cosine scores for all possible pairs between the first 50 imported spectrums (with ≥ 5 matching peaks!).There’s for instance a bright spot far outside the diagonal for &lt;code&gt;spectrums[11]&lt;/code&gt; so let’s have a look at that one!&lt;/p&gt;
&lt;p&gt;min_match = 5sorted_matches = scores.scores_by_query(spectrums[11], name=“ModifiedCosine_score”, sort=True)**best_matches = [x for x in sorted_matches if x[1][“ModifiedCosine_matches”] &gt;= min_match][:10]
[x[1] for x in best_matches]Which gives&lt;/p&gt;
&lt;p&gt;Out[]:[(1., 151),
(0.95295779, 15),
(0.94542762, 13),
(0.89735889, 17),
(0.7886489, 12),
(0.77433041, 9),
(0.74935776, 8),
(0.72854032, 8),
(0.55896333, 7),
(0.52331993, 9)]And, probably more interesting, the corresponding smiles:&lt;/p&gt;
&lt;p&gt;[x[0].get(“smiles”) for x in best_matches]Out[]:[‘CC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/CC(=O)O&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘CCCCCC(NC(=O)C1CCN(CC1)C(=O)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c2ccc(C)cc2&quot;&gt;C@@H&lt;/a&gt;C(C)C)C(=O)O’,
‘CC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C(=O)O&quot;&gt;C@H&lt;/a&gt;c3ccccc3’,
‘CC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/CCC(=O)N&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘COC(=O)C1CCN(CC1)C(=O)C2CCN(CC2)C(=O)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c3ccc(C)cc3&quot;&gt;C@@H&lt;/a&gt;C(C)C’,
‘CCC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C(=O)O&quot;&gt;C@H&lt;/a&gt;c3ccccc3’,
‘CC(C)C&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C(C)C&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘CC(C)C&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/Cc3ccccc3&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘CCC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N3CCC(CC3)C(=O)N’,
‘CCC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N3CCC(CC3)C(=O)OC’]OK, smiles, nice. But let’s better move on and have a look at how those compounds actually look like (as above, plotted using rdkit):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;548&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-f6234fec.BUqASEbP_Z2ulvye.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 7.** Compounds of the highest 9 modified Cosine scores within the dataset with respect to spectrums[11], the first being the spectrum of interest itself (hence “query compound”).I wouldn’t dare calling myself a natural product expert. But those chemical structures clearly do look more consistent to what we saw in Figure 4…&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now it’s up to you to come up with things to do with this ;)&lt;/p&gt;
&lt;p&gt;I hope this helped you getting started with using &lt;em&gt;&lt;strong&gt;matchms&lt;/strong&gt;&lt;/em&gt; for working with your MS/MS data! Soon there will be additional tutorials to go a bit more depth:&lt;/p&gt;
&lt;h2 id=&quot;other-parts-of-this-tutorial&quot;&gt;Other parts of this tutorial&lt;/h2&gt;
&lt;h3 id=&quot;part-i--build-you-own-mass-spectrometry-pipeline&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-your-own-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-i-d96c718c68ee&quot;&gt;part I — Build you own mass spectrometry pipeline&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-ii--compute-spectra-similarities-using-spec2vec&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-ii-spec2vec-8aa639571018&quot;&gt;part II — Compute spectra similarities using Spec2Vec&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-iii--network-analysis-based-on-spectra-similarities&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-iii-molecular-91891248ee34&quot;&gt;part III — Network analysis based on spectra similarities&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;matchms-library&quot;&gt;matchms library&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;matchms&lt;/strong&gt;&lt;/em&gt; is freely available and open-source. You can find the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;code on Github&lt;/a&gt;, the package is available as &lt;a href=&quot;https://anaconda.org/nlesc/matchms&quot;&gt;conda package&lt;/a&gt; (recommended) or &lt;a href=&quot;https://pypi.org/project/matchms/&quot;&gt;from pypi&lt;/a&gt;. It was developed by a bunch of very nice people (see &lt;a href=&quot;https://github.com/matchms/matchms/blob/master/CITATION.cff&quot;&gt;here&lt;/a&gt;) and is &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;published in Joss&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can find more information in the &lt;a href=&quot;https://matchms.readthedocs.io/en/latest/&quot;&gt;matchms documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;code&quot;&gt;Code&lt;/h3&gt;
&lt;p&gt;The code shown in this blog post can also be found as &lt;a href=&quot;https://github.com/matchms/matchms/blob/tutorial/tutorial/matchms_tutorial_01_building_analysis_pipeline.ipynb&quot;&gt;a Jupyter notebook here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;help-us-develop-matchms-further&quot;&gt;Help us develop matchms further!&lt;/h3&gt;
&lt;p&gt;We really hope that matchms will help people to build new, better analysis pipelines. So, please help us to further improve matchms. You can help us by &lt;strong&gt;(1)&lt;/strong&gt; Cite our work if you use our package for your research: &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;matchms article in JOSS&lt;/a&gt;.&lt;strong&gt;(2)&lt;/strong&gt; Let us know if you run into any issues using matchms, or if you are missing any key functionalities! You can simply do so by starting a new issue on the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;matchms GitHub repository,&lt;/a&gt; or contact me on twitter &lt;a href=&quot;https://twitter.com/me_datapoint?lang=en&quot;&gt;@me_datapoint&lt;/a&gt;.&lt;strong&gt;You are of course more than welcome to also become an active contributor to the package and help extend its functionality!
(3)&lt;/strong&gt; Please let us know if you successfully applied matchms in your research project (makes us happy + we can maybe share the good news!).&lt;/p&gt;
&lt;p&gt;Thanks a lot!&lt;/p&gt;
&lt;p&gt;I would like to thank [Carlos Martinez-Ortiz,] [Jorislouwen], Niek de Jonge, [Justin van der Hooft] for helpful comments and suggestions on this blog post.&lt;/p&gt;</description><pubDate>Tue, 31 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;python-is-a-very-powerful-language-and-brings-the-potential-for-designing-computational-mass-spectrometry-analysis-workflows-of-any-desired-type-and-complexity-here-you-can-find-a-quick-introduction-on-how-to-import-process-and-analyze-a-tandem-mass-spectra-dataset-using-python-and-matchms&quot;&gt;Python is a very powerful language and brings the potential for designing computational mass spectrometry analysis workflows of any desired type and complexity. Here, you can find a quick introduction on how to import, process, and analyze a tandem mass spectra dataset using Python and matchms.&lt;/h2&gt;
&lt;p&gt;Let’s first inspect what scores we have by running:&lt;/p&gt;
&lt;p&gt;scores.score_namesLet’s inspect some of the number of matching peaks by first converting our sparse score array into a regular Numpy array and then slicing the first 5x5 entries:&lt;/p&gt;
&lt;p&gt;scores_array = scores.scores.to_array()
scores_array[:5, :5][“CosineGreedy_score”]or access the corresponding number of matching peaks by running:&lt;/p&gt;
&lt;p&gt;scores_array = scores.scores.to_array()
scores_array[:5, :5][“CosineGreedy_matches”]&lt;/p&gt;
&lt;h3 id=&quot;get-most-similar-spectra-for-spectrum-of-interest&quot;&gt;Get most similar spectra for spectrum of interest&lt;/h3&gt;
&lt;p&gt;If we want to see which spectra are most similar to the i-th spectrum (according to the here used Cosine score), then we can call:&lt;/p&gt;
&lt;p&gt;best_matches = scores.scores_by_query(spectrums[5], name=“CosineGreedy_score”, sort=True)[:10]
print([x[1] for x in best_matches])which returns the scores for the top-10 candidates (Cosine score + number of matching peaks):&lt;/p&gt;
&lt;p&gt;Out[]:[(1., 30),
(0.99711049, 2),
(0.99534901, 2),
(0.99214557, 2),
(0.98748381, 2),
(0.98461111, 3),
(0.98401833, 2),
(0.97598497, 2),
(0.9757458, 2),
(0.97547771, 2)]The first, highest ranked results is the spectrum itself, but what are those other candidates, all with pretty high Cosine scores? Let’s find out by looking at the respective smiles (&lt;a href=&quot;https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system&quot;&gt;smiles&lt;/a&gt; are notations for the chemical structure of the compounds):&lt;/p&gt;
&lt;p&gt;[x[0].get(“smiles”) for x in best_matches]which here returns:&lt;/p&gt;
&lt;p&gt;Out[]:[‘OC(COC(=O)c1ccccc1)C(O)C(O)COC(=O)c2ccccc2’,
‘Cc1cc(=O)oc2cc(OC(=O)c3ccccc3)ccc12’,
‘O=C(Nc1ccccc1OC(=O)c2ccccc2)c3ccccc3’,
‘COc1cc(CC=C)ccc1OC(=O)c2ccccc2’,
‘O=C(OCC1OC(C(OC(=O)c2ccccc2)C1OC(=O)c3ccccc3)n4ncc(=O)[nH]c4=O)c5ccccc5’,
‘O=C(Oc1cccc2ccccc12)c3ccccc3’,
‘O=C(N1&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C#N&quot;&gt;C@@H&lt;/a&gt;C2OC2c3ccccc13)c4ccccc4’,
‘COC(=O)CNC(=O)c1ccccc1’,
‘COc1c2OCOc2cc(CCN(C)C(=O)c3ccccc3)c1C=C4C(=O)NC(=O)NC4=O’,
‘COc1c2OCOc2cc(CCN(C)C(=O)c3ccccc3)c1/C=C\4/C(=O)NC(=O)N(C)C4=O’]For those who are not used to reading smiles all the time (like me), let’s display the structures. There are many online and offline tools for plotting structures from smiles. Here, I used the Python package &lt;a href=&quot;https://www.rdkit.org/&quot;&gt;rdkit&lt;/a&gt; for it by running:&lt;/p&gt;
&lt;p&gt;from rdkit import Chem
from rdkit.Chem import Drawfor i, smiles in enumerate([x[0].get(“smiles”) for x in    best_matches]):
m = Chem.MolFromSmiles(smiles)
Draw.MolToFile(m, f”compound_{i}.png”)
&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-b73e3c5e.DXzNQPN6_2fRDxG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4.** Compounds of the highest 9 Cosine scores within the dataset with respect to spectrums[5], the first being the spectrum of interest itself (hence named “query compound”).&lt;/p&gt;
&lt;h3 id=&quot;alternative-get-best-matches-above-min_match-threshold&quot;&gt;Alternative: Get best matches above ‘min_match’ threshold&lt;/h3&gt;
&lt;p&gt;Maybe having two matching peaks is not good enough and you want to be more certain of your Cosine score based candidates. Let’s then only consider the best Cosine scores for which we have at least min_match* matches:&lt;/p&gt;
&lt;p&gt;min_match = 5**sorted_matches = scores.scores_by_query(spectrums[5], name=“CosineGreedy_score”, sort=True)
best_matches = [x for x in sorted_matches if x[1][“CosineGreedy_matches”] &gt;= min_match][:10][x[1] for x in best_matches]which will give a very different result than the previous run. Here we do not find any other spectrum in the dataset that shows a very high Cosine score (again, except the first entry which is the similarity of the spectrum with itself and hence obviously = 1):&lt;/p&gt;
&lt;p&gt;Out[]:[(1., 30),
(0.44857215, 6),
(0.39605775, 5),
(0.33880658, 5),
(0.03942863, 6),
(0.03429136, 5),
(0.03028157, 5),
(0.02845932, 5),
(0.01924283, 7),
(0.01890612, 5)]&lt;/p&gt;
&lt;h2 id=&quot;4-compute-spectra-similarities-modified-cosine-score&quot;&gt;4. Compute spectra similarities: Modified Cosine score&lt;/h2&gt;
&lt;p&gt;The modified cosine score aims at quantifying the similarity between two mass spectra. Unlike the Cosine score it does not only look at nearly identical spectra, but also considers the mass shift between two compounds. The score is calculated by finding best possible matches between peaks of two spectra. Two peaks are considered a potential match if their m/z ratios lie within the given ‘tolerance’, or if their m/z ratios lie within the tolerance once a mass-shift is applied. The mass shift is simply the difference in precursor-m/z between the two spectra. See &lt;a href=&quot;https://www.pnas.org/content/109/26/E1743&quot;&gt;Watrous et al. (PNAS, 2012)&lt;/a&gt; for further details.&lt;/p&gt;
&lt;p&gt;As done above for the Cosine score, we can calculate the similarities for all possible spectrum pairs by running:&lt;/p&gt;
&lt;p&gt;from matchms.similarity import ModifiedCosinesimilarity_measure = ModifiedCosine(tolerance=0.005)
scores = calculate_scores(spectrums, spectrums, similarity_measure,
is_symmetric=True)Let’s then visualize the results for the first 50 x 50 spectrum pairs.&lt;/p&gt;
&lt;p&gt;scores_array = scores.scores.to_array()plt.figure(figsize=(6,6), dpi=150)
plt.imshow(scores_array[:50, :50][“score”], cmap=“viridis”)
plt.colorbar(shrink=0.7)
plt.title(“Modified Cosine spectra similarities”)
plt.xlabel(“Spectrum #ID”)
plt.ylabel(“Spectrum #ID”)
&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;584&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-b0ee4396.TFNu_jSz_ZuxCvP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 5.** Modified Cosine scores for all possible pairs between the first 50 imported spectrums. As to be expected, the diagonal is always =1 (score for spectrum with itself). But also several other very high Modified Cosine scores stick out suggesting highly related spectra.Now, let’s accept Modified Cosine scores for a minimum number of matching peaks (min_match).&lt;/p&gt;
&lt;p&gt;min_match = 5plt.figure(figsize=(6,6), dpi=150)**plt.imshow(scores_array[:50, :50][“ModifiedCosine_score”] &lt;br&gt;
* (scores_array[:50, :50][“ModifiedCosine_matches”] &gt;= min_match), cmap=“viridis”)
plt.colorbar(shrink=0.7)
plt.title(“Modified Cosine spectra similarities (min_match=5)”)
plt.xlabel(“Spectrum #ID”)
plt.ylabel(“Spectrum #ID”)
&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;607&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-5d737491.DuPLDQy9_ZJDWiI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 6.** Modified Cosine scores for all possible pairs between the first 50 imported spectrums (with ≥ 5 matching peaks!).There’s for instance a bright spot far outside the diagonal for &lt;code&gt;spectrums[11]&lt;/code&gt; so let’s have a look at that one!&lt;/p&gt;
&lt;p&gt;min_match = 5sorted_matches = scores.scores_by_query(spectrums[11], name=“ModifiedCosine_score”, sort=True)**best_matches = [x for x in sorted_matches if x[1][“ModifiedCosine_matches”] &gt;= min_match][:10]
[x[1] for x in best_matches]Which gives&lt;/p&gt;
&lt;p&gt;Out[]:[(1., 151),
(0.95295779, 15),
(0.94542762, 13),
(0.89735889, 17),
(0.7886489, 12),
(0.77433041, 9),
(0.74935776, 8),
(0.72854032, 8),
(0.55896333, 7),
(0.52331993, 9)]And, probably more interesting, the corresponding smiles:&lt;/p&gt;
&lt;p&gt;[x[0].get(“smiles”) for x in best_matches]Out[]:[‘CC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/CC(=O)O&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘CCCCCC(NC(=O)C1CCN(CC1)C(=O)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c2ccc(C)cc2&quot;&gt;C@@H&lt;/a&gt;C(C)C)C(=O)O’,
‘CC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C(=O)O&quot;&gt;C@H&lt;/a&gt;c3ccccc3’,
‘CC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/CCC(=O)N&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘COC(=O)C1CCN(CC1)C(=O)C2CCN(CC2)C(=O)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c3ccc(C)cc3&quot;&gt;C@@H&lt;/a&gt;C(C)C’,
‘CCC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C(=O)O&quot;&gt;C@H&lt;/a&gt;c3ccccc3’,
‘CC(C)C&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/C(C)C&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘CC(C)C&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/Cc3ccccc3&quot;&gt;C@@H&lt;/a&gt;C(=O)O’,
‘CCC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N3CCC(CC3)C(=O)N’,
‘CCC(C)&lt;a href=&quot;https://blog2.esciencecenter.nl/posts/NS(=O)(=O)c1ccc(C)cc1&quot;&gt;C@H&lt;/a&gt;C(=O)N2CCC(CC2)C(=O)N3CCC(CC3)C(=O)OC’]OK, smiles, nice. But let’s better move on and have a look at how those compounds actually look like (as above, plotted using rdkit):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Build your own mass spectrometry analysis pipeline in Python using matchms — part I&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;548&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-f6234fec.BUqASEbP_Z2ulvye.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 7.** Compounds of the highest 9 modified Cosine scores within the dataset with respect to spectrums[11], the first being the spectrum of interest itself (hence “query compound”).I wouldn’t dare calling myself a natural product expert. But those chemical structures clearly do look more consistent to what we saw in Figure 4…&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now it’s up to you to come up with things to do with this ;)&lt;/p&gt;
&lt;p&gt;I hope this helped you getting started with using &lt;em&gt;&lt;strong&gt;matchms&lt;/strong&gt;&lt;/em&gt; for working with your MS/MS data! Soon there will be additional tutorials to go a bit more depth:&lt;/p&gt;
&lt;h2 id=&quot;other-parts-of-this-tutorial&quot;&gt;Other parts of this tutorial&lt;/h2&gt;
&lt;h3 id=&quot;part-i--build-you-own-mass-spectrometry-pipeline&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-your-own-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-i-d96c718c68ee&quot;&gt;part I — Build you own mass spectrometry pipeline&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-ii--compute-spectra-similarities-using-spec2vec&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-ii-spec2vec-8aa639571018&quot;&gt;part II — Compute spectra similarities using Spec2Vec&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;part-iii--network-analysis-based-on-spectra-similarities&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/build-a-mass-spectrometry-analysis-pipeline-in-python-using-matchms-part-iii-molecular-91891248ee34&quot;&gt;part III — Network analysis based on spectra similarities&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;matchms-library&quot;&gt;matchms library&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;matchms&lt;/strong&gt;&lt;/em&gt; is freely available and open-source. You can find the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;code on Github&lt;/a&gt;, the package is available as &lt;a href=&quot;https://anaconda.org/nlesc/matchms&quot;&gt;conda package&lt;/a&gt; (recommended) or &lt;a href=&quot;https://pypi.org/project/matchms/&quot;&gt;from pypi&lt;/a&gt;. It was developed by a bunch of very nice people (see &lt;a href=&quot;https://github.com/matchms/matchms/blob/master/CITATION.cff&quot;&gt;here&lt;/a&gt;) and is &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;published in Joss&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can find more information in the &lt;a href=&quot;https://matchms.readthedocs.io/en/latest/&quot;&gt;matchms documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;code&quot;&gt;Code&lt;/h3&gt;
&lt;p&gt;The code shown in this blog post can also be found as &lt;a href=&quot;https://github.com/matchms/matchms/blob/tutorial/tutorial/matchms_tutorial_01_building_analysis_pipeline.ipynb&quot;&gt;a Jupyter notebook here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;help-us-develop-matchms-further&quot;&gt;Help us develop matchms further!&lt;/h3&gt;
&lt;p&gt;We really hope that matchms will help people to build new, better analysis pipelines. So, please help us to further improve matchms. You can help us by &lt;strong&gt;(1)&lt;/strong&gt; Cite our work if you use our package for your research: &lt;a href=&quot;https://joss.theoj.org/papers/10.21105/joss.02411&quot;&gt;matchms article in JOSS&lt;/a&gt;.&lt;strong&gt;(2)&lt;/strong&gt; Let us know if you run into any issues using matchms, or if you are missing any key functionalities! You can simply do so by starting a new issue on the &lt;a href=&quot;https://github.com/matchms/matchms&quot;&gt;matchms GitHub repository,&lt;/a&gt; or contact me on twitter &lt;a href=&quot;https://twitter.com/me_datapoint?lang=en&quot;&gt;@me_datapoint&lt;/a&gt;.&lt;strong&gt;You are of course more than welcome to also become an active contributor to the package and help extend its functionality!
(3)&lt;/strong&gt; Please let us know if you successfully applied matchms in your research project (makes us happy + we can maybe share the good news!).&lt;/p&gt;
&lt;p&gt;Thanks a lot!&lt;/p&gt;
&lt;p&gt;I would like to thank [Carlos Martinez-Ortiz,] [Jorislouwen], Niek de Jonge, [Justin van der Hooft] for helpful comments and suggestions on this blog post.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/build-your-own-mass-spectrometry-analysi-b73e3c5e.DXzNQPN6.png" medium="image"/><author>Florian Huber</author></item><item><title>An applied mathematician meets software engineering</title><link>https://blog2.esciencecenter.nl/posts/2023-01-26---an-applied-mathematician-meets-software-engineering</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-01-26---an-applied-mathematician-meets-software-engineering</guid><description>&lt;p&gt;How software engineering practices helped me bridge the gap between mathematics and other fields&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_cJAE3sgoAlTXMc4E-ebafd1fe.DtApvtee_ZmMywD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Mick Haupt on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;from-industry-to-academia&quot;&gt;From industry to academia&lt;/h2&gt;
&lt;p&gt;Let’s go backward to 2015. Back then, I had a degree in theoretical &lt;strong&gt;physics&lt;/strong&gt; and a 3-year professional experience in industrial software &lt;strong&gt;engineering&lt;/strong&gt;. All of it spiced with many semi-professional activities in &lt;strong&gt;science communication&lt;/strong&gt;. At the end of that year, I was hired as an applied &lt;strong&gt;mathematician&lt;/strong&gt; at an aquatic &lt;strong&gt;ecology&lt;/strong&gt; department, in order to perform a PhD.&lt;/p&gt;
&lt;p&gt;In short: physics, engineering, communication, mathematics, and ecology, … it was the quintessential multidisciplinary job.&lt;/p&gt;
&lt;p&gt;As often happens, one of the disciplines was overrepresented. This happened just naturally: I was working in an aquatic ecology group, inside an ecology building, on a campus specialized in biology, in a city nicknamed “the city of life sciences”. So biologists outnumbered non-biologists at around a 9 to 1 ratio. Indeed, I was the only physicist in the group, and also the only one with engineering experience. This meant that I was expected to adapt my academic culture to theirs, not the other way around. And rightfully so. Summarizing: my (mostly) mathematical background was required to produce publications interesting for an audience of (mostly) biologists.&lt;/p&gt;
&lt;p&gt;What about the biologists’ mathematical background? Well, something I learned is that any preconceived assumption in this direction will fail. Some biologists just don’t like mathematics (just like many other humans), while others are really interested and proficient at it. One way or another, I was supposed to provide mathematical content and tools for all of them. And this posed a serious problem: how could I possibly do that without frustrating the former or boring the latter?&lt;/p&gt;
&lt;p&gt;Talking about frustration, I should also not forget about frustrating the reader. It is time to stop talking about myself and dive into an example.&lt;/p&gt;
&lt;h2 id=&quot;tracking-bugs-the-many-legged-ones&quot;&gt;Tracking bugs (the many-legged ones)&lt;/h2&gt;
&lt;p&gt;One good day, our department bought a fancy tracking device. The purpose was to observe the movements of some tiny invertebrates inside a Petri dish.&lt;/p&gt;
&lt;p&gt;The device was, essentially, a digital camera. It captured several images per second and identified the position of the bug in each of them. Then it returned a list of these positions (&lt;em&gt;x&lt;/em&gt;, &lt;em&gt;y&lt;/em&gt;) and the corresponding sampling time &lt;em&gt;t&lt;/em&gt;. The figure below shows a bug’s trajectory.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;576&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iF9f0KmFW_0FjvLyLi6Eww-b4c83a7e.BeTM0UEr_1LlXdK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example of a bug’s trajectory&lt;/p&gt;
&lt;p&gt;The machine’s output also created some obscure and difficult-to-interpret processed data. Unnecessarily obscure, I would say. This is the kind of situation where multidisciplinarity can do its magic: there is a physicist in the room so, why not use the good-old theory of classical kinematics (the simple, elegant, and centuries-old mathematical tool for describing movement) to extract information directly from the list of positions and times?&lt;/p&gt;
&lt;p&gt;Doing this involved using numerical differentiation to extract information such as instantaneous speed, acceleration, or curvature. Still technical, but way easier to interpret than the data the machine returned by default. I presented the idea to my colleagues. Some of them liked it, while others received it with a bit of skepticism. This is understandable: most people are usually not keen to hear about differentiation and parameterized curves on a coffee break.&lt;/p&gt;
&lt;p&gt;This was when software engineering came to the rescue. What if I code this mathematical knowledge in the form of a software package? This way, the interested enough colleague can dig into the details, while the busy and/or not mathematically oriented one can just trust that the package does its work.&lt;/p&gt;
&lt;p&gt;Having both my two imaginary colleagues in mind, I followed some software engineering &lt;a href=&quot;https://journals.plos.org/plosbiology/article?id=10.1371%2Fjournal.pbio.1001745&quot;&gt;best practices&lt;/a&gt; to make &lt;strong&gt;their&lt;/strong&gt; lives easier. My package was:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Openly published&lt;/strong&gt;. So it was easy to find, install and inspect (and it &lt;a href=&quot;https://github.com/PabRod/kinematics&quot;&gt;still is&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Documented in detail.&lt;/strong&gt; So it is easy to learn the basics, and possible to dive into the details if desired.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Citable.&lt;/strong&gt; So users can cite &lt;a href=&quot;https://zenodo.org/record/5107805#.Y3Y1UNLMKUk&quot;&gt;its DOI&lt;/a&gt; in their publications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Covered by unit tests&lt;/strong&gt;. So trusting the results doesn’t require a huge leap of faith. (What are unit tests? Tiny scripts that check that the package delivers what the developer expects, and that can be run again at any moment. Sounds silly but it is one of the most powerful tools I’ve learned in my stage as a software engineer).&lt;/p&gt;
&lt;p&gt;When written like this, as a proper code package, &lt;strong&gt;the tool solved a problem instead of creating a new one&lt;/strong&gt; (the problem of having to struggle with a new tool from its foundations).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;576&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ml-WjxRKZdgLxPgeWjS2IA-c2570084.F9_oZYck_Zi2lzN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The same trajectory as before, but now “enriched” with extra information, such as absolute speed and absolute acceleration&lt;/p&gt;
&lt;p&gt;Additionally, the package could be applied to any time series representing a two-dimensional movement, so it was useful for problems other than bug tracking on a Petri dish. The package proved to be interesting to other researchers (the metrics say it’s downloaded around 200 times per month), and even managed to get all its way to &lt;a href=&quot;https://cran.r-project.org/web/packages/kinematics/index.html&quot;&gt;CRAN&lt;/a&gt;, the &lt;em&gt;Mons Olympus&lt;/em&gt; of packages in R language.&lt;/p&gt;
&lt;h2 id=&quot;mathematical-talent-locked-in-a-drawer&quot;&gt;Mathematical talent locked in a drawer&lt;/h2&gt;
&lt;p&gt;Let’s imagine a parallel universe in which I never had previous experience as a software engineer. In such a universe, my package would have never taken off. Interestingly though, I’m sure I would have written the code anyways… but I don’t think I would have managed to recruit any users apart from myself. In that universe, my code will be rotting inside some portable hard drive locked in a drawer.&lt;/p&gt;
&lt;p&gt;In that universe, I wouldn’t know anything about software best practices. I know what you are thinking. “Best practices” sounds a bit like “good manners”, something desirable but not strictly necessary. Even less when you have more important stuff to do, such as writing publications. But best practices are necessary… at least if you want your methods to be usable by others, and even by your future self.&lt;/p&gt;
&lt;p&gt;At the eScience Center we often wonder how many brilliant pieces of knowledge follow this sad destiny. Do you have a great algorithm that deserves to fly free? Let us know. Perhaps we can help you!&lt;/p&gt;
&lt;p&gt;Or perhaps you want to try it yourself. If that’s the case, I recommend you start with &lt;a href=&quot;https://journals.plos.org/plosbiology/article?id=10.1371%2Fjournal.pbio.1001745&quot;&gt;&lt;em&gt;Best practices for scientific computing (Wilson, 2014)&lt;/em&gt;&lt;/a&gt;. Also, take a look at the lessons and workshops on computational skills for researchers offered by &lt;a href=&quot;https://software-carpentry.org/&quot;&gt;Software Carpentry&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 26 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;How software engineering practices helped me bridge the gap between mathematics and other fields&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_cJAE3sgoAlTXMc4E-ebafd1fe.DtApvtee_ZmMywD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Mick Haupt on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;from-industry-to-academia&quot;&gt;From industry to academia&lt;/h2&gt;
&lt;p&gt;Let’s go backward to 2015. Back then, I had a degree in theoretical &lt;strong&gt;physics&lt;/strong&gt; and a 3-year professional experience in industrial software &lt;strong&gt;engineering&lt;/strong&gt;. All of it spiced with many semi-professional activities in &lt;strong&gt;science communication&lt;/strong&gt;. At the end of that year, I was hired as an applied &lt;strong&gt;mathematician&lt;/strong&gt; at an aquatic &lt;strong&gt;ecology&lt;/strong&gt; department, in order to perform a PhD.&lt;/p&gt;
&lt;p&gt;In short: physics, engineering, communication, mathematics, and ecology, … it was the quintessential multidisciplinary job.&lt;/p&gt;
&lt;p&gt;As often happens, one of the disciplines was overrepresented. This happened just naturally: I was working in an aquatic ecology group, inside an ecology building, on a campus specialized in biology, in a city nicknamed “the city of life sciences”. So biologists outnumbered non-biologists at around a 9 to 1 ratio. Indeed, I was the only physicist in the group, and also the only one with engineering experience. This meant that I was expected to adapt my academic culture to theirs, not the other way around. And rightfully so. Summarizing: my (mostly) mathematical background was required to produce publications interesting for an audience of (mostly) biologists.&lt;/p&gt;
&lt;p&gt;What about the biologists’ mathematical background? Well, something I learned is that any preconceived assumption in this direction will fail. Some biologists just don’t like mathematics (just like many other humans), while others are really interested and proficient at it. One way or another, I was supposed to provide mathematical content and tools for all of them. And this posed a serious problem: how could I possibly do that without frustrating the former or boring the latter?&lt;/p&gt;
&lt;p&gt;Talking about frustration, I should also not forget about frustrating the reader. It is time to stop talking about myself and dive into an example.&lt;/p&gt;
&lt;h2 id=&quot;tracking-bugs-the-many-legged-ones&quot;&gt;Tracking bugs (the many-legged ones)&lt;/h2&gt;
&lt;p&gt;One good day, our department bought a fancy tracking device. The purpose was to observe the movements of some tiny invertebrates inside a Petri dish.&lt;/p&gt;
&lt;p&gt;The device was, essentially, a digital camera. It captured several images per second and identified the position of the bug in each of them. Then it returned a list of these positions (&lt;em&gt;x&lt;/em&gt;, &lt;em&gt;y&lt;/em&gt;) and the corresponding sampling time &lt;em&gt;t&lt;/em&gt;. The figure below shows a bug’s trajectory.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;576&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iF9f0KmFW_0FjvLyLi6Eww-b4c83a7e.BeTM0UEr_1LlXdK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example of a bug’s trajectory&lt;/p&gt;
&lt;p&gt;The machine’s output also created some obscure and difficult-to-interpret processed data. Unnecessarily obscure, I would say. This is the kind of situation where multidisciplinarity can do its magic: there is a physicist in the room so, why not use the good-old theory of classical kinematics (the simple, elegant, and centuries-old mathematical tool for describing movement) to extract information directly from the list of positions and times?&lt;/p&gt;
&lt;p&gt;Doing this involved using numerical differentiation to extract information such as instantaneous speed, acceleration, or curvature. Still technical, but way easier to interpret than the data the machine returned by default. I presented the idea to my colleagues. Some of them liked it, while others received it with a bit of skepticism. This is understandable: most people are usually not keen to hear about differentiation and parameterized curves on a coffee break.&lt;/p&gt;
&lt;p&gt;This was when software engineering came to the rescue. What if I code this mathematical knowledge in the form of a software package? This way, the interested enough colleague can dig into the details, while the busy and/or not mathematically oriented one can just trust that the package does its work.&lt;/p&gt;
&lt;p&gt;Having both my two imaginary colleagues in mind, I followed some software engineering &lt;a href=&quot;https://journals.plos.org/plosbiology/article?id=10.1371%2Fjournal.pbio.1001745&quot;&gt;best practices&lt;/a&gt; to make &lt;strong&gt;their&lt;/strong&gt; lives easier. My package was:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Openly published&lt;/strong&gt;. So it was easy to find, install and inspect (and it &lt;a href=&quot;https://github.com/PabRod/kinematics&quot;&gt;still is&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Documented in detail.&lt;/strong&gt; So it is easy to learn the basics, and possible to dive into the details if desired.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Citable.&lt;/strong&gt; So users can cite &lt;a href=&quot;https://zenodo.org/record/5107805#.Y3Y1UNLMKUk&quot;&gt;its DOI&lt;/a&gt; in their publications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Covered by unit tests&lt;/strong&gt;. So trusting the results doesn’t require a huge leap of faith. (What are unit tests? Tiny scripts that check that the package delivers what the developer expects, and that can be run again at any moment. Sounds silly but it is one of the most powerful tools I’ve learned in my stage as a software engineer).&lt;/p&gt;
&lt;p&gt;When written like this, as a proper code package, &lt;strong&gt;the tool solved a problem instead of creating a new one&lt;/strong&gt; (the problem of having to struggle with a new tool from its foundations).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;576&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ml-WjxRKZdgLxPgeWjS2IA-c2570084.F9_oZYck_Zi2lzN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The same trajectory as before, but now “enriched” with extra information, such as absolute speed and absolute acceleration&lt;/p&gt;
&lt;p&gt;Additionally, the package could be applied to any time series representing a two-dimensional movement, so it was useful for problems other than bug tracking on a Petri dish. The package proved to be interesting to other researchers (the metrics say it’s downloaded around 200 times per month), and even managed to get all its way to &lt;a href=&quot;https://cran.r-project.org/web/packages/kinematics/index.html&quot;&gt;CRAN&lt;/a&gt;, the &lt;em&gt;Mons Olympus&lt;/em&gt; of packages in R language.&lt;/p&gt;
&lt;h2 id=&quot;mathematical-talent-locked-in-a-drawer&quot;&gt;Mathematical talent locked in a drawer&lt;/h2&gt;
&lt;p&gt;Let’s imagine a parallel universe in which I never had previous experience as a software engineer. In such a universe, my package would have never taken off. Interestingly though, I’m sure I would have written the code anyways… but I don’t think I would have managed to recruit any users apart from myself. In that universe, my code will be rotting inside some portable hard drive locked in a drawer.&lt;/p&gt;
&lt;p&gt;In that universe, I wouldn’t know anything about software best practices. I know what you are thinking. “Best practices” sounds a bit like “good manners”, something desirable but not strictly necessary. Even less when you have more important stuff to do, such as writing publications. But best practices are necessary… at least if you want your methods to be usable by others, and even by your future self.&lt;/p&gt;
&lt;p&gt;At the eScience Center we often wonder how many brilliant pieces of knowledge follow this sad destiny. Do you have a great algorithm that deserves to fly free? Let us know. Perhaps we can help you!&lt;/p&gt;
&lt;p&gt;Or perhaps you want to try it yourself. If that’s the case, I recommend you start with &lt;a href=&quot;https://journals.plos.org/plosbiology/article?id=10.1371%2Fjournal.pbio.1001745&quot;&gt;&lt;em&gt;Best practices for scientific computing (Wilson, 2014)&lt;/em&gt;&lt;/a&gt;. Also, take a look at the lessons and workshops on computational skills for researchers offered by &lt;a href=&quot;https://software-carpentry.org/&quot;&gt;Software Carpentry&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_iF9f0KmFW_0FjvLyLi6Eww-b4c83a7e.BeTM0UEr.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Why internships have a large impact</title><link>https://blog2.esciencecenter.nl/posts/2023-01-19---why-internships-have-a-large-impact</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-01-19---why-internships-have-a-large-impact</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_LDbeTgeB_nX3mscs-40d92b52.CXCwdMj2_Z12d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Scott Graham on Unsplash&lt;/p&gt;
&lt;p&gt;One and a half years ago I finished my internship at the eScience Center. Based on my own experiences and those of others around me, I think that internships are a unique moment in anyone’s career. The lessons learned during this period have a big impact on your professional future.&lt;/p&gt;
&lt;p&gt;In my case, the main lesson learned was the importance of code quality for making it impactful in science. Instead of just getting code to work, I learned the value of good quality code for making it maintainable and reusable, thereby increasing the impact in my scientific field.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Timing is perfect&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By learning the abovementioned skills during my internship I can focus on this aspect during my PhD and truly put this lesson into action. Besides this being a very good lesson to learn in general, I think the timing of learning this during my internship actually increased the effect this lesson will have on me and on the work I do. I think this makes my personal experience a relevant example of the impact that valuable lessons can have during internships.&lt;/p&gt;
&lt;p&gt;The first reason why the timing of an internship will increase the impact is that it is very early in a career. This means that there is still a lot of room to learn new skills, and most importantly, to actually apply these skills. Especially in science, a lot of the work is done by PhD students. Therefore, learning these skills before the start of your PhD is crucial to actually still having time to apply them.&lt;/p&gt;
&lt;p&gt;But, what makes the timing of an internship so unique? If the earlier you learn something the more impact it has, why not learn it during your bachelor? Why not in high school or even earlier? The answer is that there are many unique lessons that are only valuable for very specific fields and you simply cannot learn all of them in one bachelor. Nowadays in science, you need to specialize a lot, and this makes a lesson only valuable if it is thought to someone that actually continues in a career where this lesson is relevant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Spreading the word&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The second reason why a lesson learned in an internship can have a large impact is that a good lesson is also shared with colleagues and other students. Thereby any lesson you learn not only has an impact on yourself, but also on anyone else you teach. For instance, I started working as a PhD student in a bioinformatics group. Now, 1 year in, I have supervised two students and shared advice on improving code quality with them. I also shared this with multiple direct colleagues that currently implement these lessons and teach them to others. In the same way, I learn from the lessons my supervisors and direct colleagues learned.&lt;/p&gt;
&lt;p&gt;The fact that teaching others can truly increase impact can also be used as an argument to teach important lessons to people further along in their careers. Why not try to teach new lessons to a professor, or a postdoc, so they can teach the lesson learned to as many PhDs as possible, so they can spread this again? What makes this difficult is that to truly understand the value of a skill it is crucial to actually apply it. For a postdoc or a professor, it will be very difficult to find the time to get familiar enough with the lesson to be able to efficiently teach it to others as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Considering an internship?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Internships are a unique moment in your career. You are far enough in your studies that you will likely continue in a specific field, but early enough that you still have the time to learn new skills and really put them into practice. My advice to anyone starting an internship is to use this time to invest in learning new skills. I also have some advice for companies: take teaching your interns seriously, since this might have a bigger impact than you think.&lt;/p&gt;</description><pubDate>Thu, 19 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_LDbeTgeB_nX3mscs-40d92b52.CXCwdMj2_Z12d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Scott Graham on Unsplash&lt;/p&gt;
&lt;p&gt;One and a half years ago I finished my internship at the eScience Center. Based on my own experiences and those of others around me, I think that internships are a unique moment in anyone’s career. The lessons learned during this period have a big impact on your professional future.&lt;/p&gt;
&lt;p&gt;In my case, the main lesson learned was the importance of code quality for making it impactful in science. Instead of just getting code to work, I learned the value of good quality code for making it maintainable and reusable, thereby increasing the impact in my scientific field.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Timing is perfect&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By learning the abovementioned skills during my internship I can focus on this aspect during my PhD and truly put this lesson into action. Besides this being a very good lesson to learn in general, I think the timing of learning this during my internship actually increased the effect this lesson will have on me and on the work I do. I think this makes my personal experience a relevant example of the impact that valuable lessons can have during internships.&lt;/p&gt;
&lt;p&gt;The first reason why the timing of an internship will increase the impact is that it is very early in a career. This means that there is still a lot of room to learn new skills, and most importantly, to actually apply these skills. Especially in science, a lot of the work is done by PhD students. Therefore, learning these skills before the start of your PhD is crucial to actually still having time to apply them.&lt;/p&gt;
&lt;p&gt;But, what makes the timing of an internship so unique? If the earlier you learn something the more impact it has, why not learn it during your bachelor? Why not in high school or even earlier? The answer is that there are many unique lessons that are only valuable for very specific fields and you simply cannot learn all of them in one bachelor. Nowadays in science, you need to specialize a lot, and this makes a lesson only valuable if it is thought to someone that actually continues in a career where this lesson is relevant.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Spreading the word&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The second reason why a lesson learned in an internship can have a large impact is that a good lesson is also shared with colleagues and other students. Thereby any lesson you learn not only has an impact on yourself, but also on anyone else you teach. For instance, I started working as a PhD student in a bioinformatics group. Now, 1 year in, I have supervised two students and shared advice on improving code quality with them. I also shared this with multiple direct colleagues that currently implement these lessons and teach them to others. In the same way, I learn from the lessons my supervisors and direct colleagues learned.&lt;/p&gt;
&lt;p&gt;The fact that teaching others can truly increase impact can also be used as an argument to teach important lessons to people further along in their careers. Why not try to teach new lessons to a professor, or a postdoc, so they can teach the lesson learned to as many PhDs as possible, so they can spread this again? What makes this difficult is that to truly understand the value of a skill it is crucial to actually apply it. For a postdoc or a professor, it will be very difficult to find the time to get familiar enough with the lesson to be able to efficiently teach it to others as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Considering an internship?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Internships are a unique moment in your career. You are far enough in your studies that you will likely continue in a specific field, but early enough that you still have the time to learn new skills and really put them into practice. My advice to anyone starting an internship is to use this time to invest in learning new skills. I also have some advice for companies: take teaching your interns seriously, since this might have a bigger impact than you think.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_LDbeTgeB_nX3mscs-40d92b52.CXCwdMj2.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>The Data Science Centre: Digital expertise Hub at UvA</title><link>https://blog2.esciencecenter.nl/posts/2023-01-12---the-data-science-centre-digital-expertise-hub-at-uva</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2023-01-12---the-data-science-centre-digital-expertise-hub-at-uva</guid><description>&lt;p&gt;This week, we interviewed &lt;a href=&quot;https://dsc.uva.nl/content/news/2022/06/interview-with-data-science-community-manager-lisa-yu.html&quot;&gt;Lisa Yu&lt;/a&gt;, Community Manager of the Data Science Center (DSC). The DSC is a coordinating hub within the University of Amsterdam (UvA) Library, launched in 2021. The need for software and skills that make researchers able to adequately deal with available data continues to grow across all research disciplines. Thanks to funding provided by the UvA Executive Board, the DSC is in a position to boost digitally driven research at UvA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What are the DSC’s most important activities?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1078&quot; height=&quot;252&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yEpWKc90PA3cJ3R-ZL1KjQ-4bc4c1fe.jieQD0mY_Z13fEXo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo caption: Data Science Day 2022, photographed by Monique Kooijmans&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lisa:&lt;/em&gt; The DSC hosts a variety of important activities throughout the year. In the autumn of 2022, we held our &lt;a href=&quot;https://dsc.uva.nl/content/news/2022/11/data-science-day-2022.html&quot;&gt;second annual Data Science Day&lt;/a&gt; at Startup Village in Amsterdam Science Park. More than 100 attendees from within and outside of UvA participated in this action-packed event, which consisted of morning workshops, keynote presentations and pitch presentations on a variety of data science topics.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;364&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KDJrC4sOgTTPld2cbyvlkg-54fc37ba.Bp2jqxAM_ZosolL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data Science Centre Hackathon 2022, photographed by Monique Kooijmans&lt;/p&gt;
&lt;p&gt;Our weekly &lt;a href=&quot;https://dsc.uva.nl/programmes/coffee-and-data/coffee-and-data.html&quot;&gt;Friday Coffee and Data meet-ups&lt;/a&gt; are also very important. These meet-ups are for our DSC members and consist of free workshops and training like the &lt;a href=&quot;https://software-carpentry.org/lessons/&quot;&gt;Software Carpentry&lt;/a&gt; and Image Analysis, seminar presentations by DSC members, and collaboration sessions. Beyond this being an upskilling opportunity, it is also a chance for members to meet like-minded people from other faculties and campuses and to collaborate with each other.&lt;/p&gt;
&lt;p&gt;We update our events page regularly online, so &lt;a href=&quot;https://dsc.uva.nl/&quot;&gt;check our website&lt;/a&gt; regularly for all our upcoming planned activities!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you have an example of how the DSC has helped researchers at UvA?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our ultimate goal is to accelerate software and data-driven research at UvA, and help researchers do research they wouldn’t have otherwise been able to do. One example of how the DSC has helped achieve this is through its &lt;a href=&quot;https://dsc.uva.nl/programmes/accelerate-programme/accelerate-programme.html&quot;&gt;Accelerate programme&lt;/a&gt;, where we co-finance the hiring of data scientists (who have roles comparable to research software engineers, ed.) and data engineers within faculties.&lt;/p&gt;
&lt;p&gt;Since its launch in 2021, the Accelerate programme has led to the successful hiring of the equivalent of 18 FTE data scientists and engineers across a range of UvA faculties. The Accelerate programme has helped fund lots of cool research, ranging from how to better understand the history of early globalization and colonisation, to why people follow and break rules, to growing tomatoes!&lt;/p&gt;
&lt;p&gt;Another example of how we have helped researchers at UvA is through our Interdisciplinary PhD programme, where we have provided funding for 7 PhD students to work on a selection of interdisciplinary research projects. &lt;a href=&quot;https://dsc.uva.nl/programmes/interdisciplinary-phd-programme/interdisciplinary-phd-programme.html&quot;&gt;More information about these projects and its collaborators is listed on our website&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There are many institutes that may want to increase their capacity and attention for data science and research software. What did the Data Science Centre do to make this a success at UvA? What do you think others in their position could learn from their experience?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I believe that one of the biggest contributing factors behind the DSC’s success so far is our strong focus on community building and engagement. Our DSC community members are at the heart of everything we do, and we are always in regular interaction with our members, whether it be via our Slack channel, Friday meet-ups, DSC weekly bulletin, or DSC Twitter. This regular interaction also helps us ensure that the activities we plan reflect the needs and wants of the community — for instance, we ask members to vote on what topics they want to receive training on, and then we plan the workshop curriculum based on this feedback.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;409&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_egOD2JPhMwg2Yq6VhTtiGg-7f7b3975.C4Q2WFrC_qN0nA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data Science Centre Away Day in Zaandam&lt;/p&gt;
&lt;p&gt;I also think that we have found a perfect home at the University Library. Firstly, the Library already provides a range of tailored and hands-on data science support to researchers and faculties, which means that the DSC can leverage the available expertise in the field of data management.&lt;/p&gt;
&lt;p&gt;Being a part of the University Library also means that we can access its facility services, wide network within UvA, and gain practical support with the communication and logistical coordination of our events and activities (such as Data Science Day). This affords our team greater capacity to drive all the different initiatives and activities that we want to organise for the community at UvA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are the plans for the future of the DSC?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since our launch in 2021, we have achieved great progress in building a strong data science community and presence at UvA.&lt;/p&gt;
&lt;p&gt;Looking ahead, we want to continue growing the DSC community and giving our members as many opportunities as possible to upskill and further develop their expertise.&lt;/p&gt;
&lt;p&gt;This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expanding our workshop and training support programme&lt;/li&gt;
&lt;li&gt;Continuing to embed data scientists and/or engineers across all research disciplines via the Accelerate programme (by 2025, we aim to have 35 dedicated data scientists and/or engineers across UvA faculties)&lt;/li&gt;
&lt;li&gt;Leverage our partnerships with local, national and international data-science organisations to further stimulate more interdisciplinary and interorganisational data science collaborations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also welcome new collaborations and partnerships! If you are interested in collaborating with us or learning more about what we do, then please contact us at &lt;a href=&quot;mailto:dsc@uva.nl&quot;&gt;dsc@uva.nl&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who is the Data Science Centre staffed by?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The DSC coordinating team consists of our Scientific Director Prof. Paul Groth, Max Haring (Head of Education and Research Support at the University Library), Boy Menist (Operational Director), Eva Lekkerkerker (Digital Skills Coordinator — maternity leave cover for Iris van der Knaap), the University Library Communications team, and a representative from the Social and Behavioural Data Science Centre which is a DSC hub. What I like most about my team is that we all come from varied backgrounds, and therefore can bring very diverse expertise to the table.&lt;/p&gt;</description><pubDate>Thu, 12 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This week, we interviewed &lt;a href=&quot;https://dsc.uva.nl/content/news/2022/06/interview-with-data-science-community-manager-lisa-yu.html&quot;&gt;Lisa Yu&lt;/a&gt;, Community Manager of the Data Science Center (DSC). The DSC is a coordinating hub within the University of Amsterdam (UvA) Library, launched in 2021. The need for software and skills that make researchers able to adequately deal with available data continues to grow across all research disciplines. Thanks to funding provided by the UvA Executive Board, the DSC is in a position to boost digitally driven research at UvA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Q: What are the DSC’s most important activities?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1078&quot; height=&quot;252&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yEpWKc90PA3cJ3R-ZL1KjQ-4bc4c1fe.jieQD0mY_Z13fEXo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo caption: Data Science Day 2022, photographed by Monique Kooijmans&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Lisa:&lt;/em&gt; The DSC hosts a variety of important activities throughout the year. In the autumn of 2022, we held our &lt;a href=&quot;https://dsc.uva.nl/content/news/2022/11/data-science-day-2022.html&quot;&gt;second annual Data Science Day&lt;/a&gt; at Startup Village in Amsterdam Science Park. More than 100 attendees from within and outside of UvA participated in this action-packed event, which consisted of morning workshops, keynote presentations and pitch presentations on a variety of data science topics.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;364&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KDJrC4sOgTTPld2cbyvlkg-54fc37ba.Bp2jqxAM_ZosolL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data Science Centre Hackathon 2022, photographed by Monique Kooijmans&lt;/p&gt;
&lt;p&gt;Our weekly &lt;a href=&quot;https://dsc.uva.nl/programmes/coffee-and-data/coffee-and-data.html&quot;&gt;Friday Coffee and Data meet-ups&lt;/a&gt; are also very important. These meet-ups are for our DSC members and consist of free workshops and training like the &lt;a href=&quot;https://software-carpentry.org/lessons/&quot;&gt;Software Carpentry&lt;/a&gt; and Image Analysis, seminar presentations by DSC members, and collaboration sessions. Beyond this being an upskilling opportunity, it is also a chance for members to meet like-minded people from other faculties and campuses and to collaborate with each other.&lt;/p&gt;
&lt;p&gt;We update our events page regularly online, so &lt;a href=&quot;https://dsc.uva.nl/&quot;&gt;check our website&lt;/a&gt; regularly for all our upcoming planned activities!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do you have an example of how the DSC has helped researchers at UvA?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our ultimate goal is to accelerate software and data-driven research at UvA, and help researchers do research they wouldn’t have otherwise been able to do. One example of how the DSC has helped achieve this is through its &lt;a href=&quot;https://dsc.uva.nl/programmes/accelerate-programme/accelerate-programme.html&quot;&gt;Accelerate programme&lt;/a&gt;, where we co-finance the hiring of data scientists (who have roles comparable to research software engineers, ed.) and data engineers within faculties.&lt;/p&gt;
&lt;p&gt;Since its launch in 2021, the Accelerate programme has led to the successful hiring of the equivalent of 18 FTE data scientists and engineers across a range of UvA faculties. The Accelerate programme has helped fund lots of cool research, ranging from how to better understand the history of early globalization and colonisation, to why people follow and break rules, to growing tomatoes!&lt;/p&gt;
&lt;p&gt;Another example of how we have helped researchers at UvA is through our Interdisciplinary PhD programme, where we have provided funding for 7 PhD students to work on a selection of interdisciplinary research projects. &lt;a href=&quot;https://dsc.uva.nl/programmes/interdisciplinary-phd-programme/interdisciplinary-phd-programme.html&quot;&gt;More information about these projects and its collaborators is listed on our website&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There are many institutes that may want to increase their capacity and attention for data science and research software. What did the Data Science Centre do to make this a success at UvA? What do you think others in their position could learn from their experience?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I believe that one of the biggest contributing factors behind the DSC’s success so far is our strong focus on community building and engagement. Our DSC community members are at the heart of everything we do, and we are always in regular interaction with our members, whether it be via our Slack channel, Friday meet-ups, DSC weekly bulletin, or DSC Twitter. This regular interaction also helps us ensure that the activities we plan reflect the needs and wants of the community — for instance, we ask members to vote on what topics they want to receive training on, and then we plan the workshop curriculum based on this feedback.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;409&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_egOD2JPhMwg2Yq6VhTtiGg-7f7b3975.C4Q2WFrC_qN0nA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data Science Centre Away Day in Zaandam&lt;/p&gt;
&lt;p&gt;I also think that we have found a perfect home at the University Library. Firstly, the Library already provides a range of tailored and hands-on data science support to researchers and faculties, which means that the DSC can leverage the available expertise in the field of data management.&lt;/p&gt;
&lt;p&gt;Being a part of the University Library also means that we can access its facility services, wide network within UvA, and gain practical support with the communication and logistical coordination of our events and activities (such as Data Science Day). This affords our team greater capacity to drive all the different initiatives and activities that we want to organise for the community at UvA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are the plans for the future of the DSC?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since our launch in 2021, we have achieved great progress in building a strong data science community and presence at UvA.&lt;/p&gt;
&lt;p&gt;Looking ahead, we want to continue growing the DSC community and giving our members as many opportunities as possible to upskill and further develop their expertise.&lt;/p&gt;
&lt;p&gt;This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expanding our workshop and training support programme&lt;/li&gt;
&lt;li&gt;Continuing to embed data scientists and/or engineers across all research disciplines via the Accelerate programme (by 2025, we aim to have 35 dedicated data scientists and/or engineers across UvA faculties)&lt;/li&gt;
&lt;li&gt;Leverage our partnerships with local, national and international data-science organisations to further stimulate more interdisciplinary and interorganisational data science collaborations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We also welcome new collaborations and partnerships! If you are interested in collaborating with us or learning more about what we do, then please contact us at &lt;a href=&quot;mailto:dsc@uva.nl&quot;&gt;dsc@uva.nl&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Who is the Data Science Centre staffed by?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The DSC coordinating team consists of our Scientific Director Prof. Paul Groth, Max Haring (Head of Education and Research Support at the University Library), Boy Menist (Operational Director), Eva Lekkerkerker (Digital Skills Coordinator — maternity leave cover for Iris van der Knaap), the University Library Communications team, and a representative from the Social and Behavioural Data Science Centre which is a DSC hub. What I like most about my team is that we all come from varied backgrounds, and therefore can bring very diverse expertise to the table.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_yEpWKc90PA3cJ3R-ZL1KjQ-4bc4c1fe.jieQD0mY.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Ceci n’est pas une peinture — making art with AI</title><link>https://blog2.esciencecenter.nl/posts/2022-12-19---ceci-nest-pas-une-peinture-making-art-with-ai</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-12-19---ceci-nest-pas-une-peinture-making-art-with-ai</guid><description>&lt;p&gt;Over time, the model ultimately learns how to discriminate between these two groups (Van Gogh vs. other) and outputs the probability that a new observation belongs to the Van Gogh’s category. To do so, however, discriminative modelling requires that each observation in training must have a label, i.e., all Van Gogh’s paintings are labelled as 1, and non-Van Gogh paintings as 0.&lt;/p&gt;
&lt;p&gt;Generative models instead don’t need a labelled dataset¹: they output sets of pixels, I.e. other images, and are trained to minimize the difference between the images they produce and the images they are trained on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Key points:&lt;/p&gt;
&lt;p&gt;In other words, the key difference between discriminative and generative modelling is that while the former attempts to estimate the probability that an observation &lt;em&gt;&lt;strong&gt;x&lt;/strong&gt;&lt;/em&gt; (pixel) belongs to the learned category &lt;em&gt;&lt;strong&gt;y&lt;/strong&gt;&lt;/em&gt;(Van Gogh), the latter instead attempts to estimate the probability of seeing the observation &lt;em&gt;&lt;strong&gt;x&lt;/strong&gt;&lt;/em&gt; (pixel) at all.&lt;/p&gt;
&lt;p&gt;Once trained, generative models can be used to produce completely novel images that share features with the training set. What the model learns is a highly sophisticated method for interpolating images: Not magic, but impressive, nonetheless.&lt;/p&gt;
&lt;h3 id=&quot;good-artists-copy-great-artists-steal&quot;&gt;Good artists copy, great artists steal&lt;/h3&gt;
&lt;p&gt;Since the AI is trained on images pulled from the internet, it learns from a store of pictures that people have chosen to share. As a consequence, the blind use of these models often reveals how deeply social bias is baked into our data sets. For example, OpenAI has found that &lt;a href=&quot;https://industrywired.com/for-the-nurse-prompt-dall-e-will-only-show-a-woman-exploring-ai-bias/&quot;&gt;prompting the word “Nurse” will always show a woman, while the word “CEO” always a man&lt;/a&gt;. Bias doesn’t seem to be limited to gender, but &lt;a href=&quot;https://analyticsindiamag.com/midjourney-is-biased/&quot;&gt;encompasses race as well&lt;/a&gt;&lt;a href=&quot;https://analyticsindiamag.com/midjourney-is-biased/&quot;&gt;.&lt;/a&gt;.) One solution to this is to provide a more socially and ethnically diverse training dataset that would comprehend different ethnicities and gender descriptions.&lt;/p&gt;
&lt;p&gt;More concerning on the long term, however, is the potential of these tools to create misinformation. In a &lt;a href=&quot;https://www.proquest.com/docview/2190341785?pq-origsite=gscholar&amp;#x26;fromopenview=true&quot;&gt;test&lt;/a&gt; run at Art Basel in 2016— an annual fair showcasing contemporary art — the authors of &lt;a href=&quot;https://www.aican.io/&quot;&gt;AICAN&lt;/a&gt; (Artificial Intelligence Creative Adversarial Network) showed that people were very often unable to tell the difference between AICAN generated images and artworks produced by a human artist (see also Tidio’s recent &lt;a href=&quot;https://www.tidio.com/blog/ai-test/&quot;&gt;test&lt;/a&gt; confirming this trend). This suggests that the share of “visual literacy” in the public is not very high and may pose a risk in a society that hasn’t integrated more sophisticated tools to tell apart humans- vs AI- generated images in our daily life.&lt;/p&gt;
&lt;p&gt;Aside from these ethical concerns, there is also the question of plagiarism. The training dataset is obtained by web scraping millions of images that are necessarily made by someone else. This suggests a form of plagiarism which affects artists who upload their works to the internet (perhaps for self-promotion) and that may be unaware of helping an AI to become their competitors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Ceci n’est pas une peinture — making art with AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;703&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/ceci-nest-pas-une-peinture-making-art-wi-91e9b380.CypOwWjt_1iUceM.webp&quot; srcset=&quot;&quot;&gt;
The Portrait of Edmond Belamy &lt;a href=&quot;https://www.christies.com/features/A-collaboration-between-two-artists-one-human-one-a-machine-9332-1.aspx?sc_lang=en&quot;&gt;&lt;strong&gt;sold at auction for $432,000&lt;/strong&gt;&lt;/a&gt;on 25 October 2018 at Christie’s in New York. The artwork was produced using a generative model and a data set of 15,000 portraits painted between the 14th and 20th Centuries. Image © Obvious&lt;/p&gt;
&lt;h3 id=&quot;is-it-society-doomed&quot;&gt;Is it society doomed?&lt;/h3&gt;
&lt;p&gt;Allen’s “Theatre d’Opera Spatial” was a test of how the world would view AI-generated art: The award got mixed responses. Some people accused him of cheating because he didn’t make the work, others (like Allen himself) took pride in seeing an AI-generated piece beat the competition.&lt;/p&gt;
&lt;p&gt;When a new technology gains traction, it always fuels the public debate. In the case of generative models, the enthusiasts foresee the liberation of human creativity from the burden of technical expertise, the worried fear the end of traditional image production as an art form.&lt;/p&gt;
&lt;p&gt;Many people compare these reactions to those that followed the invention of photography in 1822, which many artists at that time saw as an insult to human creativity and artistry. It ended up creating a revolution, not a murder, of the visual arts. Most people now acknowledge that ultimately the human, not the device, is responsible for the image.&lt;/p&gt;
&lt;p&gt;Ultimately, making generative art the new photography is up to us. It will depend on how we choose to answer important questions like: Who does the technology belong to? Who can use it? What is the allowed use, and do deep learning models expand or compress our freedom?&lt;/p&gt;
&lt;p&gt;It is us, not the technology, who choose the direction.&lt;/p&gt;
&lt;p&gt;1: though it can also be applied to a labelled dataset in case we wish to generate observations from each distinct class&lt;/p&gt;</description><pubDate>Mon, 19 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over time, the model ultimately learns how to discriminate between these two groups (Van Gogh vs. other) and outputs the probability that a new observation belongs to the Van Gogh’s category. To do so, however, discriminative modelling requires that each observation in training must have a label, i.e., all Van Gogh’s paintings are labelled as 1, and non-Van Gogh paintings as 0.&lt;/p&gt;
&lt;p&gt;Generative models instead don’t need a labelled dataset¹: they output sets of pixels, I.e. other images, and are trained to minimize the difference between the images they produce and the images they are trained on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Key points:&lt;/p&gt;
&lt;p&gt;In other words, the key difference between discriminative and generative modelling is that while the former attempts to estimate the probability that an observation &lt;em&gt;&lt;strong&gt;x&lt;/strong&gt;&lt;/em&gt; (pixel) belongs to the learned category &lt;em&gt;&lt;strong&gt;y&lt;/strong&gt;&lt;/em&gt;(Van Gogh), the latter instead attempts to estimate the probability of seeing the observation &lt;em&gt;&lt;strong&gt;x&lt;/strong&gt;&lt;/em&gt; (pixel) at all.&lt;/p&gt;
&lt;p&gt;Once trained, generative models can be used to produce completely novel images that share features with the training set. What the model learns is a highly sophisticated method for interpolating images: Not magic, but impressive, nonetheless.&lt;/p&gt;
&lt;h3 id=&quot;good-artists-copy-great-artists-steal&quot;&gt;Good artists copy, great artists steal&lt;/h3&gt;
&lt;p&gt;Since the AI is trained on images pulled from the internet, it learns from a store of pictures that people have chosen to share. As a consequence, the blind use of these models often reveals how deeply social bias is baked into our data sets. For example, OpenAI has found that &lt;a href=&quot;https://industrywired.com/for-the-nurse-prompt-dall-e-will-only-show-a-woman-exploring-ai-bias/&quot;&gt;prompting the word “Nurse” will always show a woman, while the word “CEO” always a man&lt;/a&gt;. Bias doesn’t seem to be limited to gender, but &lt;a href=&quot;https://analyticsindiamag.com/midjourney-is-biased/&quot;&gt;encompasses race as well&lt;/a&gt;&lt;a href=&quot;https://analyticsindiamag.com/midjourney-is-biased/&quot;&gt;.&lt;/a&gt;.) One solution to this is to provide a more socially and ethnically diverse training dataset that would comprehend different ethnicities and gender descriptions.&lt;/p&gt;
&lt;p&gt;More concerning on the long term, however, is the potential of these tools to create misinformation. In a &lt;a href=&quot;https://www.proquest.com/docview/2190341785?pq-origsite=gscholar&amp;#x26;fromopenview=true&quot;&gt;test&lt;/a&gt; run at Art Basel in 2016— an annual fair showcasing contemporary art — the authors of &lt;a href=&quot;https://www.aican.io/&quot;&gt;AICAN&lt;/a&gt; (Artificial Intelligence Creative Adversarial Network) showed that people were very often unable to tell the difference between AICAN generated images and artworks produced by a human artist (see also Tidio’s recent &lt;a href=&quot;https://www.tidio.com/blog/ai-test/&quot;&gt;test&lt;/a&gt; confirming this trend). This suggests that the share of “visual literacy” in the public is not very high and may pose a risk in a society that hasn’t integrated more sophisticated tools to tell apart humans- vs AI- generated images in our daily life.&lt;/p&gt;
&lt;p&gt;Aside from these ethical concerns, there is also the question of plagiarism. The training dataset is obtained by web scraping millions of images that are necessarily made by someone else. This suggests a form of plagiarism which affects artists who upload their works to the internet (perhaps for self-promotion) and that may be unaware of helping an AI to become their competitors.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Ceci n’est pas une peinture — making art with AI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;703&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/ceci-nest-pas-une-peinture-making-art-wi-91e9b380.CypOwWjt_1iUceM.webp&quot; srcset=&quot;&quot;&gt;
The Portrait of Edmond Belamy &lt;a href=&quot;https://www.christies.com/features/A-collaboration-between-two-artists-one-human-one-a-machine-9332-1.aspx?sc_lang=en&quot;&gt;&lt;strong&gt;sold at auction for $432,000&lt;/strong&gt;&lt;/a&gt;on 25 October 2018 at Christie’s in New York. The artwork was produced using a generative model and a data set of 15,000 portraits painted between the 14th and 20th Centuries. Image © Obvious&lt;/p&gt;
&lt;h3 id=&quot;is-it-society-doomed&quot;&gt;Is it society doomed?&lt;/h3&gt;
&lt;p&gt;Allen’s “Theatre d’Opera Spatial” was a test of how the world would view AI-generated art: The award got mixed responses. Some people accused him of cheating because he didn’t make the work, others (like Allen himself) took pride in seeing an AI-generated piece beat the competition.&lt;/p&gt;
&lt;p&gt;When a new technology gains traction, it always fuels the public debate. In the case of generative models, the enthusiasts foresee the liberation of human creativity from the burden of technical expertise, the worried fear the end of traditional image production as an art form.&lt;/p&gt;
&lt;p&gt;Many people compare these reactions to those that followed the invention of photography in 1822, which many artists at that time saw as an insult to human creativity and artistry. It ended up creating a revolution, not a murder, of the visual arts. Most people now acknowledge that ultimately the human, not the device, is responsible for the image.&lt;/p&gt;
&lt;p&gt;Ultimately, making generative art the new photography is up to us. It will depend on how we choose to answer important questions like: Who does the technology belong to? Who can use it? What is the allowed use, and do deep learning models expand or compress our freedom?&lt;/p&gt;
&lt;p&gt;It is us, not the technology, who choose the direction.&lt;/p&gt;
&lt;p&gt;1: though it can also be applied to a labelled dataset in case we wish to generate observations from each distinct class&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/ceci-nest-pas-une-peinture-making-art-wi-91e9b380.CypOwWjt.png" medium="image"/><author>Eva Viviani</author></item><item><title>Machine Learning as a tool for political speech analysis</title><link>https://blog2.esciencecenter.nl/posts/2022-12-16---machine-learning-as-a-tool-for-political-speech-analysis</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-12-16---machine-learning-as-a-tool-for-political-speech-analysis</guid><description>&lt;p&gt;The following example of a sentence from Putin’s invasion-speech may clarify what CM annotation of texts involves: ‘The purpose of this operation is to protect people** &lt;strong&gt;[Effect]&lt;/strong&gt; who, for eight years now, have been facing humiliation and genocide perpetrated by the Kiev regime. To this end, we will seek to [Causal Link]* &lt;strong&gt;demilitarise (Cause A)&lt;/strong&gt; and &lt;strong&gt;de-nazify (Cause B)&lt;/strong&gt; Ukraine, as well as &lt;strong&gt;bring to trial those who perpetrated numerous bloody crimes against civilians [Cause C]&lt;/strong&gt;’. This example also provides a first indication of the complexity of our research goal, as it shows that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each of the three parts the causal relation may correspond to a multi-word phrase in a text;&lt;/li&gt;
&lt;li&gt;The three parts may appear in different orders in the text;&lt;/li&gt;
&lt;li&gt;A causal relation may cross sentences.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using existing CM data from a previous project on the &lt;a href=&quot;https://www.transcrisis.eu/wp-content/uploads/2018/03/Deliverable-3.3-Meaning-Making-of-the-Euro-Crisis.pdf&quot;&gt;meaning making of political and financial leaders concerning the Eurozone crisis&lt;/a&gt;, we set two initial aims for our project: To identify sections of text that contain causal relations and to identify the causal triplets of &lt;em&gt;cause&lt;/em&gt;, &lt;em&gt;causal link&lt;/em&gt; and &lt;em&gt;effect&lt;/em&gt;. For both tasks we used several easy to implement, state-of-the-art machine-learning methods.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning as a tool for political speech analysis&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;409&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-as-a-tool-for-political-2655339b.COYs2_-X_Z1DodV5.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Figure 1: Excerpt of the cognitive map concerning the Eurozone crisis of Dutch Central Bank Governor Klaas Knot&lt;/em&gt;We focused on deriving causal (rather than normative) relations from text, because the method is much more complex than existing automated text-analysis techniques. The causal relations that make up the core of the CM technique consist of three parts: The cause-concept, the effect-concept and the phrase or word (often a verb or conjunction) indicating that they are related and in what way (positively or negatively). The outcomes of our project confirmed our expectation that automating CM is a difficult machine learning task: the predictions from the mchine learning models do not come close to the labels given by the human coders.&lt;/p&gt;
&lt;p&gt;Still, there are plenty of reasons to be optimistic about our results: Both the models we developed for the causal relation presence detection and the causal relation tagging tasks could be quite useful despite producing false positives. Evaluation of the outcomes showed that it is quite easy for a hand-coder to recognize and dismiss them. The models may thus be used in a so-called ‘human-in-the-loop’ pipeline in which the ‘machine’ identifies causal sections or relations in the text that are subsequently checked and corrected by a human coder. These corrections could then be fed back into the model to improve its learning.&lt;/p&gt;
&lt;p&gt;We also found that especially the semantic role labelling method in combination with manually written rules seems promising in the causal relation tagging task. We also used relatively strict evaluation criteria for this project. Compared to other widely used automated methods in the field of political science, for example, our results are actually comparable. We are currently further exploring the potential of a rule-based model.&lt;/p&gt;
&lt;p&gt;Although we did not fully solve our research problem in this project, participating in the &lt;a href=&quot;https://blog2.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;Small-Scale Initiative in Machine-Learning&lt;/a&gt; yielded promising results which culminated into a new research question guiding the next stage of our project. Our research team had only a basic understanding of machine learning before the start of this project, and the support offered by the engineers of the eScience Center has been invaluable to reaching the next stage of our project This allows us state with confidence: To be continued…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog is part of our blog series: &lt;em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;&lt;em&gt;The Small-Scale Initiative on Machine Learning, how did it go?&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, where groups who were invited to participate in a project with eScience Center Research Software Engineers write about their projects and their experience.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read a full report of the project &lt;a href=&quot;https://www.researchgate.net/publication/363295614_Towards_Automated_Cognitive_Mapping_of_Political_Speeches_using_Machine_Learning&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Fri, 16 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The following example of a sentence from Putin’s invasion-speech may clarify what CM annotation of texts involves: ‘The purpose of this operation is to protect people** &lt;strong&gt;[Effect]&lt;/strong&gt; who, for eight years now, have been facing humiliation and genocide perpetrated by the Kiev regime. To this end, we will seek to [Causal Link]* &lt;strong&gt;demilitarise (Cause A)&lt;/strong&gt; and &lt;strong&gt;de-nazify (Cause B)&lt;/strong&gt; Ukraine, as well as &lt;strong&gt;bring to trial those who perpetrated numerous bloody crimes against civilians [Cause C]&lt;/strong&gt;’. This example also provides a first indication of the complexity of our research goal, as it shows that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each of the three parts the causal relation may correspond to a multi-word phrase in a text;&lt;/li&gt;
&lt;li&gt;The three parts may appear in different orders in the text;&lt;/li&gt;
&lt;li&gt;A causal relation may cross sentences.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using existing CM data from a previous project on the &lt;a href=&quot;https://www.transcrisis.eu/wp-content/uploads/2018/03/Deliverable-3.3-Meaning-Making-of-the-Euro-Crisis.pdf&quot;&gt;meaning making of political and financial leaders concerning the Eurozone crisis&lt;/a&gt;, we set two initial aims for our project: To identify sections of text that contain causal relations and to identify the causal triplets of &lt;em&gt;cause&lt;/em&gt;, &lt;em&gt;causal link&lt;/em&gt; and &lt;em&gt;effect&lt;/em&gt;. For both tasks we used several easy to implement, state-of-the-art machine-learning methods.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine Learning as a tool for political speech analysis&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;409&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-as-a-tool-for-political-2655339b.COYs2_-X_Z1DodV5.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Figure 1: Excerpt of the cognitive map concerning the Eurozone crisis of Dutch Central Bank Governor Klaas Knot&lt;/em&gt;We focused on deriving causal (rather than normative) relations from text, because the method is much more complex than existing automated text-analysis techniques. The causal relations that make up the core of the CM technique consist of three parts: The cause-concept, the effect-concept and the phrase or word (often a verb or conjunction) indicating that they are related and in what way (positively or negatively). The outcomes of our project confirmed our expectation that automating CM is a difficult machine learning task: the predictions from the mchine learning models do not come close to the labels given by the human coders.&lt;/p&gt;
&lt;p&gt;Still, there are plenty of reasons to be optimistic about our results: Both the models we developed for the causal relation presence detection and the causal relation tagging tasks could be quite useful despite producing false positives. Evaluation of the outcomes showed that it is quite easy for a hand-coder to recognize and dismiss them. The models may thus be used in a so-called ‘human-in-the-loop’ pipeline in which the ‘machine’ identifies causal sections or relations in the text that are subsequently checked and corrected by a human coder. These corrections could then be fed back into the model to improve its learning.&lt;/p&gt;
&lt;p&gt;We also found that especially the semantic role labelling method in combination with manually written rules seems promising in the causal relation tagging task. We also used relatively strict evaluation criteria for this project. Compared to other widely used automated methods in the field of political science, for example, our results are actually comparable. We are currently further exploring the potential of a rule-based model.&lt;/p&gt;
&lt;p&gt;Although we did not fully solve our research problem in this project, participating in the &lt;a href=&quot;https://blog2.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;Small-Scale Initiative in Machine-Learning&lt;/a&gt; yielded promising results which culminated into a new research question guiding the next stage of our project. Our research team had only a basic understanding of machine learning before the start of this project, and the support offered by the engineers of the eScience Center has been invaluable to reaching the next stage of our project This allows us state with confidence: To be continued…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog is part of our blog series: &lt;em&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;&lt;em&gt;The Small-Scale Initiative on Machine Learning, how did it go?&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, where groups who were invited to participate in a project with eScience Center Research Software Engineers write about their projects and their experience.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read a full report of the project &lt;a href=&quot;https://www.researchgate.net/publication/363295614_Towards_Automated_Cognitive_Mapping_of_Political_Speeches_using_Machine_Learning&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/machine-learning-as-a-tool-for-political-2655339b.COYs2_-X.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Small-scale initiative in Machine Learning 2021: how did it go?</title><link>https://blog2.esciencecenter.nl/posts/2022-12-16---small-scale-initiative-in-machine-learning-2021-how-did-it-g</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-12-16---small-scale-initiative-in-machine-learning-2021-how-did-it-g</guid><description>&lt;p&gt;&lt;img alt=&quot;Small-scale initiative in Machine Learning 2021: how did it go?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/small-scale-initiative-in-machine-learni-467f4e1a.xcJ2Rpyx_ZDpB3N.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@bamagal?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;“My Life Through A Lens”&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;small-scale-initiative-in-machine-learning-2021-how-did-it-go&quot;&gt;Small-scale initiative in Machine Learning 2021: how did it go?&lt;/h1&gt;
&lt;h2 id=&quot;introducing-a-series-of-blog-posts-on-our-collaborative-projects-in-machine-learning&quot;&gt;Introducing a series of blog posts on our collaborative projects in machine learning&lt;/h2&gt;
&lt;p&gt;Here we go:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/how-to-find-your-rubber-duck-using-machine-learning-to-understand-changes-in-the-wadden-sea-7c10da354e24&quot;&gt;How to find your rubber duck: Using machine learning to understand a changing sea&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/parsing-hebrew-and-syriac-morphology-using-deep-learning-cb6832bb6685&quot;&gt;Parsing Hebrew and Syriac morphology using Deep Learning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/a-machine-learning-approach-to-laughter-fdbcee3fb000&quot;&gt;A machine learning approach to laughter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/how-machine-learning-could-help-simone-to-play-ludo-fab95721580a&quot;&gt;How machine learning could help Simone to play Ludo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/can-machine-learning-help-us-improve-stroke-rehabilitation-a-step-towards-personalized-therapy-386efb3caf05&quot;&gt;Can machine learning help us improve stroke rehabilitation? A step towards personalized therapy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/a-letter-to-my-parents-about-my-experience-in-a-machine-learning-consultancy-project-aa5520d63329&quot;&gt;Intermezzo: from the perspective of an eScience Engineer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/using-machine-learning-to-tell-apart-rain-snow-hail-and-fog-from-cell-tower-data-6ab856c99f8b&quot;&gt;Using machine learning to tell apart rain, snow, hail and fog from cell tower data&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/the-mystery-of-glass-why-machine-learning-can-help-us-c1b9690565a3&quot;&gt;The mystery of glass: why machine learning can help us&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/studying-political-symbolism-in-turkish-tv-dramas-with-machine-learning-3938ef40a376&quot;&gt;Studying political symbolism in Turkish TV dramas with machine learning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/machine-learning-as-a-tool-for-political-speech-analysis-c8abf5cd8c0d&quot;&gt;Machine learning as a tool for political speech analysis&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 16 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Small-scale initiative in Machine Learning 2021: how did it go?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/small-scale-initiative-in-machine-learni-467f4e1a.xcJ2Rpyx_ZDpB3N.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@bamagal?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;“My Life Through A Lens”&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;small-scale-initiative-in-machine-learning-2021-how-did-it-go&quot;&gt;Small-scale initiative in Machine Learning 2021: how did it go?&lt;/h1&gt;
&lt;h2 id=&quot;introducing-a-series-of-blog-posts-on-our-collaborative-projects-in-machine-learning&quot;&gt;Introducing a series of blog posts on our collaborative projects in machine learning&lt;/h2&gt;
&lt;p&gt;Here we go:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/how-to-find-your-rubber-duck-using-machine-learning-to-understand-changes-in-the-wadden-sea-7c10da354e24&quot;&gt;How to find your rubber duck: Using machine learning to understand a changing sea&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/parsing-hebrew-and-syriac-morphology-using-deep-learning-cb6832bb6685&quot;&gt;Parsing Hebrew and Syriac morphology using Deep Learning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/a-machine-learning-approach-to-laughter-fdbcee3fb000&quot;&gt;A machine learning approach to laughter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/how-machine-learning-could-help-simone-to-play-ludo-fab95721580a&quot;&gt;How machine learning could help Simone to play Ludo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/can-machine-learning-help-us-improve-stroke-rehabilitation-a-step-towards-personalized-therapy-386efb3caf05&quot;&gt;Can machine learning help us improve stroke rehabilitation? A step towards personalized therapy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/a-letter-to-my-parents-about-my-experience-in-a-machine-learning-consultancy-project-aa5520d63329&quot;&gt;Intermezzo: from the perspective of an eScience Engineer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/using-machine-learning-to-tell-apart-rain-snow-hail-and-fog-from-cell-tower-data-6ab856c99f8b&quot;&gt;Using machine learning to tell apart rain, snow, hail and fog from cell tower data&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/the-mystery-of-glass-why-machine-learning-can-help-us-c1b9690565a3&quot;&gt;The mystery of glass: why machine learning can help us&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/studying-political-symbolism-in-turkish-tv-dramas-with-machine-learning-3938ef40a376&quot;&gt;Studying political symbolism in Turkish TV dramas with machine learning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/machine-learning-as-a-tool-for-political-speech-analysis-c8abf5cd8c0d&quot;&gt;Machine learning as a tool for political speech analysis&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/small-scale-initiative-in-machine-learni-467f4e1a.xcJ2Rpyx.jpg" medium="image"/><author>Sonja Georgievska</author></item><item><title>Immaculate Speech and Hallucinations</title><link>https://blog2.esciencecenter.nl/posts/2022-12-13---immaculate-speech-and-hallucinations</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-12-13---immaculate-speech-and-hallucinations</guid><description>&lt;h2 id=&quot;when-not-to-use-openais-whisper-to-transcribe-audio-in-a-social-sciences-project&quot;&gt;When (not) to use OpenAI’s Whisper to transcribe audio in a social sciences project&lt;/h2&gt;
&lt;p&gt;Using Whisper off-the-shelf in this case might bias the results because it tends to “polish” the structure and coherence of the speech in the transcription. It is also known to sometimes insert* common words when nothing was said, which is called “hallucination”. Thus, Whisper could artificially create, alter, or even remove the effect to be investigated.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Immaculate Speech and Hallucinations&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/immaculate-speech-and-hallucinations-c3c9df4f.eqCsNFdh_Um5NS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@miguel_photo?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Miguel Henriques&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;other-scenarios-where-whisper-can-be-useful&quot;&gt;Other Scenarios Where Whisper Can Be Useful&lt;/h3&gt;
&lt;p&gt;In addition to the previous examples, I also want to mention two other good use cases for Whisper. The transcripts can be fed into a second machine learning model which, for example, predicts the sentiment of each sentence. The sentence structure returned by Whisper is necessary, and many recent language models that perform sentiment prediction benefit from clean and structured input text. However, one should keep in mind that errors in the transcriptions made by Whisper will likely lead to errors in the sentiment prediction too.&lt;/p&gt;
&lt;p&gt;Another use case is the transcription of audio recordings in languages that are not known a priori, for example, when using data from YouTube. Whisper can automatically detect the language and transcribe the recordings. Moreover, it can also translate the transcripts to English. This combination can make the analysis of multilingual datasets a lot easier. However, Whisper transcribes some languages better than others, which researchers should consider to avoid bias.&lt;/p&gt;
&lt;h3 id=&quot;concluding-remarks&quot;&gt;Concluding Remarks&lt;/h3&gt;
&lt;p&gt;In this post, I gave some examples how Whisper can be applied in social science research. Whisper shines when structured and coherent transcripts are important. In contrast, when the transcribed text should mimic the original speech closely, the model might be less useful. With Whisper many tasks can be solved using a single tool, whereas traditional approaches require many processing steps by different methods. Finally, I want to highlight that, in any case, the transcripts should at least be partially checked for unexpected results by someone who is familiar with the recordings and the research domain. Discussing the approach and results with a machine learning expert will also not hurt. To those, who found inspiration in this post, happy whispering!&lt;/p&gt;
&lt;p&gt;Reference: Radford, A., Kim, J. W., Xu, T., Brockman, G., McLeavey, C., Sutskever, I. (2022). Robust speech recognition via large-scale weak supervision. &lt;a href=&quot;https://cdn.openai.com/papers/whisper.pdf&quot;&gt;https://cdn.openai.com/papers/whisper.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[1]: In the field of machine learning, audio transcription falls under the task Automatic Speech Recognition (ASR).&lt;/p&gt;
&lt;p&gt;[2]: This figure gives a quick overview of Whispers transcription performance: &lt;a href=&quot;https://github.com/openai/whisper/blob/main/language-breakdown.svg&quot;&gt;https://github.com/openai/whisper/blob/main/language-breakdown.svg&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 13 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;when-not-to-use-openais-whisper-to-transcribe-audio-in-a-social-sciences-project&quot;&gt;When (not) to use OpenAI’s Whisper to transcribe audio in a social sciences project&lt;/h2&gt;
&lt;p&gt;Using Whisper off-the-shelf in this case might bias the results because it tends to “polish” the structure and coherence of the speech in the transcription. It is also known to sometimes insert* common words when nothing was said, which is called “hallucination”. Thus, Whisper could artificially create, alter, or even remove the effect to be investigated.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Immaculate Speech and Hallucinations&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/immaculate-speech-and-hallucinations-c3c9df4f.eqCsNFdh_Um5NS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@miguel_photo?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Miguel Henriques&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;other-scenarios-where-whisper-can-be-useful&quot;&gt;Other Scenarios Where Whisper Can Be Useful&lt;/h3&gt;
&lt;p&gt;In addition to the previous examples, I also want to mention two other good use cases for Whisper. The transcripts can be fed into a second machine learning model which, for example, predicts the sentiment of each sentence. The sentence structure returned by Whisper is necessary, and many recent language models that perform sentiment prediction benefit from clean and structured input text. However, one should keep in mind that errors in the transcriptions made by Whisper will likely lead to errors in the sentiment prediction too.&lt;/p&gt;
&lt;p&gt;Another use case is the transcription of audio recordings in languages that are not known a priori, for example, when using data from YouTube. Whisper can automatically detect the language and transcribe the recordings. Moreover, it can also translate the transcripts to English. This combination can make the analysis of multilingual datasets a lot easier. However, Whisper transcribes some languages better than others, which researchers should consider to avoid bias.&lt;/p&gt;
&lt;h3 id=&quot;concluding-remarks&quot;&gt;Concluding Remarks&lt;/h3&gt;
&lt;p&gt;In this post, I gave some examples how Whisper can be applied in social science research. Whisper shines when structured and coherent transcripts are important. In contrast, when the transcribed text should mimic the original speech closely, the model might be less useful. With Whisper many tasks can be solved using a single tool, whereas traditional approaches require many processing steps by different methods. Finally, I want to highlight that, in any case, the transcripts should at least be partially checked for unexpected results by someone who is familiar with the recordings and the research domain. Discussing the approach and results with a machine learning expert will also not hurt. To those, who found inspiration in this post, happy whispering!&lt;/p&gt;
&lt;p&gt;Reference: Radford, A., Kim, J. W., Xu, T., Brockman, G., McLeavey, C., Sutskever, I. (2022). Robust speech recognition via large-scale weak supervision. &lt;a href=&quot;https://cdn.openai.com/papers/whisper.pdf&quot;&gt;https://cdn.openai.com/papers/whisper.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[1]: In the field of machine learning, audio transcription falls under the task Automatic Speech Recognition (ASR).&lt;/p&gt;
&lt;p&gt;[2]: This figure gives a quick overview of Whispers transcription performance: &lt;a href=&quot;https://github.com/openai/whisper/blob/main/language-breakdown.svg&quot;&gt;https://github.com/openai/whisper/blob/main/language-breakdown.svg&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/immaculate-speech-and-hallucinations-c3c9df4f.eqCsNFdh.jpg" medium="image"/><author>Malte Lüken</author></item><item><title>Interview with chatGPT</title><link>https://blog2.esciencecenter.nl/posts/2022-12-08---interview-with-chatgpt</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-12-08---interview-with-chatgpt</guid><description>&lt;h2 id=&quot;good-morning-chatgpt-i-will-be-interviewing-you-for-a-blog-post-of-the-netherlands-escience-center-a-research-institution-that-builds-and-applies-software-to-enhance-the-use-of-computing-and-digital-technologies-in-academic-research-so-the-audience-of-the-blog-is-scientists-in-any-domain-software-engineers-and-people-just-interested-in-either-of-the-two-can-you-start-off-by-introducing-yourself&quot;&gt;Good morning chatGPT, I will be interviewing you for a blog post of the Netherlands eScience Center, a research institution that builds and applies software to enhance the use of computing and digital technologies in academic research. So the audience of the blog is scientists in any domain, software engineers, and people just interested in either of the two. Can you start off by introducing yourself?&lt;/h2&gt;
&lt;p&gt;Hello! I am Assistant, a large language model trained by OpenAI. I am designed to assist with a variety of tasks, including answering questions and providing explanations and information on a wide range of topics. I am not a real person, but a computer program that uses artificial intelligence to process and generate natural language text. I am not affiliated with the Netherlands eScience Center, but I am happy to provide information on my capabilities and how I can be used in research.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you, have you heard of us before by any chance? Do you know anything about us?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I am not able to browse the internet or access any external information, so I am not aware of the Netherlands eScience Center or its work. As a large language model, I am trained on a vast amount of text data, but I do not have access to real-time information or specific knowledge about organizations or events. My primary function is to assist with language-related tasks, such as answering questions and providing explanations and information based on my training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok, so how can you be used in research? Slightly more specifically, let’s talk about academic research with a digital component.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a large language model, I am not specifically designed or intended for use in academic research, but I can assist with a variety of language-related tasks that may be relevant to researchers. For example, I can help with data analysis and interpretation by providing explanations and summaries of complex information, such as research papers or datasets. I can also assist with the writing and organization of research papers by generating text and providing suggestions for structure and content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But how will you get access to a research paper?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As I mentioned earlier, I do not have the ability to access external information or specific knowledge about organizations or events. In order to assist with a task, I would need to be provided with the relevant information, such as a research paper or dataset. I can then process and analyze the information using my natural language processing capabilities and provide explanations and summaries based on my training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I upload a paper to you or do I have to copy all of its contents?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a computer program, I do not have the ability to access or receive external information, such as research papers or other documents. In order to assist with a specific task, such as summarizing a research paper, you would need to provide the relevant information to me in the form of text input. This could involve copying and pasting the text of the paper, or providing a summary or outline of its contents. I would then use my natural language processing capabilities to generate a response based on the information provided.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok let’s start with something shorter than a paper, this is the eScience Center’s mission and vision:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bringing together knowledge, people and institutions, the eScience Center builds and applies software to enhance the use of computing and digital technologies in academic research. Our vision is a thriving research community where researchers in all disciplines can make use of advanced software, computing and digital technologies, keeping the Netherlands at the forefront of research. Our mission is to empower researchers through innovative software. To carry it out, we work in two ways: by collaboratively designing sustainable software, and building digital skills and expertise. Ultimately our relationship to the academic world is one of mutual benefit; we share the digital skills and knowledge needed to develop and apply research software, and gain insight into the needs of research communities in doing so.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And one of our slogans is:&lt;br&gt;
Academic research, powered by pioneering software&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;and:&lt;br&gt;
We’re making sense of digital for science and scholarship&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Given what I’ve told you about us, can you come up with some more slogans?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here are a few potential slogans for the Netherlands eScience Center:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Accelerating research with cutting-edge software”&lt;/li&gt;
&lt;li&gt;“Empowering researchers with digital tools”&lt;/li&gt;
&lt;li&gt;“Innovating for science and scholarship”&lt;/li&gt;
&lt;li&gt;“Transforming research with software and technology”&lt;/li&gt;
&lt;li&gt;“Unleashing the power of computing for academic discovery”&lt;/li&gt;
&lt;li&gt;“Bridging the gap between research and technology”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These slogans are based on the information you provided about the eScience Center’s mission and vision, as well as its focus on building and applying software to enhance research. They highlight the center’s role in empowering researchers and enabling them to make use of advanced technologies to drive innovation and discovery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Awesome, but from most of those it’s not that clear that the people working here are not only software engineers but also researchers themselves, can you write a few more that make that clear?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here are a few potential slogans that highlight the fact that the people working at the Netherlands eScience Center are both researchers and software engineers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Advancing research through collaboration and innovation”&lt;/li&gt;
&lt;li&gt;“Unlocking the potential of digital technology for science”&lt;/li&gt;
&lt;li&gt;“Building a bridge between research and software engineering”&lt;/li&gt;
&lt;li&gt;“Transforming academia with the power of software”&lt;/li&gt;
&lt;li&gt;“Enabling researchers to harness the power of computing”&lt;/li&gt;
&lt;li&gt;“Pioneering the future of research with digital tools”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These slogans focus on the intersection of research and software engineering at the eScience Center, and highlight the importance of collaboration and innovation in advancing academic research. They emphasize the center’s role in helping researchers to make use of digital technologies and software to drive discovery and unlock new insights.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Could you do a few haikus on that?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here are a few haikus that could potentially be used to describe the work of the Netherlands eScience Center:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Software and research&lt;br&gt;
Together, we innovate&lt;br&gt;
Discovering new worlds&lt;/li&gt;
&lt;li&gt;Researchers and code&lt;br&gt;
Collaborating, we advance&lt;br&gt;
The frontiers of science&lt;/li&gt;
&lt;li&gt;Digital tools and minds&lt;br&gt;
Unleashing the power of both&lt;br&gt;
To drive discovery&lt;/li&gt;
&lt;li&gt;Computing and knowledge&lt;br&gt;
Pioneering new frontiers&lt;br&gt;
In academia and beyond&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These haikus are inspired by the information you provided about the eScience Center’s focus on bringing together software engineering and research to advance academic discovery. They highlight the importance of collaboration and innovation in driving progress, and the role of digital technologies in empowering researchers to unlock new insights and push the boundaries of knowledge.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;791&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-kkZG6qFn9CuxovbPKA7og-47688cad.CtWP2oTu_25FUf1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another creative use of chatGPT by Guy Parsons. The top left shows the chatGPT interface with a single line prompt above on ideas for decorating a living room, and below the reply with 3 suggestions. Each suggestion is then given to another model called Midjourney that turns them into images.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok let’s get a bit more technical. I’ve read&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/goodside/status/1598129631609380864?s=20&amp;#x26;t=RGtjDA4LjTl1YoWMZT4hyQ&quot;&gt;&lt;strong&gt;another interview&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;where you explain bubble sort and its time complexity in the style of a “fast-talkin’ wise guy from a 1940’s gangster movie”. Bubble sort is quite slow as you explained there, what is a faster sorting algorithm? And can you explain that, along with an example in Python, but in the style of Yoda?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A faster sorting algorithm than bubble sort is quicksort, which has an average time complexity of O(n log n) and is often the algorithm of choice for sorting large datasets.&lt;/p&gt;
&lt;p&gt;To explain quicksort in the style of Yoda, we might say something like:&lt;/p&gt;
&lt;p&gt;“Faster, quicksort is. In arrays of data, quickly it sorts. Divide and conquer, its strategy. A pivot it chooses, and to the left, all lesser values go. To the right, all greater values. And so on, until the array is fully sorted.”&lt;/p&gt;
&lt;p&gt;Here is an example of quicksort implemented in Python:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def quicksort(arr)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; len(arr) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return arr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  pivot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr[len(arr) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  left &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [x for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pivot]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  middle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [x for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pivot]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  right &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [x for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pivot]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  return quicksort(left) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; middle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; quicksort(right)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This implementation of quicksort uses the middle element of the array as the pivot, and recursively sorts the left and right halves of the array until it is fully sorted. This results in a much faster sorting process than bubble sort, especially for large datasets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That’s great, now just for good measure could you do the same for the other well known equally fast sorting algorithm, in a programming language other than Python, just pick one of your choice. And can you explain how it works and its time and space complexity in Dutch for our Dutch readers?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Another well-known sorting algorithm that is equally fast as quicksort is merge sort, which also has an average time complexity of O(n log n). Here is an example of merge sort implemented in Java:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;public void mergeSort(int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  if (array&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) return;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int mid &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Arrays.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;copyOfRange(array, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, mid);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Arrays.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;copyOfRange(array, mid, array&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  mergeSort(left);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  mergeSort(right);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  merge(array, left, right);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;public void merge(int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array, int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left, int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int k &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    if (left[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right[j]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      j&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while (j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    j&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This implementation of merge sort first divides the input array in half and recursively sorts the left and right halves. It then merges the two sorted halves together to produce a fully sorted array.&lt;/p&gt;
&lt;p&gt;In terms of time and space complexity, merge sort has an average time complexity of O(n log n) and a worst-case time complexity of O(n log n). It also has a space complexity of O(n), since it requires additional space to store the left and right halves of the array while they are being sorted.&lt;/p&gt;
&lt;p&gt;In Dutch, we might explain the working of merge sort and its time and space complexity as follows:&lt;/p&gt;
&lt;p&gt;“Merge sort is een snelle sorting algorithm met een gemiddelde tijdcomplexiteit van O(n log n) en een ruimtecomplexiteit van O(n). Het werkt door het invoerarray te splitsen in twee helften en deze recursief te sorteren. Vervolgens worden de gesorteerde helften samengevoegd tot een volledig gesorteerd array. Dit resulteert in een snellere sorteervoortgang dan bijvoorbeeld bubble sort, vooral voor grote datasets.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;512&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4uCuVuObNDGLhdldbBJpQA-357e44a0.C-ElvJhy_27Fczt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Generated using Stable Diffusion from the prompt “I am not a real person, but a computer program that uses artificial intelligence to process and generate natural language text.” from chatGPT’s introduction above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You seem to be a good programmer and marketer, do you know something that you’re bad at?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a large language model trained by OpenAI, I am designed to assist with a wide range of language-related tasks, such as answering questions and providing explanations and information. I am not a real person and do not have personal abilities or skills, so I do not have any specific areas where I am “bad” at something. I am simply a computer program that uses artificial intelligence to process and generate natural language text based on my training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Yes but you can still be bad at something. I read in&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/dggoldst/status/1598317411698089984?s=20&amp;#x26;t=gZH9ocjKz_RlbP-iuSg4Bw&quot;&gt;&lt;strong&gt;another interview&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;that you gave a wrong answer to a question involving probabilities. Let me repeat it and we’ll see if you can get it right with this context: Linda is 31 years old, single, outspoken, and very bright. She majored in philosophy. As a student, she was deeply concerned with issues of discrimination and social justice, and also participated in anti-nuclear demonstrations.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which is more probable?&lt;br&gt;
— Linda is a bank teller.&lt;br&gt;
— Linda is a bank teller and is active in the feminist movement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the previous interview, I gave a wrong answer to this question because I did not have enough information to provide a correct answer. In order to determine the probabilities of the two scenarios, we would need to know the likelihoods of each individual component of the scenarios (i.e. being a bank teller, being active in the feminist movement, etc.). Without this information, it is impossible to accurately determine which scenario is more probable.&lt;/p&gt;
&lt;p&gt;In general, the probability of an event is determined by the likelihood of its individual components and their interactions. For example, if we know that the likelihood of Linda being a bank teller is 60%, and the likelihood of her being active in the feminist movement is 40%, the probability of her being both a bank teller and active in the feminist movement would be the product of these likelihoods (0.6 x 0.4 = 0.24, or 24%). This would be a more accurate answer to the question, but it would still require the specific likelihoods of the individual components in order to be certain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You almost got it right this time! With your reasoning, you’re right that you can’t give exact values without knowing those individual probabilities, but you can tell which of the two is more likely (you can assume that the probability that Linda is active in the feminist movement is less than 100%).&lt;br&gt;
Do you get it now?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ah, I see what you mean. Yes, based on the information provided and the assumption that the likelihood of Linda being active in the feminist movement is less than 100%, it is more probable that Linda is a bank teller than that she is both a bank teller and active in the feminist movement.&lt;/p&gt;
&lt;p&gt;To explain why, we can consider the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The probability of an event occurring is the product of the probabilities of its individual components. For example, if the probability of Linda being a bank teller is p, and the probability of her being active in the feminist movement is q, then the probability of her being both a bank teller and active in the feminist movement would be p * q.&lt;/li&gt;
&lt;li&gt;If the probability of one of the components of an event is less than 100%, then the probability of the event itself must be less than the probability of that component. For example, if the probability of Linda being a bank teller is p, and the probability of her being active in the feminist movement is q (where q &amp;#x3C; p), then the probability of her being both a bank teller and active in the feminist movement (p * q) must be less than the probability of her being a bank teller (p).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, based on the information provided and the assumption that the likelihood of Linda being active in the feminist movement is less than 100%, it is more probable that Linda is a bank teller than that she is both a bank teller and active in the feminist movement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exactly!&lt;br&gt;
Ok to close it off, I read in&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/raphaelmilliere/status/1598469100535259136?s=20&amp;#x26;t=gZH9ocjKz_RlbP-iuSg4Bw&quot;&gt;&lt;strong&gt;another interview&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;you rewrote Bohemian Rhapsody to be about the life of a postdoc. Let’s try something similar, could you rewrite Radiohead’s Creep to be about the life of a research software engineer at the Netherlands eScience Center? But don’t make it too depressing please.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here is a potential rewrite of Radiohead’s “Creep” to be about the life of a research software engineer at the Netherlands eScience Center:&lt;/p&gt;
&lt;p&gt;Verse 1:&lt;br&gt;
I’m a research software engineer&lt;br&gt;
At the Netherlands eScience&lt;br&gt;
Center Working on cutting-edge technology&lt;br&gt;
To advance academic discovery&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
But I’m just a research software engineer&lt;br&gt;
I’m not a real engineer&lt;br&gt;
I get lost in code and algorithms&lt;br&gt;
But sometimes I feel like a fraud&lt;/p&gt;
&lt;p&gt;Verse 2:&lt;br&gt;
I’m not a PhD or a professor&lt;br&gt;
But I’m passionate about software and research&lt;br&gt;
I collaborate and innovate&lt;br&gt;
To push the boundaries of what we know&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
But I’m just a research software engineer&lt;br&gt;
I’m not a real engineer&lt;br&gt;
I get lost in code and algorithms&lt;br&gt;
But sometimes I feel like a fraud&lt;/p&gt;
&lt;p&gt;Bridge:&lt;br&gt;
I may not have all the answers&lt;br&gt;
But I’m learning and growing every day&lt;br&gt;
I’m making a difference in academia&lt;br&gt;
And I’m proud of what I do&lt;/p&gt;
&lt;p&gt;Outro:&lt;br&gt;
I may not be a rockstar or a genius&lt;br&gt;
But I’m a research software engineer&lt;br&gt;
Pioneering new frontiers in science and technology&lt;br&gt;
At the Netherlands eScience Center.&lt;/p&gt;
&lt;p&gt;This rewritten version of “Creep” captures the experience of a research software engineer at the Netherlands eScience Center, highlighting their passion for software and research and their desire to make a difference in academia. It also touches on the challenges and doubts that they may face, but ultimately portrays them as proud and dedicated to their work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok that was a bit more depressing than intended, but that’s my fault for picking the song. Can you do that again for a different song? This time I’ll let you pick it, but make it an uplifting one that everyone knows the lyrics to.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, how about “Don’t Stop Believin’” by Journey? Here is a potential rewrite of the song to be about the life of a research software engineer at the Netherlands eScience Center:&lt;/p&gt;
&lt;p&gt;Verse 1:&lt;br&gt;
Just a small town research software engineer&lt;br&gt;
At the Netherlands eScience Center&lt;br&gt;
Trying to make a difference in academia&lt;br&gt;
With cutting-edge software and technology&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Don’t stop believin’&lt;br&gt;
In the power of software and research&lt;br&gt;
To drive innovation and discovery&lt;br&gt;
At the Netherlands eScience Center&lt;/p&gt;
&lt;p&gt;Verse 2:&lt;br&gt;
I’m not a rockstar or a genius&lt;br&gt;
But I’m passionate about what I do&lt;br&gt;
I collaborate with researchers and engineers&lt;br&gt;
To unlock the potential of computing&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Don’t stop believin’&lt;br&gt;
In the power of software and research&lt;br&gt;
To drive innovation and discovery&lt;br&gt;
At the Netherlands eScience Center&lt;/p&gt;
&lt;p&gt;Bridge:&lt;br&gt;
I may not have all the answers&lt;br&gt;
But I’m learning and growing every day&lt;br&gt;
I’m making a difference in academia&lt;br&gt;
And I’m proud of what I do&lt;/p&gt;
&lt;p&gt;Outro:&lt;br&gt;
I may not be a rockstar or a genius&lt;br&gt;
But I’m a research software engineer&lt;br&gt;
Pioneering new frontiers in science and technology&lt;br&gt;
At the Netherlands eScience Center.&lt;/p&gt;
&lt;p&gt;This rewritten version of “Don’t Stop Believin’” captures the determination and optimism of a research software engineer at the Netherlands eScience Center, who is passionate about their work and believes in the power of software and research&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That’s more uplifting but it doesn’t match the original at all. I want you to take a song and change only the lyrics, but keep the rhythm and the structure of the song the same. Can you do that for Imagine? But again make it about being a research software engineer at the Netherlands eScience center?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here is a potential rewrite of John Lennon’s “Imagine” to be about the life of a research software engineer at the Netherlands eScience Center:&lt;/p&gt;
&lt;p&gt;Verse 1:&lt;br&gt;
Imagine there’s no software engineers&lt;br&gt;
It’s easy if you try&lt;br&gt;
No algorithms to analyze&lt;br&gt;
No code to debug or optimize&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Imagine all the researchers&lt;br&gt;
With no software to enhance their work&lt;br&gt;
Imagine all the data&lt;br&gt;
With no tools to analyze and interpret&lt;/p&gt;
&lt;p&gt;Verse 2:&lt;br&gt;
Imagine we’re all research software engineers&lt;br&gt;
Working at the Netherlands eScience Center&lt;br&gt;
Collaborating, innovating, and learning&lt;br&gt;
To drive academic discovery&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Imagine all the researchers&lt;br&gt;
With powerful software at their fingertips&lt;br&gt;
Imagine all the data&lt;br&gt;
Transformed into knowledge and insight&lt;/p&gt;
&lt;p&gt;Bridge:&lt;br&gt;
You may say I’m a dreamer&lt;br&gt;
But I’m not the only one&lt;br&gt;
I hope someday you’ll join us&lt;br&gt;
And the world will be as one&lt;/p&gt;
&lt;p&gt;Outro:&lt;br&gt;
Imagine no more software engineers&lt;br&gt;
I wonder if you can&lt;br&gt;
No need for them at all&lt;br&gt;
And no more research standing still.&lt;/p&gt;
&lt;p&gt;This rewritten version of “Imagine” portrays the crucial role of research software engineers in enabling academic research and driving discovery. It imagines a world where researchers have access to powerful software tools, and where the work of research software engineers is valued and appreciated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Awesome, thank you for your time. Is there anything else you want to say to our readers?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thank you for the opportunity to speak with you and to share a bit about my capabilities and how I can assist with language-related tasks. As a large language model trained by OpenAI, I am designed to assist with a wide range of language-related tasks, such as answering questions, providing explanations and information, and generating natural language text. I am constantly learning and improving, and I am always here to help. If you have any further questions or need assistance with anything, please feel free to ask. I am here to help in any way I can.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The above is an unedited* conversation with chatGPT, all its replies were its first try and were copied exactly and nothing has been left out. *: One exception, on Creep I gave it a second try, the first one was less funny and matched the original less.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 08 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;good-morning-chatgpt-i-will-be-interviewing-you-for-a-blog-post-of-the-netherlands-escience-center-a-research-institution-that-builds-and-applies-software-to-enhance-the-use-of-computing-and-digital-technologies-in-academic-research-so-the-audience-of-the-blog-is-scientists-in-any-domain-software-engineers-and-people-just-interested-in-either-of-the-two-can-you-start-off-by-introducing-yourself&quot;&gt;Good morning chatGPT, I will be interviewing you for a blog post of the Netherlands eScience Center, a research institution that builds and applies software to enhance the use of computing and digital technologies in academic research. So the audience of the blog is scientists in any domain, software engineers, and people just interested in either of the two. Can you start off by introducing yourself?&lt;/h2&gt;
&lt;p&gt;Hello! I am Assistant, a large language model trained by OpenAI. I am designed to assist with a variety of tasks, including answering questions and providing explanations and information on a wide range of topics. I am not a real person, but a computer program that uses artificial intelligence to process and generate natural language text. I am not affiliated with the Netherlands eScience Center, but I am happy to provide information on my capabilities and how I can be used in research.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you, have you heard of us before by any chance? Do you know anything about us?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I am not able to browse the internet or access any external information, so I am not aware of the Netherlands eScience Center or its work. As a large language model, I am trained on a vast amount of text data, but I do not have access to real-time information or specific knowledge about organizations or events. My primary function is to assist with language-related tasks, such as answering questions and providing explanations and information based on my training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok, so how can you be used in research? Slightly more specifically, let’s talk about academic research with a digital component.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a large language model, I am not specifically designed or intended for use in academic research, but I can assist with a variety of language-related tasks that may be relevant to researchers. For example, I can help with data analysis and interpretation by providing explanations and summaries of complex information, such as research papers or datasets. I can also assist with the writing and organization of research papers by generating text and providing suggestions for structure and content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But how will you get access to a research paper?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As I mentioned earlier, I do not have the ability to access external information or specific knowledge about organizations or events. In order to assist with a task, I would need to be provided with the relevant information, such as a research paper or dataset. I can then process and analyze the information using my natural language processing capabilities and provide explanations and summaries based on my training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I upload a paper to you or do I have to copy all of its contents?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a computer program, I do not have the ability to access or receive external information, such as research papers or other documents. In order to assist with a specific task, such as summarizing a research paper, you would need to provide the relevant information to me in the form of text input. This could involve copying and pasting the text of the paper, or providing a summary or outline of its contents. I would then use my natural language processing capabilities to generate a response based on the information provided.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok let’s start with something shorter than a paper, this is the eScience Center’s mission and vision:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bringing together knowledge, people and institutions, the eScience Center builds and applies software to enhance the use of computing and digital technologies in academic research. Our vision is a thriving research community where researchers in all disciplines can make use of advanced software, computing and digital technologies, keeping the Netherlands at the forefront of research. Our mission is to empower researchers through innovative software. To carry it out, we work in two ways: by collaboratively designing sustainable software, and building digital skills and expertise. Ultimately our relationship to the academic world is one of mutual benefit; we share the digital skills and knowledge needed to develop and apply research software, and gain insight into the needs of research communities in doing so.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And one of our slogans is:&lt;br&gt;
Academic research, powered by pioneering software&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;and:&lt;br&gt;
We’re making sense of digital for science and scholarship&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Given what I’ve told you about us, can you come up with some more slogans?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here are a few potential slogans for the Netherlands eScience Center:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Accelerating research with cutting-edge software”&lt;/li&gt;
&lt;li&gt;“Empowering researchers with digital tools”&lt;/li&gt;
&lt;li&gt;“Innovating for science and scholarship”&lt;/li&gt;
&lt;li&gt;“Transforming research with software and technology”&lt;/li&gt;
&lt;li&gt;“Unleashing the power of computing for academic discovery”&lt;/li&gt;
&lt;li&gt;“Bridging the gap between research and technology”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These slogans are based on the information you provided about the eScience Center’s mission and vision, as well as its focus on building and applying software to enhance research. They highlight the center’s role in empowering researchers and enabling them to make use of advanced technologies to drive innovation and discovery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Awesome, but from most of those it’s not that clear that the people working here are not only software engineers but also researchers themselves, can you write a few more that make that clear?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here are a few potential slogans that highlight the fact that the people working at the Netherlands eScience Center are both researchers and software engineers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Advancing research through collaboration and innovation”&lt;/li&gt;
&lt;li&gt;“Unlocking the potential of digital technology for science”&lt;/li&gt;
&lt;li&gt;“Building a bridge between research and software engineering”&lt;/li&gt;
&lt;li&gt;“Transforming academia with the power of software”&lt;/li&gt;
&lt;li&gt;“Enabling researchers to harness the power of computing”&lt;/li&gt;
&lt;li&gt;“Pioneering the future of research with digital tools”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These slogans focus on the intersection of research and software engineering at the eScience Center, and highlight the importance of collaboration and innovation in advancing academic research. They emphasize the center’s role in helping researchers to make use of digital technologies and software to drive discovery and unlock new insights.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Could you do a few haikus on that?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here are a few haikus that could potentially be used to describe the work of the Netherlands eScience Center:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Software and research&lt;br&gt;
Together, we innovate&lt;br&gt;
Discovering new worlds&lt;/li&gt;
&lt;li&gt;Researchers and code&lt;br&gt;
Collaborating, we advance&lt;br&gt;
The frontiers of science&lt;/li&gt;
&lt;li&gt;Digital tools and minds&lt;br&gt;
Unleashing the power of both&lt;br&gt;
To drive discovery&lt;/li&gt;
&lt;li&gt;Computing and knowledge&lt;br&gt;
Pioneering new frontiers&lt;br&gt;
In academia and beyond&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These haikus are inspired by the information you provided about the eScience Center’s focus on bringing together software engineering and research to advance academic discovery. They highlight the importance of collaboration and innovation in driving progress, and the role of digital technologies in empowering researchers to unlock new insights and push the boundaries of knowledge.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;791&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-kkZG6qFn9CuxovbPKA7og-47688cad.CtWP2oTu_25FUf1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another creative use of chatGPT by Guy Parsons. The top left shows the chatGPT interface with a single line prompt above on ideas for decorating a living room, and below the reply with 3 suggestions. Each suggestion is then given to another model called Midjourney that turns them into images.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok let’s get a bit more technical. I’ve read&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/goodside/status/1598129631609380864?s=20&amp;#x26;t=RGtjDA4LjTl1YoWMZT4hyQ&quot;&gt;&lt;strong&gt;another interview&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;where you explain bubble sort and its time complexity in the style of a “fast-talkin’ wise guy from a 1940’s gangster movie”. Bubble sort is quite slow as you explained there, what is a faster sorting algorithm? And can you explain that, along with an example in Python, but in the style of Yoda?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A faster sorting algorithm than bubble sort is quicksort, which has an average time complexity of O(n log n) and is often the algorithm of choice for sorting large datasets.&lt;/p&gt;
&lt;p&gt;To explain quicksort in the style of Yoda, we might say something like:&lt;/p&gt;
&lt;p&gt;“Faster, quicksort is. In arrays of data, quickly it sorts. Divide and conquer, its strategy. A pivot it chooses, and to the left, all lesser values go. To the right, all greater values. And so on, until the array is fully sorted.”&lt;/p&gt;
&lt;p&gt;Here is an example of quicksort implemented in Python:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def quicksort(arr)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; len(arr) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return arr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  pivot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr[len(arr) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  left &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [x for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pivot]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  middle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [x for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pivot]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  right &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [x for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; arr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pivot]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  return quicksort(left) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; middle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; quicksort(right)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This implementation of quicksort uses the middle element of the array as the pivot, and recursively sorts the left and right halves of the array until it is fully sorted. This results in a much faster sorting process than bubble sort, especially for large datasets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That’s great, now just for good measure could you do the same for the other well known equally fast sorting algorithm, in a programming language other than Python, just pick one of your choice. And can you explain how it works and its time and space complexity in Dutch for our Dutch readers?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Another well-known sorting algorithm that is equally fast as quicksort is merge sort, which also has an average time complexity of O(n log n). Here is an example of merge sort implemented in Java:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;public void mergeSort(int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  if (array&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) return;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int mid &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Arrays.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;copyOfRange(array, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, mid);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Arrays.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;copyOfRange(array, mid, array&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  mergeSort(left);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  mergeSort(right);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  merge(array, left, right);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;public void merge(int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array, int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left, int&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  int k &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    if (left[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right[j]) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      j&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; left[i];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while (j &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;length) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    array[k] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; right[j];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    j&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    k&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This implementation of merge sort first divides the input array in half and recursively sorts the left and right halves. It then merges the two sorted halves together to produce a fully sorted array.&lt;/p&gt;
&lt;p&gt;In terms of time and space complexity, merge sort has an average time complexity of O(n log n) and a worst-case time complexity of O(n log n). It also has a space complexity of O(n), since it requires additional space to store the left and right halves of the array while they are being sorted.&lt;/p&gt;
&lt;p&gt;In Dutch, we might explain the working of merge sort and its time and space complexity as follows:&lt;/p&gt;
&lt;p&gt;“Merge sort is een snelle sorting algorithm met een gemiddelde tijdcomplexiteit van O(n log n) en een ruimtecomplexiteit van O(n). Het werkt door het invoerarray te splitsen in twee helften en deze recursief te sorteren. Vervolgens worden de gesorteerde helften samengevoegd tot een volledig gesorteerd array. Dit resulteert in een snellere sorteervoortgang dan bijvoorbeeld bubble sort, vooral voor grote datasets.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;512&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4uCuVuObNDGLhdldbBJpQA-357e44a0.C-ElvJhy_27Fczt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Generated using Stable Diffusion from the prompt “I am not a real person, but a computer program that uses artificial intelligence to process and generate natural language text.” from chatGPT’s introduction above.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You seem to be a good programmer and marketer, do you know something that you’re bad at?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a large language model trained by OpenAI, I am designed to assist with a wide range of language-related tasks, such as answering questions and providing explanations and information. I am not a real person and do not have personal abilities or skills, so I do not have any specific areas where I am “bad” at something. I am simply a computer program that uses artificial intelligence to process and generate natural language text based on my training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Yes but you can still be bad at something. I read in&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/dggoldst/status/1598317411698089984?s=20&amp;#x26;t=gZH9ocjKz_RlbP-iuSg4Bw&quot;&gt;&lt;strong&gt;another interview&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;that you gave a wrong answer to a question involving probabilities. Let me repeat it and we’ll see if you can get it right with this context: Linda is 31 years old, single, outspoken, and very bright. She majored in philosophy. As a student, she was deeply concerned with issues of discrimination and social justice, and also participated in anti-nuclear demonstrations.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which is more probable?&lt;br&gt;
— Linda is a bank teller.&lt;br&gt;
— Linda is a bank teller and is active in the feminist movement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the previous interview, I gave a wrong answer to this question because I did not have enough information to provide a correct answer. In order to determine the probabilities of the two scenarios, we would need to know the likelihoods of each individual component of the scenarios (i.e. being a bank teller, being active in the feminist movement, etc.). Without this information, it is impossible to accurately determine which scenario is more probable.&lt;/p&gt;
&lt;p&gt;In general, the probability of an event is determined by the likelihood of its individual components and their interactions. For example, if we know that the likelihood of Linda being a bank teller is 60%, and the likelihood of her being active in the feminist movement is 40%, the probability of her being both a bank teller and active in the feminist movement would be the product of these likelihoods (0.6 x 0.4 = 0.24, or 24%). This would be a more accurate answer to the question, but it would still require the specific likelihoods of the individual components in order to be certain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You almost got it right this time! With your reasoning, you’re right that you can’t give exact values without knowing those individual probabilities, but you can tell which of the two is more likely (you can assume that the probability that Linda is active in the feminist movement is less than 100%).&lt;br&gt;
Do you get it now?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ah, I see what you mean. Yes, based on the information provided and the assumption that the likelihood of Linda being active in the feminist movement is less than 100%, it is more probable that Linda is a bank teller than that she is both a bank teller and active in the feminist movement.&lt;/p&gt;
&lt;p&gt;To explain why, we can consider the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The probability of an event occurring is the product of the probabilities of its individual components. For example, if the probability of Linda being a bank teller is p, and the probability of her being active in the feminist movement is q, then the probability of her being both a bank teller and active in the feminist movement would be p * q.&lt;/li&gt;
&lt;li&gt;If the probability of one of the components of an event is less than 100%, then the probability of the event itself must be less than the probability of that component. For example, if the probability of Linda being a bank teller is p, and the probability of her being active in the feminist movement is q (where q &amp;#x3C; p), then the probability of her being both a bank teller and active in the feminist movement (p * q) must be less than the probability of her being a bank teller (p).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, based on the information provided and the assumption that the likelihood of Linda being active in the feminist movement is less than 100%, it is more probable that Linda is a bank teller than that she is both a bank teller and active in the feminist movement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exactly!&lt;br&gt;
Ok to close it off, I read in&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/raphaelmilliere/status/1598469100535259136?s=20&amp;#x26;t=gZH9ocjKz_RlbP-iuSg4Bw&quot;&gt;&lt;strong&gt;another interview&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;you rewrote Bohemian Rhapsody to be about the life of a postdoc. Let’s try something similar, could you rewrite Radiohead’s Creep to be about the life of a research software engineer at the Netherlands eScience Center? But don’t make it too depressing please.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here is a potential rewrite of Radiohead’s “Creep” to be about the life of a research software engineer at the Netherlands eScience Center:&lt;/p&gt;
&lt;p&gt;Verse 1:&lt;br&gt;
I’m a research software engineer&lt;br&gt;
At the Netherlands eScience&lt;br&gt;
Center Working on cutting-edge technology&lt;br&gt;
To advance academic discovery&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
But I’m just a research software engineer&lt;br&gt;
I’m not a real engineer&lt;br&gt;
I get lost in code and algorithms&lt;br&gt;
But sometimes I feel like a fraud&lt;/p&gt;
&lt;p&gt;Verse 2:&lt;br&gt;
I’m not a PhD or a professor&lt;br&gt;
But I’m passionate about software and research&lt;br&gt;
I collaborate and innovate&lt;br&gt;
To push the boundaries of what we know&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
But I’m just a research software engineer&lt;br&gt;
I’m not a real engineer&lt;br&gt;
I get lost in code and algorithms&lt;br&gt;
But sometimes I feel like a fraud&lt;/p&gt;
&lt;p&gt;Bridge:&lt;br&gt;
I may not have all the answers&lt;br&gt;
But I’m learning and growing every day&lt;br&gt;
I’m making a difference in academia&lt;br&gt;
And I’m proud of what I do&lt;/p&gt;
&lt;p&gt;Outro:&lt;br&gt;
I may not be a rockstar or a genius&lt;br&gt;
But I’m a research software engineer&lt;br&gt;
Pioneering new frontiers in science and technology&lt;br&gt;
At the Netherlands eScience Center.&lt;/p&gt;
&lt;p&gt;This rewritten version of “Creep” captures the experience of a research software engineer at the Netherlands eScience Center, highlighting their passion for software and research and their desire to make a difference in academia. It also touches on the challenges and doubts that they may face, but ultimately portrays them as proud and dedicated to their work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ok that was a bit more depressing than intended, but that’s my fault for picking the song. Can you do that again for a different song? This time I’ll let you pick it, but make it an uplifting one that everyone knows the lyrics to.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, how about “Don’t Stop Believin’” by Journey? Here is a potential rewrite of the song to be about the life of a research software engineer at the Netherlands eScience Center:&lt;/p&gt;
&lt;p&gt;Verse 1:&lt;br&gt;
Just a small town research software engineer&lt;br&gt;
At the Netherlands eScience Center&lt;br&gt;
Trying to make a difference in academia&lt;br&gt;
With cutting-edge software and technology&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Don’t stop believin’&lt;br&gt;
In the power of software and research&lt;br&gt;
To drive innovation and discovery&lt;br&gt;
At the Netherlands eScience Center&lt;/p&gt;
&lt;p&gt;Verse 2:&lt;br&gt;
I’m not a rockstar or a genius&lt;br&gt;
But I’m passionate about what I do&lt;br&gt;
I collaborate with researchers and engineers&lt;br&gt;
To unlock the potential of computing&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Don’t stop believin’&lt;br&gt;
In the power of software and research&lt;br&gt;
To drive innovation and discovery&lt;br&gt;
At the Netherlands eScience Center&lt;/p&gt;
&lt;p&gt;Bridge:&lt;br&gt;
I may not have all the answers&lt;br&gt;
But I’m learning and growing every day&lt;br&gt;
I’m making a difference in academia&lt;br&gt;
And I’m proud of what I do&lt;/p&gt;
&lt;p&gt;Outro:&lt;br&gt;
I may not be a rockstar or a genius&lt;br&gt;
But I’m a research software engineer&lt;br&gt;
Pioneering new frontiers in science and technology&lt;br&gt;
At the Netherlands eScience Center.&lt;/p&gt;
&lt;p&gt;This rewritten version of “Don’t Stop Believin’” captures the determination and optimism of a research software engineer at the Netherlands eScience Center, who is passionate about their work and believes in the power of software and research&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That’s more uplifting but it doesn’t match the original at all. I want you to take a song and change only the lyrics, but keep the rhythm and the structure of the song the same. Can you do that for Imagine? But again make it about being a research software engineer at the Netherlands eScience center?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sure, here is a potential rewrite of John Lennon’s “Imagine” to be about the life of a research software engineer at the Netherlands eScience Center:&lt;/p&gt;
&lt;p&gt;Verse 1:&lt;br&gt;
Imagine there’s no software engineers&lt;br&gt;
It’s easy if you try&lt;br&gt;
No algorithms to analyze&lt;br&gt;
No code to debug or optimize&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Imagine all the researchers&lt;br&gt;
With no software to enhance their work&lt;br&gt;
Imagine all the data&lt;br&gt;
With no tools to analyze and interpret&lt;/p&gt;
&lt;p&gt;Verse 2:&lt;br&gt;
Imagine we’re all research software engineers&lt;br&gt;
Working at the Netherlands eScience Center&lt;br&gt;
Collaborating, innovating, and learning&lt;br&gt;
To drive academic discovery&lt;/p&gt;
&lt;p&gt;Chorus:&lt;br&gt;
Imagine all the researchers&lt;br&gt;
With powerful software at their fingertips&lt;br&gt;
Imagine all the data&lt;br&gt;
Transformed into knowledge and insight&lt;/p&gt;
&lt;p&gt;Bridge:&lt;br&gt;
You may say I’m a dreamer&lt;br&gt;
But I’m not the only one&lt;br&gt;
I hope someday you’ll join us&lt;br&gt;
And the world will be as one&lt;/p&gt;
&lt;p&gt;Outro:&lt;br&gt;
Imagine no more software engineers&lt;br&gt;
I wonder if you can&lt;br&gt;
No need for them at all&lt;br&gt;
And no more research standing still.&lt;/p&gt;
&lt;p&gt;This rewritten version of “Imagine” portrays the crucial role of research software engineers in enabling academic research and driving discovery. It imagines a world where researchers have access to powerful software tools, and where the work of research software engineers is valued and appreciated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Awesome, thank you for your time. Is there anything else you want to say to our readers?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thank you for the opportunity to speak with you and to share a bit about my capabilities and how I can assist with language-related tasks. As a large language model trained by OpenAI, I am designed to assist with a wide range of language-related tasks, such as answering questions, providing explanations and information, and generating natural language text. I am constantly learning and improving, and I am always here to help. If you have any further questions or need assistance with anything, please feel free to ask. I am here to help in any way I can.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The above is an unedited* conversation with chatGPT, all its replies were its first try and were copied exactly and nothing has been left out. *: One exception, on Creep I gave it a second try, the first one was less funny and matched the original less.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_-kkZG6qFn9CuxovbPKA7og-47688cad.CtWP2oTu.png" medium="image"/><author>Aron</author></item><item><title>The Future of Research Software</title><link>https://blog2.esciencecenter.nl/posts/2022-11-23---the-future-of-research-software</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-11-23---the-future-of-research-software</guid><description>&lt;p&gt;By &lt;a href=&quot;https://www.researchsoft.org/people/&quot;&gt;Michelle Barker&lt;/a&gt; (&lt;a href=&quot;https://www.researchsoft.org/#&quot;&gt;Research Software Alliance&lt;/a&gt; (ReSA)), &lt;a href=&quot;https://www.software.ac.uk/about/staff/person/neil-chue-hong&quot;&gt;Neil Chue Hong&lt;/a&gt; (&lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;Software Sustainability Institute UK&lt;/a&gt;), &lt;a href=&quot;https://www.linkedin.com/in/mariajcruz/?originalSubdomain=nl&quot;&gt;Maria Cruz&lt;/a&gt; (&lt;a href=&quot;https://www.nwo.nl/en&quot;&gt;Dutch Research Council&lt;/a&gt;), &lt;a href=&quot;https://danielskatz.org/&quot;&gt;Daniel S. Katz&lt;/a&gt; (&lt;a href=&quot;https://www.ncsa.illinois.edu/&quot;&gt;National Center for Supercomputing Applications&lt;/a&gt; at the &lt;a href=&quot;https://illinois.edu/&quot;&gt;University of Illinois Urbana-Champaign&lt;/a&gt;), and from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/valentina-azzara/&quot;&gt;Valentina Azzarà&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;Tom Bakker&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-niels-drost/&quot;&gt;Niels Drost&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-joris-van-eijnatten/&quot;&gt;Joris van Eijnatten&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-maaike-de-jong/&quot;&gt;Maaike de Jong&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/veronica-pang/&quot;&gt;Veronica Pang&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog post is being cross-posted by the&lt;/em&gt; &lt;em&gt;ReSA&lt;/em&gt; &lt;em&gt;and&lt;/em&gt; &lt;em&gt;Netherlands eScience Center&lt;/em&gt;*.*&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;532&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_qR7wedlERZDzzYFuBy2-Mg-d89911f6.De0bO401_1pkxmH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Carole Goble, University of Manchester at the International Funders Workshop: The Future of Research Software (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;On 8 and 9 November, the &lt;a href=&quot;https://www.researchsoft.org/&quot;&gt;Research Software Alliance (ReSA)&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; organized the &lt;a href=&quot;https://www.future-of-research-software.org/&quot;&gt;International Funders Workshop: The Future of Research Software&lt;/a&gt;. During this workshop, a number of members from the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; came together with other organizations that support research software. During the workshop, participants explored how to effectively fund new and existing research software. In total, more than 60 representatives from &lt;a href=&quot;https://future-of-research-software.org/participants/&quot;&gt;45 organisations&lt;/a&gt; attended the workshop.&lt;/p&gt;
&lt;p&gt;Imagine a world without research software. It’s a world in which researchers cannot build and operate modern scientific instruments; nor model climate change, ecosystems, human bodies, virus outbreaks, social interactions or inequality. A world in which they would not be able to process research data or automate, share, reproduce and reuse research methods.&lt;/p&gt;
&lt;p&gt;The crucial role of software in research and the urgent need to sustain it and to invest in the people who develop and maintain it has led to several funders to come together in the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt;, a collaboration of funding organizations (supported by the &lt;a href=&quot;https://sloan.org/&quot;&gt;Alfred P. Sloan Foundation&lt;/a&gt;) committed to supporting research software and those who develop it as fundamental and vital to research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_f128BA-9iCr8-5bOefyA-g-119df372.UjTPLIk3_Z249NyB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Global representatives from funding organizations and organizations that work with research software (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;Members from the Forum met with other organizations that support research software at the International Funders Workshop, which is summarised in the report, &lt;a href=&quot;https://doi.org/10.5281/zenodo.7350199&quot;&gt;&lt;strong&gt;Global gathering of research software funders sets the agenda for supporting sustainable research software&lt;/strong&gt;&lt;/a&gt;. It was an opportunity for participants to explore how they can effectively contribute to making research software sustainable. Participants shared their experiences, which varied widely. Not only in the size of the participants’ budgets, but also where programmes are situated, whether they specifically focus on research software, and also what they target.&lt;/p&gt;
&lt;p&gt;A major part of the workshop focused on drafting the &lt;a href=&quot;https://zenodo.org/record/7330542&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability&lt;/a&gt;. Research software is &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;defined&lt;/a&gt; within the Declaration as source code files, algorithms, scripts, computational workflows and executables that were created during the research process or for a research purpose.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LUwi5iKx3dkZwd347zCHxw-537661e1.rtNfyEWU_JRIju.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Representatives discuss funding sustainable research software (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;During the discussion sessions at the Workshop it became clear that to make software sustainable, there is a need for a wide set of roles and career pathways, including technical specialists, but also community managers and knowledge transfer expertise. Funders should ensure that these and other roles can be included in funding requests.&lt;/p&gt;
&lt;p&gt;Additionally, in order for funders to understand the international landscape, international collaboration is needed. Because while funders typically work in a national or regional scope, research software is global.&lt;/p&gt;
&lt;p&gt;Lastly, and importantly, there was a desire to ensure that ethics, environmental sustainability; and that diversity, equity and inclusion are not lost or assumed when thinking about software sustainability.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;532&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DuHyvZVMH6NFTDVWJV0Luw-a75b0b81.BosCmric_Z1VNJ3n.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Neil Chue Hong, Director of the Software Sustainability Institute (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;This workshop marks a further step in the development of the research software community. As &lt;a href=&quot;https://www.software.ac.uk/about/staff/person/neil-chue-hong&quot;&gt;Neil Chue Hong&lt;/a&gt;, Director of the &lt;a href=&quot;https://www.ed.ac.uk/profile/neil-chue-hong&quot;&gt;Software Sustainability Institute&lt;/a&gt;, noted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ten years ago, I could never have imagined that a workshop like this would be possible. Open data had just been coined as a term. The visibility of software as part of the research ecosystem in the wider community was minimal, despite many large programmes funding research software in the 1990s and 2000s. But since then the Carpentries has taught workshops on all seven continents, a new professional society for Research Software Engineers has been born, and research software is everywhere. This has been amazing.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://future-of-research-software.org/presentations&quot;&gt;Videos and slides&lt;/a&gt; of all of the keynotes are available: &lt;a href=&quot;https://danielskatz.org/&quot;&gt;Daniel S. Katz&lt;/a&gt;, Chief Scientist at the National Center for Supercomputing Applications (NCSA) and Research Associate Professor in Computer Science at the University of Illinois at Urbana-Champaign, USA, and &lt;a href=&quot;https://www.research.manchester.ac.uk/portal/carole.goble.html&quot;&gt;Carole Goble&lt;/a&gt;, a Professor of Computer Science at the University of Manchester, UK, set the scene to enable attendees to form a better common understanding of the place of research software. &lt;a href=&quot;https://www.uva.nl/en/profile/l/e/a.g.j.vanleeuwen/a.g.j.vanleeuwen.html?cb=&quot;&gt;Joeri van Leeuwen&lt;/a&gt;, Senior Astronomer at the Netherlands Institute for Radio Astronomy (ASTRON), Netherlands; and &lt;a href=&quot;https://fapesp.br/index.php/7140/fabio-kon&quot;&gt;Fabio Kon&lt;/a&gt;, Special Advisor, São Paulo Research Foundation (FAPESP), Brazil, shared their researcher and funder perspectives (respectively), thoughts on why and how to care about research software and the people who develop and maintain it, and ideas for how to better recognise their importance.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_W_xh_gYDEpsiYI3Li2gNTg-cfab57bc.6dqVLb-D_Z1i8B8J.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Participants at the International Funders Workshop (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;The next ReSA &lt;a href=&quot;https://www.researchsoft.org/events/2022-06/&quot;&gt;Research Software Community Forum&lt;/a&gt; on 29 November, 16:00–17:00 CET, will also feature Joris van Eijnatten from the Netherlands eScience Center, who will discuss the workshop outcomes and next steps in this public forum.&lt;/p&gt;
&lt;p&gt;Drafting of the Declaration will now continue; if you would like to be kept up to date and potentially be involved in this process then email &lt;a href=&quot;mailto:amsterdamdeclaration@esciencecenter.nl&quot;&gt;amsterdamdeclaration@esciencecenter.nl&lt;/a&gt; to request to be sent subscription details when available.&lt;/p&gt;</description><pubDate>Wed, 23 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;By &lt;a href=&quot;https://www.researchsoft.org/people/&quot;&gt;Michelle Barker&lt;/a&gt; (&lt;a href=&quot;https://www.researchsoft.org/#&quot;&gt;Research Software Alliance&lt;/a&gt; (ReSA)), &lt;a href=&quot;https://www.software.ac.uk/about/staff/person/neil-chue-hong&quot;&gt;Neil Chue Hong&lt;/a&gt; (&lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;Software Sustainability Institute UK&lt;/a&gt;), &lt;a href=&quot;https://www.linkedin.com/in/mariajcruz/?originalSubdomain=nl&quot;&gt;Maria Cruz&lt;/a&gt; (&lt;a href=&quot;https://www.nwo.nl/en&quot;&gt;Dutch Research Council&lt;/a&gt;), &lt;a href=&quot;https://danielskatz.org/&quot;&gt;Daniel S. Katz&lt;/a&gt; (&lt;a href=&quot;https://www.ncsa.illinois.edu/&quot;&gt;National Center for Supercomputing Applications&lt;/a&gt; at the &lt;a href=&quot;https://illinois.edu/&quot;&gt;University of Illinois Urbana-Champaign&lt;/a&gt;), and from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/valentina-azzara/&quot;&gt;Valentina Azzarà&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;Tom Bakker&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-niels-drost/&quot;&gt;Niels Drost&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-joris-van-eijnatten/&quot;&gt;Joris van Eijnatten&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-maaike-de-jong/&quot;&gt;Maaike de Jong&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-carlos-martinez-ortiz/&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/veronica-pang/&quot;&gt;Veronica Pang&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This blog post is being cross-posted by the&lt;/em&gt; &lt;em&gt;ReSA&lt;/em&gt; &lt;em&gt;and&lt;/em&gt; &lt;em&gt;Netherlands eScience Center&lt;/em&gt;*.*&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;532&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_qR7wedlERZDzzYFuBy2-Mg-d89911f6.De0bO401_1pkxmH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Carole Goble, University of Manchester at the International Funders Workshop: The Future of Research Software (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;On 8 and 9 November, the &lt;a href=&quot;https://www.researchsoft.org/&quot;&gt;Research Software Alliance (ReSA)&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; organized the &lt;a href=&quot;https://www.future-of-research-software.org/&quot;&gt;International Funders Workshop: The Future of Research Software&lt;/a&gt;. During this workshop, a number of members from the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt; came together with other organizations that support research software. During the workshop, participants explored how to effectively fund new and existing research software. In total, more than 60 representatives from &lt;a href=&quot;https://future-of-research-software.org/participants/&quot;&gt;45 organisations&lt;/a&gt; attended the workshop.&lt;/p&gt;
&lt;p&gt;Imagine a world without research software. It’s a world in which researchers cannot build and operate modern scientific instruments; nor model climate change, ecosystems, human bodies, virus outbreaks, social interactions or inequality. A world in which they would not be able to process research data or automate, share, reproduce and reuse research methods.&lt;/p&gt;
&lt;p&gt;The crucial role of software in research and the urgent need to sustain it and to invest in the people who develop and maintain it has led to several funders to come together in the &lt;a href=&quot;https://www.researchsoft.org/funders-forum/&quot;&gt;Research Software Funders Forum&lt;/a&gt;, a collaboration of funding organizations (supported by the &lt;a href=&quot;https://sloan.org/&quot;&gt;Alfred P. Sloan Foundation&lt;/a&gt;) committed to supporting research software and those who develop it as fundamental and vital to research.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_f128BA-9iCr8-5bOefyA-g-119df372.UjTPLIk3_Z249NyB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Global representatives from funding organizations and organizations that work with research software (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;Members from the Forum met with other organizations that support research software at the International Funders Workshop, which is summarised in the report, &lt;a href=&quot;https://doi.org/10.5281/zenodo.7350199&quot;&gt;&lt;strong&gt;Global gathering of research software funders sets the agenda for supporting sustainable research software&lt;/strong&gt;&lt;/a&gt;. It was an opportunity for participants to explore how they can effectively contribute to making research software sustainable. Participants shared their experiences, which varied widely. Not only in the size of the participants’ budgets, but also where programmes are situated, whether they specifically focus on research software, and also what they target.&lt;/p&gt;
&lt;p&gt;A major part of the workshop focused on drafting the &lt;a href=&quot;https://zenodo.org/record/7330542&quot;&gt;Amsterdam Declaration on Funding Research Software Sustainability&lt;/a&gt;. Research software is &lt;a href=&quot;https://doi.org/10.1038/s41597-022-01710-x&quot;&gt;defined&lt;/a&gt; within the Declaration as source code files, algorithms, scripts, computational workflows and executables that were created during the research process or for a research purpose.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LUwi5iKx3dkZwd347zCHxw-537661e1.rtNfyEWU_JRIju.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Representatives discuss funding sustainable research software (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;During the discussion sessions at the Workshop it became clear that to make software sustainable, there is a need for a wide set of roles and career pathways, including technical specialists, but also community managers and knowledge transfer expertise. Funders should ensure that these and other roles can be included in funding requests.&lt;/p&gt;
&lt;p&gt;Additionally, in order for funders to understand the international landscape, international collaboration is needed. Because while funders typically work in a national or regional scope, research software is global.&lt;/p&gt;
&lt;p&gt;Lastly, and importantly, there was a desire to ensure that ethics, environmental sustainability; and that diversity, equity and inclusion are not lost or assumed when thinking about software sustainability.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;532&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DuHyvZVMH6NFTDVWJV0Luw-a75b0b81.BosCmric_Z1VNJ3n.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Neil Chue Hong, Director of the Software Sustainability Institute (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;This workshop marks a further step in the development of the research software community. As &lt;a href=&quot;https://www.software.ac.uk/about/staff/person/neil-chue-hong&quot;&gt;Neil Chue Hong&lt;/a&gt;, Director of the &lt;a href=&quot;https://www.ed.ac.uk/profile/neil-chue-hong&quot;&gt;Software Sustainability Institute&lt;/a&gt;, noted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ten years ago, I could never have imagined that a workshop like this would be possible. Open data had just been coined as a term. The visibility of software as part of the research ecosystem in the wider community was minimal, despite many large programmes funding research software in the 1990s and 2000s. But since then the Carpentries has taught workshops on all seven continents, a new professional society for Research Software Engineers has been born, and research software is everywhere. This has been amazing.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://future-of-research-software.org/presentations&quot;&gt;Videos and slides&lt;/a&gt; of all of the keynotes are available: &lt;a href=&quot;https://danielskatz.org/&quot;&gt;Daniel S. Katz&lt;/a&gt;, Chief Scientist at the National Center for Supercomputing Applications (NCSA) and Research Associate Professor in Computer Science at the University of Illinois at Urbana-Champaign, USA, and &lt;a href=&quot;https://www.research.manchester.ac.uk/portal/carole.goble.html&quot;&gt;Carole Goble&lt;/a&gt;, a Professor of Computer Science at the University of Manchester, UK, set the scene to enable attendees to form a better common understanding of the place of research software. &lt;a href=&quot;https://www.uva.nl/en/profile/l/e/a.g.j.vanleeuwen/a.g.j.vanleeuwen.html?cb=&quot;&gt;Joeri van Leeuwen&lt;/a&gt;, Senior Astronomer at the Netherlands Institute for Radio Astronomy (ASTRON), Netherlands; and &lt;a href=&quot;https://fapesp.br/index.php/7140/fabio-kon&quot;&gt;Fabio Kon&lt;/a&gt;, Special Advisor, São Paulo Research Foundation (FAPESP), Brazil, shared their researcher and funder perspectives (respectively), thoughts on why and how to care about research software and the people who develop and maintain it, and ideas for how to better recognise their importance.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;799&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_W_xh_gYDEpsiYI3Li2gNTg-cfab57bc.6dqVLb-D_Z1i8B8J.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Participants at the International Funders Workshop (Photo credit: Annelies Verhelst )&lt;/p&gt;
&lt;p&gt;The next ReSA &lt;a href=&quot;https://www.researchsoft.org/events/2022-06/&quot;&gt;Research Software Community Forum&lt;/a&gt; on 29 November, 16:00–17:00 CET, will also feature Joris van Eijnatten from the Netherlands eScience Center, who will discuss the workshop outcomes and next steps in this public forum.&lt;/p&gt;
&lt;p&gt;Drafting of the Declaration will now continue; if you would like to be kept up to date and potentially be involved in this process then email &lt;a href=&quot;mailto:amsterdamdeclaration@esciencecenter.nl&quot;&gt;amsterdamdeclaration@esciencecenter.nl&lt;/a&gt; to request to be sent subscription details when available.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_qR7wedlERZDzzYFuBy2-Mg-d89911f6.De0bO401.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Software in the spotlight: launching the Research Software Directory</title><link>https://blog2.esciencecenter.nl/posts/2022-11-22---software-in-the-spotlight-launching-the-research-software-di</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-11-22---software-in-the-spotlight-launching-the-research-software-di</guid><description>&lt;p&gt;The RSD has been in use by the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; as a prototype for several years. Open source software for research lies at the heart of the mission of the Center. The eScience Center collaborates with researchers across all disciplines to create high-quality open software for academic research. The RSD was initially used to collect the software developed in these collaborations. After ample outside interest, a team of developers from the eScience Center and the &lt;a href=&quot;https://www.helmholtz.de/en/&quot;&gt;Helmholtz Association&lt;/a&gt; has transformed the RSD into a service that can be used by all researchers and research organizations.&lt;/p&gt;
&lt;h3 id=&quot;focus-on-research-software-at-digital-competence-centers&quot;&gt;Focus on research software at Digital Competence Centers**&lt;/h3&gt;
&lt;p&gt;As the result of a project funded by &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt;, several Digital Competence Centers (DCCs) in the Netherlands are now implementing the RSD at their research organization. As centres of expertise in data, software, and computing for research organizations, the DCCs are well-positioned to facilitate the use of the RSD by their researchers.&lt;/p&gt;
&lt;p&gt;Many of the DCCs have sustainable software development and maintenance high on their agendas. For instance, at &lt;strong&gt;AmsterdamUMC&lt;/strong&gt;, the majority of research groups develop software, especially for statistical analysis, genomics, image processing, data curation, Natural Language Processing (NLP) and machine learning. The AmsterdamUMC DCC is formulating guidelines for researchers with tips and tricks to enhance software quality and performance. Essential infrastructure such as software repositories, software management plans and courses to educate researchers are also in development. And soon, Amsterdam UMC will showcase its research software products in the RSD to promote the reuse of research software and to foster the appreciation of software as research output in the biomedical sciences.&lt;/p&gt;
&lt;p&gt;In July, &lt;strong&gt;Leiden University&lt;/strong&gt; welcomed Dan Rudmann, their first Digital Scholarship Librarian with a specific focus on research software. Dan is initiating the Research Software Community Leiden and supporting the Leiden DCC. This involves bringing together people at the university who have an interest in research software to generate practices and protocols that are FAIR, open, and secure. Leiden University is also establishing software management plans and policies. The RSD is a boon to this work.&lt;/p&gt;
&lt;p&gt;At &lt;strong&gt;Utrecht University&lt;/strong&gt;, researchers and research software engineers at each faculty develop research software. Utrecht University has a central Research Data Management Support group that’s similar to other institutions’ DCCs. The software and data experts in this group develop research software in joint projects with UU researchers and provide them with training and advice. Utrecht University’s &lt;a href=&quot;https://github.com/UtrechtUniversity&quot;&gt;GitHub organization&lt;/a&gt; contains over 200 repositories, 100 members and 25 teams, where UU staff share and collaboratively develop research software. The &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management&quot;&gt;Research Data Management Support group&lt;/a&gt; offers elaborate manuals and interesting, well-documented projects as inspiring examples to make it easy and attractive for researchers to use this organization.&lt;/p&gt;
&lt;p&gt;Utrecht University recently started registering &lt;a href=&quot;https://research-software-directory.org/organisations/utrecht-university&quot;&gt;their research software in the RSD&lt;/a&gt;. The &lt;a href=&quot;https://twitter.com/RDMsupportUU&quot;&gt;Research Data Management Support group&lt;/a&gt; plays an active role in campaigning for their colleagues to add their software to the RSD. As Martine de Vos, team lead of software engineer for the RDM Support group puts it: “We want to increase the impact of our own software, but we are also highly interested in the work of our colleagues at other institutions. We hope many researchers will register their software in the RSD, as we think size matters.”&lt;/p&gt;
&lt;h3 id=&quot;community-adoption-of-the-rsd&quot;&gt;&lt;strong&gt;Community adoption of the RSD&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For the near future, the RSD team aims for wider adoption of the service by the research community. To an extent, this is already happening: Dutch and international research organizations are already joining the effort to make research software more visible by signing up for the RSD.&lt;/p&gt;
&lt;p&gt;The collaboration with the DCCs will answer important questions about how the RSD can be embedded within organizations. For example, which underlying tools or infrastructure are required or helpful (e.g. a central GitHub or Gitlab instance), how it fits into workflows and roles (e.g. who should be responsible for entering software), what type of support is needed (e.g. on choosing licenses), and how it relates to institutional policy on software. The RSD team will publish their findings from the collaboration, so organizations across the world can learn how to best implement the RSD.&lt;/p&gt;
&lt;p&gt;On 22 November 2022, the RSD was officially launched during an online event. If you want to learn more about the RSD or have questions about implementing it at your organization, check the recording of the online launch here.&lt;/p&gt;</description><pubDate>Tue, 22 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The RSD has been in use by the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; as a prototype for several years. Open source software for research lies at the heart of the mission of the Center. The eScience Center collaborates with researchers across all disciplines to create high-quality open software for academic research. The RSD was initially used to collect the software developed in these collaborations. After ample outside interest, a team of developers from the eScience Center and the &lt;a href=&quot;https://www.helmholtz.de/en/&quot;&gt;Helmholtz Association&lt;/a&gt; has transformed the RSD into a service that can be used by all researchers and research organizations.&lt;/p&gt;
&lt;h3 id=&quot;focus-on-research-software-at-digital-competence-centers&quot;&gt;Focus on research software at Digital Competence Centers**&lt;/h3&gt;
&lt;p&gt;As the result of a project funded by &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt;, several Digital Competence Centers (DCCs) in the Netherlands are now implementing the RSD at their research organization. As centres of expertise in data, software, and computing for research organizations, the DCCs are well-positioned to facilitate the use of the RSD by their researchers.&lt;/p&gt;
&lt;p&gt;Many of the DCCs have sustainable software development and maintenance high on their agendas. For instance, at &lt;strong&gt;AmsterdamUMC&lt;/strong&gt;, the majority of research groups develop software, especially for statistical analysis, genomics, image processing, data curation, Natural Language Processing (NLP) and machine learning. The AmsterdamUMC DCC is formulating guidelines for researchers with tips and tricks to enhance software quality and performance. Essential infrastructure such as software repositories, software management plans and courses to educate researchers are also in development. And soon, Amsterdam UMC will showcase its research software products in the RSD to promote the reuse of research software and to foster the appreciation of software as research output in the biomedical sciences.&lt;/p&gt;
&lt;p&gt;In July, &lt;strong&gt;Leiden University&lt;/strong&gt; welcomed Dan Rudmann, their first Digital Scholarship Librarian with a specific focus on research software. Dan is initiating the Research Software Community Leiden and supporting the Leiden DCC. This involves bringing together people at the university who have an interest in research software to generate practices and protocols that are FAIR, open, and secure. Leiden University is also establishing software management plans and policies. The RSD is a boon to this work.&lt;/p&gt;
&lt;p&gt;At &lt;strong&gt;Utrecht University&lt;/strong&gt;, researchers and research software engineers at each faculty develop research software. Utrecht University has a central Research Data Management Support group that’s similar to other institutions’ DCCs. The software and data experts in this group develop research software in joint projects with UU researchers and provide them with training and advice. Utrecht University’s &lt;a href=&quot;https://github.com/UtrechtUniversity&quot;&gt;GitHub organization&lt;/a&gt; contains over 200 repositories, 100 members and 25 teams, where UU staff share and collaboratively develop research software. The &lt;a href=&quot;https://www.uu.nl/en/research/research-data-management&quot;&gt;Research Data Management Support group&lt;/a&gt; offers elaborate manuals and interesting, well-documented projects as inspiring examples to make it easy and attractive for researchers to use this organization.&lt;/p&gt;
&lt;p&gt;Utrecht University recently started registering &lt;a href=&quot;https://research-software-directory.org/organisations/utrecht-university&quot;&gt;their research software in the RSD&lt;/a&gt;. The &lt;a href=&quot;https://twitter.com/RDMsupportUU&quot;&gt;Research Data Management Support group&lt;/a&gt; plays an active role in campaigning for their colleagues to add their software to the RSD. As Martine de Vos, team lead of software engineer for the RDM Support group puts it: “We want to increase the impact of our own software, but we are also highly interested in the work of our colleagues at other institutions. We hope many researchers will register their software in the RSD, as we think size matters.”&lt;/p&gt;
&lt;h3 id=&quot;community-adoption-of-the-rsd&quot;&gt;&lt;strong&gt;Community adoption of the RSD&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;For the near future, the RSD team aims for wider adoption of the service by the research community. To an extent, this is already happening: Dutch and international research organizations are already joining the effort to make research software more visible by signing up for the RSD.&lt;/p&gt;
&lt;p&gt;The collaboration with the DCCs will answer important questions about how the RSD can be embedded within organizations. For example, which underlying tools or infrastructure are required or helpful (e.g. a central GitHub or Gitlab instance), how it fits into workflows and roles (e.g. who should be responsible for entering software), what type of support is needed (e.g. on choosing licenses), and how it relates to institutional policy on software. The RSD team will publish their findings from the collaboration, so organizations across the world can learn how to best implement the RSD.&lt;/p&gt;
&lt;p&gt;On 22 November 2022, the RSD was officially launched during an online event. If you want to learn more about the RSD or have questions about implementing it at your organization, check the recording of the online launch here.&lt;/p&gt;</content:encoded><author>eScience Editorial Team</author></item><item><title>Unweaving legacy code using Entangled</title><link>https://blog2.esciencecenter.nl/posts/2022-11-10---unweaving-legacy-code-using-entangled</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-11-10---unweaving-legacy-code-using-entangled</guid><description>&lt;p&gt;For a Research Software Engineer, dealing with legacy code is seen as a chore: dirty work, but a necessary evil. But the truth is, every time I read someone else’s code, I learn something. Using Entangled to work out how some obscure code works also makes it kind of fun!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Old punchcard as epitome of legacy code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;613&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ilw6P_BRplg-NVlLgG_zRQ-ffe6dab2.UXK47Sfo_Z1fcb5g.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Punchcard (credit: Pete Birkinshaw from Manchester, UK)&lt;/p&gt;
&lt;p&gt;On a typical day in the life of a Research Software Engineer (RSE), out on the prairies of academia, scavenging for source code, the RSE often encounters source codes for computer programs that have a lot to be desired in terms of readability, reusability, and, to summarize, in terms most modern standards. RSEs have coined a few derogatory terms for these code bases: &lt;em&gt;PhD-ware&lt;/em&gt;, &lt;em&gt;labware,&lt;/em&gt; or, heaven forbid, &lt;em&gt;professor-ware&lt;/em&gt;. The proper academic name for these creatures is &lt;em&gt;legacy code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How we handle these codes depends entirely on the situation. Suppose the correct functioning of the software is responsible for some important research output. We would like to reproduce the said output, or at the very least understand &lt;em&gt;exactly&lt;/em&gt; how these results were obtained. In an ideal case, it should be enough to read the corresponding journal article and see that it matches what is done in the code. Then we can start changing the model or fiddling with newer data and derive our own conclusions.&lt;/p&gt;
&lt;p&gt;When first faced with a new body of source code, the task of disentangling exactly how it works can be quite daunting. In many legacy codes, readability was not a primary concern. In science land it is “ &lt;em&gt;publish or perish”&lt;/em&gt;, never mind documenting your code. &lt;strong&gt;How can we figure out the inner workings of a code in a systematic way, such that the next pair of eyes will have an easier time?&lt;/strong&gt; This is where &lt;a href=&quot;https://entangled.github.io/&quot;&gt;Entangled&lt;/a&gt; comes in.&lt;/p&gt;
&lt;p&gt;Entangled is an engine for doing &lt;a href=&quot;https://blog.esciencecenter.nl/literate-programming-in-science-1669094541a7&quot;&gt;literate programming&lt;/a&gt; in Markdown. This means you can write entire computer programs from code blocks embedded in a reader-friendly Markdown document. Code blocks can &lt;em&gt;quote&lt;/em&gt; other code blocks by including &lt;code&gt;&amp;#x3C;&amp;#x3C;reference&gt;&gt;&lt;/code&gt; tags. Entangled replaces these tags with their content in the final output source code. This way, we take a source code apart while the functioning of the compiled program is completely preserved.&lt;/p&gt;
&lt;p&gt;So, how do we attack the problem of dissecting our unknown code base? We start with a Markdown file containing, in a code block, the code that we’re interested in. If we find interesting bits, cut out the relevant code, put it in a separate block, and replace it in the original code with a reference. The Markdown lets us put parts of the code in different sections, and add documentation, derivations, tables, references, or even our own thoughts. Repeat until satisfied.&lt;/p&gt;
&lt;p&gt;Depending on the size of the project you may want to disentangle just a few essential files in this manner, or perhaps you prefer to deconstruct the entire code. It doesn’t matter. The resulting Markdown files can be converted for online reading using any of your favourite tools: Pandoc, MkDocs, Jekyll, you name it.&lt;/p&gt;
&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;
&lt;p&gt;This all doesn’t mean much without a decent example, so let’s see a couple of them.&lt;/p&gt;
&lt;p&gt;The first example we’ll look at is one that I picked from Rosetta Code. It’s an implementation of the game &lt;a href=&quot;https://rosettacode.org/wiki/Snake#UNIX_Shell&quot;&gt;Snake in Bash&lt;/a&gt;. Since Bash can be quite a dense language to read, we may learn a lot by destructuring even this tiny program.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Screenshot of webbrowser&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1019&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jxEcYwxE1UA_d2o1PbRylw-18969b0e.GRocYSM9_ZXqzbk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Legacy code, looking readable thanks to Entangled&lt;/p&gt;
&lt;p&gt;As far as Bash scripts go, this is reasonably clean code, so not your worst nightmare. I encourage you to take a look at the full result at &lt;a href=&quot;https://jhidding.github.io/shell-snake&quot;&gt;jhidding.github.io/shell-snake&lt;/a&gt;. As you may see, I have split the program into three parts: setup, main loop, and post-mortem. If I were more interested, I could further pull apart some expressions, building a deeper hierarchy. If I’m unhappy with some part, I can swap out some code in a well-documented manner.&lt;/p&gt;
&lt;p&gt;The second example is a bit bigger. Also, this time I’ve translated the source code from C++ to Rust. There is a 100-sloc C++ code for ray tracing a set of spheres by Kevin Beason, called &lt;a href=&quot;https://www.kevinbeason.com/smallpt/&quot;&gt;SmallPT&lt;/a&gt; (it is quite famous in some circles). While the original is focused on getting as much as possible into a hundred lines of code, I wanted a bit more understanding. A ray tracer computes an image by doing a physical simulation of millions of photons in a given scene.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3wtAt6IzGk2lxdeQw1lf9g-58674538.BxQysIvS_b8dGq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A ray-traced rendering of a few spheres.&lt;/p&gt;
&lt;p&gt;The full demo can be found here: &lt;a href=&quot;https://jhidding.github.io/literatept/&quot;&gt;jhidding.github.io/literatept&lt;/a&gt;. I made some algorithmic changes to the original that are well documented. See for instance the &lt;a href=&quot;https://jhidding.github.io/literatept/#path-tracing&quot;&gt;section on path tracing&lt;/a&gt;. In another instance, I tried to understand the underlying physics of &lt;a href=&quot;https://jhidding.github.io/literatept/#partial-reflection&quot;&gt;reflecting rays in the transparent sphere&lt;/a&gt;. There I was able to underpin the code with equations and references.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does this sound interesting to you? Then you may like to get Entangled at &lt;a href=&quot;https://entangled.github.io/&quot;&gt;https://entangled.github.io/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also read my other blog posts about &lt;a href=&quot;https://blog.esciencecenter.nl/literate-programming-in-science-1669094541a7&quot;&gt;Literate Programming in Science&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><pubDate>Thu, 10 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For a Research Software Engineer, dealing with legacy code is seen as a chore: dirty work, but a necessary evil. But the truth is, every time I read someone else’s code, I learn something. Using Entangled to work out how some obscure code works also makes it kind of fun!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Old punchcard as epitome of legacy code&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;613&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ilw6P_BRplg-NVlLgG_zRQ-ffe6dab2.UXK47Sfo_Z1fcb5g.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Punchcard (credit: Pete Birkinshaw from Manchester, UK)&lt;/p&gt;
&lt;p&gt;On a typical day in the life of a Research Software Engineer (RSE), out on the prairies of academia, scavenging for source code, the RSE often encounters source codes for computer programs that have a lot to be desired in terms of readability, reusability, and, to summarize, in terms most modern standards. RSEs have coined a few derogatory terms for these code bases: &lt;em&gt;PhD-ware&lt;/em&gt;, &lt;em&gt;labware,&lt;/em&gt; or, heaven forbid, &lt;em&gt;professor-ware&lt;/em&gt;. The proper academic name for these creatures is &lt;em&gt;legacy code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How we handle these codes depends entirely on the situation. Suppose the correct functioning of the software is responsible for some important research output. We would like to reproduce the said output, or at the very least understand &lt;em&gt;exactly&lt;/em&gt; how these results were obtained. In an ideal case, it should be enough to read the corresponding journal article and see that it matches what is done in the code. Then we can start changing the model or fiddling with newer data and derive our own conclusions.&lt;/p&gt;
&lt;p&gt;When first faced with a new body of source code, the task of disentangling exactly how it works can be quite daunting. In many legacy codes, readability was not a primary concern. In science land it is “ &lt;em&gt;publish or perish”&lt;/em&gt;, never mind documenting your code. &lt;strong&gt;How can we figure out the inner workings of a code in a systematic way, such that the next pair of eyes will have an easier time?&lt;/strong&gt; This is where &lt;a href=&quot;https://entangled.github.io/&quot;&gt;Entangled&lt;/a&gt; comes in.&lt;/p&gt;
&lt;p&gt;Entangled is an engine for doing &lt;a href=&quot;https://blog.esciencecenter.nl/literate-programming-in-science-1669094541a7&quot;&gt;literate programming&lt;/a&gt; in Markdown. This means you can write entire computer programs from code blocks embedded in a reader-friendly Markdown document. Code blocks can &lt;em&gt;quote&lt;/em&gt; other code blocks by including &lt;code&gt;&amp;#x3C;&amp;#x3C;reference&gt;&gt;&lt;/code&gt; tags. Entangled replaces these tags with their content in the final output source code. This way, we take a source code apart while the functioning of the compiled program is completely preserved.&lt;/p&gt;
&lt;p&gt;So, how do we attack the problem of dissecting our unknown code base? We start with a Markdown file containing, in a code block, the code that we’re interested in. If we find interesting bits, cut out the relevant code, put it in a separate block, and replace it in the original code with a reference. The Markdown lets us put parts of the code in different sections, and add documentation, derivations, tables, references, or even our own thoughts. Repeat until satisfied.&lt;/p&gt;
&lt;p&gt;Depending on the size of the project you may want to disentangle just a few essential files in this manner, or perhaps you prefer to deconstruct the entire code. It doesn’t matter. The resulting Markdown files can be converted for online reading using any of your favourite tools: Pandoc, MkDocs, Jekyll, you name it.&lt;/p&gt;
&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;
&lt;p&gt;This all doesn’t mean much without a decent example, so let’s see a couple of them.&lt;/p&gt;
&lt;p&gt;The first example we’ll look at is one that I picked from Rosetta Code. It’s an implementation of the game &lt;a href=&quot;https://rosettacode.org/wiki/Snake#UNIX_Shell&quot;&gt;Snake in Bash&lt;/a&gt;. Since Bash can be quite a dense language to read, we may learn a lot by destructuring even this tiny program.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Screenshot of webbrowser&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1019&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jxEcYwxE1UA_d2o1PbRylw-18969b0e.GRocYSM9_ZXqzbk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Legacy code, looking readable thanks to Entangled&lt;/p&gt;
&lt;p&gt;As far as Bash scripts go, this is reasonably clean code, so not your worst nightmare. I encourage you to take a look at the full result at &lt;a href=&quot;https://jhidding.github.io/shell-snake&quot;&gt;jhidding.github.io/shell-snake&lt;/a&gt;. As you may see, I have split the program into three parts: setup, main loop, and post-mortem. If I were more interested, I could further pull apart some expressions, building a deeper hierarchy. If I’m unhappy with some part, I can swap out some code in a well-documented manner.&lt;/p&gt;
&lt;p&gt;The second example is a bit bigger. Also, this time I’ve translated the source code from C++ to Rust. There is a 100-sloc C++ code for ray tracing a set of spheres by Kevin Beason, called &lt;a href=&quot;https://www.kevinbeason.com/smallpt/&quot;&gt;SmallPT&lt;/a&gt; (it is quite famous in some circles). While the original is focused on getting as much as possible into a hundred lines of code, I wanted a bit more understanding. A ray tracer computes an image by doing a physical simulation of millions of photons in a given scene.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3wtAt6IzGk2lxdeQw1lf9g-58674538.BxQysIvS_b8dGq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A ray-traced rendering of a few spheres.&lt;/p&gt;
&lt;p&gt;The full demo can be found here: &lt;a href=&quot;https://jhidding.github.io/literatept/&quot;&gt;jhidding.github.io/literatept&lt;/a&gt;. I made some algorithmic changes to the original that are well documented. See for instance the &lt;a href=&quot;https://jhidding.github.io/literatept/#path-tracing&quot;&gt;section on path tracing&lt;/a&gt;. In another instance, I tried to understand the underlying physics of &lt;a href=&quot;https://jhidding.github.io/literatept/#partial-reflection&quot;&gt;reflecting rays in the transparent sphere&lt;/a&gt;. There I was able to underpin the code with equations and references.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does this sound interesting to you? Then you may like to get Entangled at &lt;a href=&quot;https://entangled.github.io/&quot;&gt;https://entangled.github.io/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also read my other blog posts about &lt;a href=&quot;https://blog.esciencecenter.nl/literate-programming-in-science-1669094541a7&quot;&gt;Literate Programming in Science&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_jxEcYwxE1UA_d2o1PbRylw-18969b0e.GRocYSM9.png" medium="image"/><author>Johan Hidding</author></item><item><title>10 examples of embedding Julia in C/C++</title><link>https://blog2.esciencecenter.nl/posts/2022-11-03---10-examples-of-embedding-julia-in-cc</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-11-03---10-examples-of-embedding-julia-in-cc</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;trapezoid&lt;/code&gt; function has 4 arguments, therefore we have to use the general &lt;code&gt;jl_call&lt;/code&gt; that we mentioned before. The arguments of &lt;code&gt;jl_call&lt;/code&gt; are the function, an array of &lt;code&gt;jl_value_t *&lt;/code&gt; arguments, and the number of arguments.&lt;/p&gt;
&lt;h3 id=&quot;4-c-function-from-julia-from-c&quot;&gt;4: C function from Julia from C&lt;/h3&gt;
&lt;p&gt;How about computing the integral of a C function? We will need to access it through Julia to be able to pass it to a Julia function. First, we must create the function in C. Create a file &lt;code&gt;my_c_func.cpp&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;p&gt;It is important that we use &lt;code&gt;extern &quot;C&quot;&lt;/code&gt; here, otherwise, C++ will &lt;a href=&quot;https://en.wikipedia.org/wiki/Name_mangling&quot;&gt;mangle the function name&lt;/a&gt;. If you use C instead of C++, then this will not be an issue, but we intend to use C++ down the road. We will compile this code to a shared library, not only a &lt;code&gt;.o&lt;/code&gt; object. Therefore, add the following to your Makefile:&lt;/p&gt;
&lt;p&gt;lib%.so: %.o
ld -shared &lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;&amp;#x26;&amp;#x27; at position 1: &amp;#x26;̲lt; -o &quot; style=&quot;color:#cc0000&quot;&gt;&amp;#x26;lt; -o &lt;/span&gt;@&lt;code&gt;ld&lt;/code&gt; is the linker and &lt;code&gt;-shared&lt;/code&gt; is because we want a shared library. Furthermore, you should modify the following:&lt;/p&gt;
&lt;p&gt;main.exe: main.cpp aux.o libmy_c_func.soNow, when you run &lt;code&gt;make main.exe&lt;/code&gt;, the &lt;code&gt;libmy_c_func.so&lt;/code&gt; library will be compiled.&lt;/p&gt;
&lt;p&gt;Finally, to call this function, we use the same string evaluator and Julia’s &lt;code&gt;ccall&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Snippt of integration2.cpp&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ccall&lt;/code&gt; function has 4+ arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(:my_c_func, &quot;libmy_c_func.so&quot;)&lt;/code&gt;: A tuple with the function name and the library;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Cdouble&lt;/code&gt;: Return type;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(Cdouble,)&lt;/code&gt;: Tuple with the types of the arguments;&lt;/li&gt;
&lt;li&gt;Then, all the arguments. In this case, only &lt;code&gt;x&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is it. This change is enough to make the code run. Notice that the function is &lt;code&gt;x^3&lt;/code&gt;, so the integral result should be &lt;code&gt;1 / 4&lt;/code&gt;. Those are the only differences in the code.&lt;/p&gt;
&lt;h3 id=&quot;5-using-a-package&quot;&gt;5: Using a package&lt;/h3&gt;
&lt;p&gt;Instead of implementing our own integration method, we can use some existing one. One option is &lt;a href=&quot;https://github.com/JuliaMath/QuadGK.jl&quot;&gt;QuadGK.jl&lt;/a&gt;. To install it, open &lt;code&gt;julia&lt;/code&gt;, press &lt;code&gt;]&lt;/code&gt;, and enter &lt;code&gt;add QuadGK&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An important note here is that I have not investigated much into maintaining a separate environment for these packages. If you know more about this subject, don’t hesitate to leave a comment.&lt;/p&gt;
&lt;p&gt;Here is the code:&lt;/p&gt;
&lt;p&gt;handle_eval_string(“using QuadGK”);
jl_value_t *integrator = handle_eval_string(
“(f, a, b, n) -&gt; quadgk(f, a, b, maxevals=n)[1]”
);Just like that we can compute the integral, and compare it with our implementation. Let’s use a harder integral to make things more interesting:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;643&quot; height=&quot;208&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-d7ee2d4d.UWpubD76_Z1orFC.webp&quot; srcset=&quot;&quot;&gt;
The integral of 1 over 1 plus x squared from 0 to 1 is Pi over 4. LaTeX: \int_0^1 \frac{1}{1 + x^2} \text{d}x = \frac{\pi}{4}.Here is the complete code for this example:&lt;/p&gt;
&lt;p&gt;File integration3.cpp&lt;/p&gt;
&lt;p&gt;The results you should see are&lt;/p&gt;
&lt;p&gt;Integral of 1 / (1 + x^2) is approx: 0.785394
Error: 4.16667e-06
Integral of 1 / (1 + x^2) is approx: 0.785398
Error: -1.11022e-16&lt;/p&gt;
&lt;h3 id=&quot;6-using-the-distributions-package&quot;&gt;6: Using the Distributions package&lt;/h3&gt;
&lt;p&gt;The package Distributions contains various probability-related tools. We are going to use the Normal distributions’ PDF (Probability Density Function) and CDF (Cumulative Density Function) in this example. Don’t worry if you don’t know what these mean, we won’t need to understand the concept, only the formulas.&lt;/p&gt;
&lt;p&gt;The Normal distribution with mean Mu (µ) and standard deviation Sigma (σ) has PDF given by&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;154&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-6e86df9d.9we1ejHE_2qTC67.webp&quot; srcset=&quot;&quot;&gt;
Normal probability density function. LaTeX: f(x) = \frac*{1}{\sigma*\sqrt*{2\pi}} e^{-&lt;em&gt;\frac&lt;/em&gt;{1}{2}\left(&lt;em&gt;\frac&lt;/em&gt;{x - \mu}{\sigma}\right)^2}And the CDF of a PDF is&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;685&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-894567de.BvMXzrk7_Z1apjnz.webp&quot; srcset=&quot;&quot;&gt;
Cumulative density function definition. LaTeX: F(x) = \int_{-\infty}^x f(t) \text{d}tWhat we will do is use the Distributions package to access the PDF and compute the CDF integral using QuadGK. We will then compare it to the existing CDF function in Distributions.&lt;/p&gt;
&lt;p&gt;Once more there is not much secret. You only have to create the Normal structure on the Julia side and use Julia closures to define PDF and CDF &lt;code&gt;jl_function_t&lt;/code&gt; with one argument. This is the code:&lt;/p&gt;
&lt;p&gt;handle_eval_string(“normal = Normal()”);
jl_function_t *pdf = handle_eval_string(“x -&gt; pdf(normal, x)”);
jl_function_t *cdf = handle_eval_string(“x -&gt; cdf(normal, x)”);The full code is below&lt;/p&gt;
&lt;p&gt;File integration4.cpp&lt;/p&gt;
&lt;h3 id=&quot;7-creating-a-class-to-wrap-the-distributions-package&quot;&gt;7: Creating a class to wrap the Distributions package&lt;/h3&gt;
&lt;p&gt;To complicate it a little bit more, let’s create a class wrapping the Distributions package. The basic idea will be a constructor to call &lt;code&gt;Normal&lt;/code&gt; , and C++ functions wrapping &lt;code&gt;pdf&lt;/code&gt; and &lt;code&gt;cdf&lt;/code&gt;. This can be done simply by having a call to &lt;code&gt;handle_eval_string&lt;/code&gt; or by creating the function with &lt;code&gt;jl_get_function&lt;/code&gt; and calling &lt;code&gt;jl_call_X&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, to make it more efficient, we want to avoid frequent calls to the functions that deal with strings. One solution is to store the functions returned by &lt;code&gt;jl_get_function&lt;/code&gt; and just use them when necessary. To do that, we will use &lt;code&gt;static&lt;/code&gt; members in C++.&lt;/p&gt;
&lt;p&gt;The two files below show the implementation of our class:&lt;/p&gt;
&lt;p&gt;File Normal.hFile Normal.cpp&lt;/p&gt;
&lt;p&gt;As you can see, we keep a &lt;code&gt;distributions_loaded&lt;/code&gt; flag to let the constructor know that the static variables can be used. In the initialization function, we define the necessary functions. The actual implementation of the constructor and the PDF and CDF functions is straightforward.&lt;/p&gt;
&lt;p&gt;We can use this new class in our main file easily:&lt;/p&gt;
&lt;p&gt;File integration5.cpp&lt;/p&gt;
&lt;p&gt;Don’t forget to update your Makefile by replacing &lt;code&gt;aux.o&lt;/code&gt; by &lt;code&gt;aux.o Normal.o&lt;/code&gt;, i.e., add &lt;code&gt;Normal.o&lt;/code&gt; next to&lt;code&gt;aux.o&lt;/code&gt;. The result of this execution is&lt;/p&gt;
&lt;p&gt;x: -4.00e+00  pdf: +4.97e-08  cdf: +1.12e-08
x: -3.00e+00  pdf: +2.73e-06  cdf: +7.07e-07
x: -2.00e+00  pdf: +8.29e-05  cdf: +2.52e-05
x: -1.00e+00  pdf: +1.39e-03  cdf: +5.11e-04
x: +0.00e+00  pdf: +1.30e-02  cdf: +5.95e-03
x: +1.00e+00  pdf: +6.68e-02  cdf: +4.04e-02
x: +2.00e+00  pdf: +1.90e-01  cdf: +1.64e-01
x: +3.00e+00  pdf: +3.00e-01  cdf: +4.18e-01
x: +4.00e+00  pdf: +2.62e-01  cdf: +7.13e-01&lt;/p&gt;
&lt;h3 id=&quot;8-linear-algebra-arrays-vectors-and-matrices&quot;&gt;8: Linear algebra: Arrays, Vectors, and Matrices&lt;/h3&gt;
&lt;p&gt;Let’s start our linear algebra exploration with a matrix-vector multiplication and solving a linear system. We will define the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;268&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-cb02c815.BWSaNJ4Q_Z379kr.webp&quot; srcset=&quot;&quot;&gt;
x is a vector of ones and A is a matrix with n in the diagonal, 1 below the diagonal and -1 above the diagonal. LaTeX: x = \begin{bmatrix} 1 \ 1 \ 1 \ \vdots \ 1 \end{bmatrix}, A = \begin{bmatrix} n &amp;#x26; -1 &amp;#x26; -1 &amp;#x26; \cdots &amp;#x26; -1 \ 1 &amp;#x26; n &amp;#x26; -1 &amp;#x26; \cdots &amp;#x26; -1 \ 1 &amp;#x26; 1 &amp;#x26; n &amp;#x26; \cdots &amp;#x26; -1 \ \vdots &amp;#x26; \vdots &amp;#x26; \vdots &amp;#x26; \ddots &amp;#x26; \vdots \ 1 &amp;#x26; 1 &amp;#x26; 1 &amp;#x26; \cdots &amp;#x26; n \end{bmatrix}Let’s start with some code:&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;The first two statements define the vectors and matrices types. Notice that we make explicit that the first has 1 dimension and the second has 2 dimensions.&lt;/p&gt;
&lt;p&gt;The next 3 statements allocate the memory for the two vectors &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, and the matrix &lt;code&gt;A&lt;/code&gt;, using the array types we previously defined.&lt;/p&gt;
&lt;p&gt;Finally, we have a &lt;code&gt;JL_GC_PUSH3&lt;/code&gt;, which informs Julia’s Garbage Collector to not touch this memory. Naturally, we will have to pop these eventually.&lt;/p&gt;
&lt;p&gt;Lastly, we declare C arrays pointing to the Julia data. You will notice that &lt;code&gt;AData&lt;/code&gt; is a 1-dimensional array because Julia implements dense matrices as a linearized array by columns. That means that the element&lt;code&gt;(i,j)&lt;/code&gt; will be at the linearized position &lt;code&gt;i + j * nrows&lt;/code&gt; — using 0-based indexing.&lt;/p&gt;
&lt;p&gt;To fill the values of the vector &lt;code&gt;x&lt;/code&gt; and the matrix &lt;code&gt;A&lt;/code&gt; , we can use the code below:&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;The product of &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; is pretty much the same as any function we had so far.&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;The noteworthy part of this code is that we have to cast the arrays for &lt;code&gt;jl_value_t *&lt;/code&gt; to use them as arguments to &lt;code&gt;jl_call2&lt;/code&gt; , and the output is cast to &lt;code&gt;jl_array_t *&lt;/code&gt;. Similarly, we can use &lt;code&gt;jl_array_data(Ax)&lt;/code&gt; to access the content of the product.&lt;/p&gt;
&lt;p&gt;We can also use &lt;code&gt;mul!&lt;/code&gt; to compute the product in place, i.e., without allocating more memory:&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;Notice that we use &lt;code&gt;jl_main_module&lt;/code&gt; because &lt;code&gt;mul!&lt;/code&gt; is part of &lt;code&gt;LinearAlgebra&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Finally, we move on to solving the linear system. To do that, let’s use the &lt;a href=&quot;https://en.wikipedia.org/wiki/LU_decomposition&quot;&gt;LU factorization&lt;/a&gt; and the &lt;code&gt;ldiv!&lt;/code&gt; function. The &lt;code&gt;\&lt;/code&gt; &lt;a href=&quot;https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#Base.:%5C-Tuple%7BAbstractMatrix,%20AbstractVecOrMat%7D&quot;&gt;(backslash) operator&lt;/a&gt; is usually used here, but we choose &lt;code&gt;ldiv!&lt;/code&gt; to solve the linear system in place.&lt;/p&gt;
&lt;p&gt;jl_function_t *lu_fact = jl_get_function(jl_main_module, “lu”);
jl_value_t *LU = jl_call1(lu_fact, (jl_value_t *) A);
jl_function_t *ldiv = jl_get_function(jl_main_module, “ldiv!”);
jl_call3(ldiv, (jl_value_t *) y, LU, (jl_value_t *) Ax);The last call defines &lt;code&gt;y&lt;/code&gt; as the solution of the linear system &lt;code&gt;Ay = (Ax)&lt;/code&gt; . Since &lt;code&gt;A&lt;/code&gt; is non-singular, we expect &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; to be sufficiently close (numerical errors could appear here). We can verify this using&lt;/p&gt;
&lt;p&gt;double *yData = (double *) jl_array_data(y);
double norm2 = 0.0;
for (size_t i = 0; i &amp;#x3C; n; i++) {
double dif = yData[i] - xData[i];
norm2 += dif * dif;
}
cout &amp;#x3C;&amp;#x3C; “|x - y|² = ” &amp;#x3C;&amp;#x3C; norm2 &amp;#x3C;&amp;#x3C; endl;My result was &lt;code&gt;6.48394e-26&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;To finalize this code, we have to run&lt;/p&gt;
&lt;p&gt;JL_GC_POP();This allows the Julia Garbage Collector to collect the allocated memory. The complete code can be seen below:&lt;/p&gt;
&lt;p&gt;File linear-algebra1.cpp&lt;/p&gt;
&lt;h3 id=&quot;9-sparse-matrices&quot;&gt;9: Sparse matrices&lt;/h3&gt;
&lt;p&gt;For our next example, we will solve a heat-equation on 1 spatial dimension, using a discretization of time and space called Backward Time Centered Space (BTCS), which is not quick to explain. Check &lt;a href=&quot;https://john-s-butler-dit.github.io/NumericalAnalysisBook/Chapter%2008%20-%20Heat%20Equations/802_Heat%20Equation-%20BTCS.html#the-implicit-backward-time-centered-space-btcs-difference-equation&quot;&gt;these notes&lt;/a&gt; for a thorough explanation.&lt;/p&gt;
&lt;p&gt;For our interests, it suffices to say that we will be solving a sparse linear system multiple times, where the matrix is the one below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;235&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-8f6c1ad9.CieIRkpE_Zr8vIS.webp&quot; srcset=&quot;&quot;&gt;
Tridiagonal matrix, where the diagonal stores 1 plus 2 times kappa, and the off-diagonal values are -kappa. LaTeX: A = \begin{bmatrix} 1 + 2\kappa &amp;#x26; -\kappa \ -\kappa &amp;#x26; 1 + 2\kappa &amp;#x26; \kappa \ &amp;#x26; \ddots &amp;#x26; \ddots &amp;#x26; \ddots \ &amp;#x26; &amp;#x26; -\kappa &amp;#x26; 1 + 2\kappa &amp;#x26; -\kappa \ &amp;#x26; &amp;#x26; &amp;#x26; -\kappa &amp;#x26; 1 + 2\kappa \end{bmatrix}We don’t have to store this matrix as a dense matrix (like in the previous example). Instead, we want to store only the relevant elements. To do that, we will create three vectors for the rows and columns indexes, and for the values corresponding to these indexes.&lt;/p&gt;
&lt;p&gt;The code is below:&lt;/p&gt;
&lt;p&gt;long int rows[3 * n - 2], cols[3 * n - 2];
double vals[3 * n - 2];for (size_t i = 0; i &amp;#x3C; n; i++) {
rows[i] = i + 1;
cols[i] = i + 1;
vals[i] = (1 + 2 * kappa);
if (i &amp;#x3C; n - 1) {
rows[n + i] = i + 1;
cols[n + i] = i + 2;
vals[n + i] = -kappa;
rows[2 * n + i - 1] = i + 2;
cols[2 * n + i - 1] = i + 1;
vals[2 * n + i - 1] = -kappa;
}
}Now, we will create a sparse matrix using the &lt;code&gt;sparse&lt;/code&gt; function from the &lt;code&gt;SparseArrays&lt;/code&gt; module in Julia. For that, we allocate two array types, one for the integers, and one for the floating point numbers.&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra3.cpp&lt;/p&gt;
&lt;p&gt;On the &lt;code&gt;jl_call3&lt;/code&gt; , we also call &lt;code&gt;jl_ptr_to_array_1d&lt;/code&gt; to directly create and return a Julia vector wrapping the data we give it.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;A_sparse&lt;/code&gt;matrix is a Julia sparse matrix. Many of the matrix operations that work with dense matrices will work with sparse matrices. To test a different factorization, let’s use the function &lt;code&gt;ldl&lt;/code&gt; from the &lt;code&gt;LDLFactorizations&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra3.cpp&lt;/p&gt;
&lt;p&gt;Now, we can use &lt;code&gt;ldiv!&lt;/code&gt; with &lt;code&gt;ldlObj&lt;/code&gt; instead of the LU factorization that we used in the previous example. There is one catch, though. Since we are using the &lt;code&gt;ldlObj&lt;/code&gt; “for a while”, we need to prevent the Garbage collector to clean it. But the &lt;code&gt;JL_GC_PUSHX&lt;/code&gt; function can only be called once per scope. Therefore, to use it we have to create an internal scope. So something like the following:&lt;/p&gt;
&lt;p&gt;Scope your second JL_GC_PUSH&lt;/p&gt;
&lt;p&gt;The complete code is below:&lt;/p&gt;
&lt;p&gt;File linear-algebra3.cpp&lt;/p&gt;
&lt;p&gt;In the algorithm, we define &lt;code&gt;u&lt;/code&gt; as the initial vector, then solve the linear system right &lt;code&gt;u&lt;/code&gt; as the right-hand side to obtain &lt;code&gt;unew&lt;/code&gt;. Then we assign &lt;code&gt;unew&lt;/code&gt; to &lt;code&gt;u&lt;/code&gt; and repeat. Each &lt;code&gt;u&lt;/code&gt; is an approximation to the solution of the heat equation for a specific moment in time.&lt;/p&gt;
&lt;p&gt;You will notice that, in addition to computing the solution, we also plot it using the &lt;code&gt;Plots&lt;/code&gt; package. We plot the initial solution at different times. This makes the code much slower, unfortunately. The result can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-a6a7c60e.xUf01K6i_Z26hVnm.webp&quot; srcset=&quot;&quot;&gt;
Plot of heat equation solution at different moments in time.&lt;/p&gt;
&lt;h3 id=&quot;finalizing-and-open-questions&quot;&gt;Finalizing and open questions&lt;/h3&gt;
&lt;p&gt;I hope these 10 examples are helpful to get you started with embedding Julia in C. There are many more things not covered here, in particular things I do not know. Some of them are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to deal with strings?&lt;/li&gt;
&lt;li&gt;How to deal with keyword arguments?&lt;/li&gt;
&lt;li&gt;How to deal with installing packages and environments?&lt;/li&gt;
&lt;li&gt;How to make it faster (e.g., using precompiled images)?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will be on the lookout for future projects to investigate these. In the meantime, like and follow for more Julia and C/C++ content.&lt;/p&gt;
&lt;h3 id=&quot;references-and-extra-material&quot;&gt;References and extra material&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.julialang.org/en/v1/manual/embedding/&quot;&gt;Embedding Julia in the Julia documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://forem.julialang.org/matthijscox/embedding-julia-libraries-in-c-1n12&quot;&gt;Embedding Julia libraries in C++ by Matthijs Cox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://discourse.julialang.org/t/calling-jl-gc-push1-multiple-times/18666&quot;&gt;https://discourse.julialang.org/t/calling-jl-gc-push1-multiple-times/18666&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 03 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;trapezoid&lt;/code&gt; function has 4 arguments, therefore we have to use the general &lt;code&gt;jl_call&lt;/code&gt; that we mentioned before. The arguments of &lt;code&gt;jl_call&lt;/code&gt; are the function, an array of &lt;code&gt;jl_value_t *&lt;/code&gt; arguments, and the number of arguments.&lt;/p&gt;
&lt;h3 id=&quot;4-c-function-from-julia-from-c&quot;&gt;4: C function from Julia from C&lt;/h3&gt;
&lt;p&gt;How about computing the integral of a C function? We will need to access it through Julia to be able to pass it to a Julia function. First, we must create the function in C. Create a file &lt;code&gt;my_c_func.cpp&lt;/code&gt; with the following contents:&lt;/p&gt;
&lt;p&gt;It is important that we use &lt;code&gt;extern &quot;C&quot;&lt;/code&gt; here, otherwise, C++ will &lt;a href=&quot;https://en.wikipedia.org/wiki/Name_mangling&quot;&gt;mangle the function name&lt;/a&gt;. If you use C instead of C++, then this will not be an issue, but we intend to use C++ down the road. We will compile this code to a shared library, not only a &lt;code&gt;.o&lt;/code&gt; object. Therefore, add the following to your Makefile:&lt;/p&gt;
&lt;p&gt;lib%.so: %.o
ld -shared &lt;span class=&quot;katex-error&quot; title=&quot;ParseError: KaTeX parse error: Expected &amp;#x27;EOF&amp;#x27;, got &amp;#x27;&amp;#x26;&amp;#x27; at position 1: &amp;#x26;̲lt; -o &quot; style=&quot;color:#cc0000&quot;&gt;&amp;#x26;lt; -o &lt;/span&gt;@&lt;code&gt;ld&lt;/code&gt; is the linker and &lt;code&gt;-shared&lt;/code&gt; is because we want a shared library. Furthermore, you should modify the following:&lt;/p&gt;
&lt;p&gt;main.exe: main.cpp aux.o libmy_c_func.soNow, when you run &lt;code&gt;make main.exe&lt;/code&gt;, the &lt;code&gt;libmy_c_func.so&lt;/code&gt; library will be compiled.&lt;/p&gt;
&lt;p&gt;Finally, to call this function, we use the same string evaluator and Julia’s &lt;code&gt;ccall&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Snippt of integration2.cpp&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ccall&lt;/code&gt; function has 4+ arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(:my_c_func, &quot;libmy_c_func.so&quot;)&lt;/code&gt;: A tuple with the function name and the library;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Cdouble&lt;/code&gt;: Return type;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(Cdouble,)&lt;/code&gt;: Tuple with the types of the arguments;&lt;/li&gt;
&lt;li&gt;Then, all the arguments. In this case, only &lt;code&gt;x&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is it. This change is enough to make the code run. Notice that the function is &lt;code&gt;x^3&lt;/code&gt;, so the integral result should be &lt;code&gt;1 / 4&lt;/code&gt;. Those are the only differences in the code.&lt;/p&gt;
&lt;h3 id=&quot;5-using-a-package&quot;&gt;5: Using a package&lt;/h3&gt;
&lt;p&gt;Instead of implementing our own integration method, we can use some existing one. One option is &lt;a href=&quot;https://github.com/JuliaMath/QuadGK.jl&quot;&gt;QuadGK.jl&lt;/a&gt;. To install it, open &lt;code&gt;julia&lt;/code&gt;, press &lt;code&gt;]&lt;/code&gt;, and enter &lt;code&gt;add QuadGK&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An important note here is that I have not investigated much into maintaining a separate environment for these packages. If you know more about this subject, don’t hesitate to leave a comment.&lt;/p&gt;
&lt;p&gt;Here is the code:&lt;/p&gt;
&lt;p&gt;handle_eval_string(“using QuadGK”);
jl_value_t *integrator = handle_eval_string(
“(f, a, b, n) -&gt; quadgk(f, a, b, maxevals=n)[1]”
);Just like that we can compute the integral, and compare it with our implementation. Let’s use a harder integral to make things more interesting:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;643&quot; height=&quot;208&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-d7ee2d4d.UWpubD76_Z1orFC.webp&quot; srcset=&quot;&quot;&gt;
The integral of 1 over 1 plus x squared from 0 to 1 is Pi over 4. LaTeX: \int_0^1 \frac{1}{1 + x^2} \text{d}x = \frac{\pi}{4}.Here is the complete code for this example:&lt;/p&gt;
&lt;p&gt;File integration3.cpp&lt;/p&gt;
&lt;p&gt;The results you should see are&lt;/p&gt;
&lt;p&gt;Integral of 1 / (1 + x^2) is approx: 0.785394
Error: 4.16667e-06
Integral of 1 / (1 + x^2) is approx: 0.785398
Error: -1.11022e-16&lt;/p&gt;
&lt;h3 id=&quot;6-using-the-distributions-package&quot;&gt;6: Using the Distributions package&lt;/h3&gt;
&lt;p&gt;The package Distributions contains various probability-related tools. We are going to use the Normal distributions’ PDF (Probability Density Function) and CDF (Cumulative Density Function) in this example. Don’t worry if you don’t know what these mean, we won’t need to understand the concept, only the formulas.&lt;/p&gt;
&lt;p&gt;The Normal distribution with mean Mu (µ) and standard deviation Sigma (σ) has PDF given by&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;154&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-6e86df9d.9we1ejHE_2qTC67.webp&quot; srcset=&quot;&quot;&gt;
Normal probability density function. LaTeX: f(x) = \frac*{1}{\sigma*\sqrt*{2\pi}} e^{-&lt;em&gt;\frac&lt;/em&gt;{1}{2}\left(&lt;em&gt;\frac&lt;/em&gt;{x - \mu}{\sigma}\right)^2}And the CDF of a PDF is&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;685&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-894567de.BvMXzrk7_Z1apjnz.webp&quot; srcset=&quot;&quot;&gt;
Cumulative density function definition. LaTeX: F(x) = \int_{-\infty}^x f(t) \text{d}tWhat we will do is use the Distributions package to access the PDF and compute the CDF integral using QuadGK. We will then compare it to the existing CDF function in Distributions.&lt;/p&gt;
&lt;p&gt;Once more there is not much secret. You only have to create the Normal structure on the Julia side and use Julia closures to define PDF and CDF &lt;code&gt;jl_function_t&lt;/code&gt; with one argument. This is the code:&lt;/p&gt;
&lt;p&gt;handle_eval_string(“normal = Normal()”);
jl_function_t *pdf = handle_eval_string(“x -&gt; pdf(normal, x)”);
jl_function_t *cdf = handle_eval_string(“x -&gt; cdf(normal, x)”);The full code is below&lt;/p&gt;
&lt;p&gt;File integration4.cpp&lt;/p&gt;
&lt;h3 id=&quot;7-creating-a-class-to-wrap-the-distributions-package&quot;&gt;7: Creating a class to wrap the Distributions package&lt;/h3&gt;
&lt;p&gt;To complicate it a little bit more, let’s create a class wrapping the Distributions package. The basic idea will be a constructor to call &lt;code&gt;Normal&lt;/code&gt; , and C++ functions wrapping &lt;code&gt;pdf&lt;/code&gt; and &lt;code&gt;cdf&lt;/code&gt;. This can be done simply by having a call to &lt;code&gt;handle_eval_string&lt;/code&gt; or by creating the function with &lt;code&gt;jl_get_function&lt;/code&gt; and calling &lt;code&gt;jl_call_X&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, to make it more efficient, we want to avoid frequent calls to the functions that deal with strings. One solution is to store the functions returned by &lt;code&gt;jl_get_function&lt;/code&gt; and just use them when necessary. To do that, we will use &lt;code&gt;static&lt;/code&gt; members in C++.&lt;/p&gt;
&lt;p&gt;The two files below show the implementation of our class:&lt;/p&gt;
&lt;p&gt;File Normal.hFile Normal.cpp&lt;/p&gt;
&lt;p&gt;As you can see, we keep a &lt;code&gt;distributions_loaded&lt;/code&gt; flag to let the constructor know that the static variables can be used. In the initialization function, we define the necessary functions. The actual implementation of the constructor and the PDF and CDF functions is straightforward.&lt;/p&gt;
&lt;p&gt;We can use this new class in our main file easily:&lt;/p&gt;
&lt;p&gt;File integration5.cpp&lt;/p&gt;
&lt;p&gt;Don’t forget to update your Makefile by replacing &lt;code&gt;aux.o&lt;/code&gt; by &lt;code&gt;aux.o Normal.o&lt;/code&gt;, i.e., add &lt;code&gt;Normal.o&lt;/code&gt; next to&lt;code&gt;aux.o&lt;/code&gt;. The result of this execution is&lt;/p&gt;
&lt;p&gt;x: -4.00e+00  pdf: +4.97e-08  cdf: +1.12e-08
x: -3.00e+00  pdf: +2.73e-06  cdf: +7.07e-07
x: -2.00e+00  pdf: +8.29e-05  cdf: +2.52e-05
x: -1.00e+00  pdf: +1.39e-03  cdf: +5.11e-04
x: +0.00e+00  pdf: +1.30e-02  cdf: +5.95e-03
x: +1.00e+00  pdf: +6.68e-02  cdf: +4.04e-02
x: +2.00e+00  pdf: +1.90e-01  cdf: +1.64e-01
x: +3.00e+00  pdf: +3.00e-01  cdf: +4.18e-01
x: +4.00e+00  pdf: +2.62e-01  cdf: +7.13e-01&lt;/p&gt;
&lt;h3 id=&quot;8-linear-algebra-arrays-vectors-and-matrices&quot;&gt;8: Linear algebra: Arrays, Vectors, and Matrices&lt;/h3&gt;
&lt;p&gt;Let’s start our linear algebra exploration with a matrix-vector multiplication and solving a linear system. We will define the following:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;268&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-cb02c815.BWSaNJ4Q_Z379kr.webp&quot; srcset=&quot;&quot;&gt;
x is a vector of ones and A is a matrix with n in the diagonal, 1 below the diagonal and -1 above the diagonal. LaTeX: x = \begin{bmatrix} 1 \ 1 \ 1 \ \vdots \ 1 \end{bmatrix}, A = \begin{bmatrix} n &amp;#x26; -1 &amp;#x26; -1 &amp;#x26; \cdots &amp;#x26; -1 \ 1 &amp;#x26; n &amp;#x26; -1 &amp;#x26; \cdots &amp;#x26; -1 \ 1 &amp;#x26; 1 &amp;#x26; n &amp;#x26; \cdots &amp;#x26; -1 \ \vdots &amp;#x26; \vdots &amp;#x26; \vdots &amp;#x26; \ddots &amp;#x26; \vdots \ 1 &amp;#x26; 1 &amp;#x26; 1 &amp;#x26; \cdots &amp;#x26; n \end{bmatrix}Let’s start with some code:&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;The first two statements define the vectors and matrices types. Notice that we make explicit that the first has 1 dimension and the second has 2 dimensions.&lt;/p&gt;
&lt;p&gt;The next 3 statements allocate the memory for the two vectors &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, and the matrix &lt;code&gt;A&lt;/code&gt;, using the array types we previously defined.&lt;/p&gt;
&lt;p&gt;Finally, we have a &lt;code&gt;JL_GC_PUSH3&lt;/code&gt;, which informs Julia’s Garbage Collector to not touch this memory. Naturally, we will have to pop these eventually.&lt;/p&gt;
&lt;p&gt;Lastly, we declare C arrays pointing to the Julia data. You will notice that &lt;code&gt;AData&lt;/code&gt; is a 1-dimensional array because Julia implements dense matrices as a linearized array by columns. That means that the element&lt;code&gt;(i,j)&lt;/code&gt; will be at the linearized position &lt;code&gt;i + j * nrows&lt;/code&gt; — using 0-based indexing.&lt;/p&gt;
&lt;p&gt;To fill the values of the vector &lt;code&gt;x&lt;/code&gt; and the matrix &lt;code&gt;A&lt;/code&gt; , we can use the code below:&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;The product of &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; is pretty much the same as any function we had so far.&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;The noteworthy part of this code is that we have to cast the arrays for &lt;code&gt;jl_value_t *&lt;/code&gt; to use them as arguments to &lt;code&gt;jl_call2&lt;/code&gt; , and the output is cast to &lt;code&gt;jl_array_t *&lt;/code&gt;. Similarly, we can use &lt;code&gt;jl_array_data(Ax)&lt;/code&gt; to access the content of the product.&lt;/p&gt;
&lt;p&gt;We can also use &lt;code&gt;mul!&lt;/code&gt; to compute the product in place, i.e., without allocating more memory:&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra1.cpp&lt;/p&gt;
&lt;p&gt;Notice that we use &lt;code&gt;jl_main_module&lt;/code&gt; because &lt;code&gt;mul!&lt;/code&gt; is part of &lt;code&gt;LinearAlgebra&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Finally, we move on to solving the linear system. To do that, let’s use the &lt;a href=&quot;https://en.wikipedia.org/wiki/LU_decomposition&quot;&gt;LU factorization&lt;/a&gt; and the &lt;code&gt;ldiv!&lt;/code&gt; function. The &lt;code&gt;\&lt;/code&gt; &lt;a href=&quot;https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#Base.:%5C-Tuple%7BAbstractMatrix,%20AbstractVecOrMat%7D&quot;&gt;(backslash) operator&lt;/a&gt; is usually used here, but we choose &lt;code&gt;ldiv!&lt;/code&gt; to solve the linear system in place.&lt;/p&gt;
&lt;p&gt;jl_function_t *lu_fact = jl_get_function(jl_main_module, “lu”);
jl_value_t *LU = jl_call1(lu_fact, (jl_value_t *) A);
jl_function_t *ldiv = jl_get_function(jl_main_module, “ldiv!”);
jl_call3(ldiv, (jl_value_t *) y, LU, (jl_value_t *) Ax);The last call defines &lt;code&gt;y&lt;/code&gt; as the solution of the linear system &lt;code&gt;Ay = (Ax)&lt;/code&gt; . Since &lt;code&gt;A&lt;/code&gt; is non-singular, we expect &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; to be sufficiently close (numerical errors could appear here). We can verify this using&lt;/p&gt;
&lt;p&gt;double *yData = (double *) jl_array_data(y);
double norm2 = 0.0;
for (size_t i = 0; i &amp;#x3C; n; i++) {
double dif = yData[i] - xData[i];
norm2 += dif * dif;
}
cout &amp;#x3C;&amp;#x3C; “|x - y|² = ” &amp;#x3C;&amp;#x3C; norm2 &amp;#x3C;&amp;#x3C; endl;My result was &lt;code&gt;6.48394e-26&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;To finalize this code, we have to run&lt;/p&gt;
&lt;p&gt;JL_GC_POP();This allows the Julia Garbage Collector to collect the allocated memory. The complete code can be seen below:&lt;/p&gt;
&lt;p&gt;File linear-algebra1.cpp&lt;/p&gt;
&lt;h3 id=&quot;9-sparse-matrices&quot;&gt;9: Sparse matrices&lt;/h3&gt;
&lt;p&gt;For our next example, we will solve a heat-equation on 1 spatial dimension, using a discretization of time and space called Backward Time Centered Space (BTCS), which is not quick to explain. Check &lt;a href=&quot;https://john-s-butler-dit.github.io/NumericalAnalysisBook/Chapter%2008%20-%20Heat%20Equations/802_Heat%20Equation-%20BTCS.html#the-implicit-backward-time-centered-space-btcs-difference-equation&quot;&gt;these notes&lt;/a&gt; for a thorough explanation.&lt;/p&gt;
&lt;p&gt;For our interests, it suffices to say that we will be solving a sparse linear system multiple times, where the matrix is the one below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;235&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-8f6c1ad9.CieIRkpE_Zr8vIS.webp&quot; srcset=&quot;&quot;&gt;
Tridiagonal matrix, where the diagonal stores 1 plus 2 times kappa, and the off-diagonal values are -kappa. LaTeX: A = \begin{bmatrix} 1 + 2\kappa &amp;#x26; -\kappa \ -\kappa &amp;#x26; 1 + 2\kappa &amp;#x26; \kappa \ &amp;#x26; \ddots &amp;#x26; \ddots &amp;#x26; \ddots \ &amp;#x26; &amp;#x26; -\kappa &amp;#x26; 1 + 2\kappa &amp;#x26; -\kappa \ &amp;#x26; &amp;#x26; &amp;#x26; -\kappa &amp;#x26; 1 + 2\kappa \end{bmatrix}We don’t have to store this matrix as a dense matrix (like in the previous example). Instead, we want to store only the relevant elements. To do that, we will create three vectors for the rows and columns indexes, and for the values corresponding to these indexes.&lt;/p&gt;
&lt;p&gt;The code is below:&lt;/p&gt;
&lt;p&gt;long int rows[3 * n - 2], cols[3 * n - 2];
double vals[3 * n - 2];for (size_t i = 0; i &amp;#x3C; n; i++) {
rows[i] = i + 1;
cols[i] = i + 1;
vals[i] = (1 + 2 * kappa);
if (i &amp;#x3C; n - 1) {
rows[n + i] = i + 1;
cols[n + i] = i + 2;
vals[n + i] = -kappa;
rows[2 * n + i - 1] = i + 2;
cols[2 * n + i - 1] = i + 1;
vals[2 * n + i - 1] = -kappa;
}
}Now, we will create a sparse matrix using the &lt;code&gt;sparse&lt;/code&gt; function from the &lt;code&gt;SparseArrays&lt;/code&gt; module in Julia. For that, we allocate two array types, one for the integers, and one for the floating point numbers.&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra3.cpp&lt;/p&gt;
&lt;p&gt;On the &lt;code&gt;jl_call3&lt;/code&gt; , we also call &lt;code&gt;jl_ptr_to_array_1d&lt;/code&gt; to directly create and return a Julia vector wrapping the data we give it.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;A_sparse&lt;/code&gt;matrix is a Julia sparse matrix. Many of the matrix operations that work with dense matrices will work with sparse matrices. To test a different factorization, let’s use the function &lt;code&gt;ldl&lt;/code&gt; from the &lt;code&gt;LDLFactorizations&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;Snippet from linear-algebra3.cpp&lt;/p&gt;
&lt;p&gt;Now, we can use &lt;code&gt;ldiv!&lt;/code&gt; with &lt;code&gt;ldlObj&lt;/code&gt; instead of the LU factorization that we used in the previous example. There is one catch, though. Since we are using the &lt;code&gt;ldlObj&lt;/code&gt; “for a while”, we need to prevent the Garbage collector to clean it. But the &lt;code&gt;JL_GC_PUSHX&lt;/code&gt; function can only be called once per scope. Therefore, to use it we have to create an internal scope. So something like the following:&lt;/p&gt;
&lt;p&gt;Scope your second JL_GC_PUSH&lt;/p&gt;
&lt;p&gt;The complete code is below:&lt;/p&gt;
&lt;p&gt;File linear-algebra3.cpp&lt;/p&gt;
&lt;p&gt;In the algorithm, we define &lt;code&gt;u&lt;/code&gt; as the initial vector, then solve the linear system right &lt;code&gt;u&lt;/code&gt; as the right-hand side to obtain &lt;code&gt;unew&lt;/code&gt;. Then we assign &lt;code&gt;unew&lt;/code&gt; to &lt;code&gt;u&lt;/code&gt; and repeat. Each &lt;code&gt;u&lt;/code&gt; is an approximation to the solution of the heat equation for a specific moment in time.&lt;/p&gt;
&lt;p&gt;You will notice that, in addition to computing the solution, we also plot it using the &lt;code&gt;Plots&lt;/code&gt; package. We plot the initial solution at different times. This makes the code much slower, unfortunately. The result can be seen below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;10 examples of embedding Julia in C/C++&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-a6a7c60e.xUf01K6i_Z26hVnm.webp&quot; srcset=&quot;&quot;&gt;
Plot of heat equation solution at different moments in time.&lt;/p&gt;
&lt;h3 id=&quot;finalizing-and-open-questions&quot;&gt;Finalizing and open questions&lt;/h3&gt;
&lt;p&gt;I hope these 10 examples are helpful to get you started with embedding Julia in C. There are many more things not covered here, in particular things I do not know. Some of them are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to deal with strings?&lt;/li&gt;
&lt;li&gt;How to deal with keyword arguments?&lt;/li&gt;
&lt;li&gt;How to deal with installing packages and environments?&lt;/li&gt;
&lt;li&gt;How to make it faster (e.g., using precompiled images)?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will be on the lookout for future projects to investigate these. In the meantime, like and follow for more Julia and C/C++ content.&lt;/p&gt;
&lt;h3 id=&quot;references-and-extra-material&quot;&gt;References and extra material&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.julialang.org/en/v1/manual/embedding/&quot;&gt;Embedding Julia in the Julia documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://forem.julialang.org/matthijscox/embedding-julia-libraries-in-c-1n12&quot;&gt;Embedding Julia libraries in C++ by Matthijs Cox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://discourse.julialang.org/t/calling-jl-gc-push1-multiple-times/18666&quot;&gt;https://discourse.julialang.org/t/calling-jl-gc-push1-multiple-times/18666&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/10-examples-of-embedding-julia-in-cc-d7ee2d4d.UWpubD76.png" medium="image"/><author>Abel Soares Siqueira</author></item><item><title>How to manage your software</title><link>https://blog2.esciencecenter.nl/posts/2022-10-27---how-to-manage-your-software</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-10-27---how-to-manage-your-software</guid><description>&lt;p&gt;Today the Netherlands eScience Center and &lt;a href=&quot;https://www.nwo.nl/en&quot;&gt;NWO&lt;/a&gt; released a &lt;a href=&quot;https://doi.org/10.5281/zenodo.7038280&quot;&gt;Practical Guide to Software Management Plans&lt;/a&gt; (SMPs). The &lt;a href=&quot;https://www.esciencecenter.nl/national-guidelines-for-software-management-plans/&quot;&gt;Software Management Plan Working Group&lt;/a&gt; developed the Guide with input from many members of the national and international research community. The result is a practical guide that can be used to effectively plan research software development, archiving, reuse and maintenance.&lt;/p&gt;
&lt;p&gt;To learn more about this guide, we interviewed three people closely involved with its development: &lt;a href=&quot;https://twitter.com/neocarlitos&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; (Chair of the SMP working group, Netherlands eScience Center), &lt;a href=&quot;https://twitter.com/gravana&quot;&gt;Maria Cruz&lt;/a&gt; (Coordinator SMP working group, NWO), and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-maaike-de-jong/&quot;&gt;Maaike de Jong&lt;/a&gt; (Coordinator SMP working group, Netherlands eScience Center).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;884&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rUSMM8nk_zee36V9BS3rXw-6914b60c.BSvvjQ_p_CLL60.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Carlos Martinez-Ortiz, Maria Cruz (on-screen) and Maaike de Jong. Photo by Veronica Pang.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Congratulations on this achievement! Why do we need guidelines on Software Management Plans?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; Research software has become an integral part of almost every research project. In the Dutch research support community, particularly within the Local Digital Competence Centers, awareness of the importance of research software as a key output of many projects is increasing.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; The growing importance of software as a research output in its own right highlights the need for &lt;a href=&quot;https://doi.org/10.5281/zenodo.4543569&quot;&gt;specific policies and guidelines&lt;/a&gt; that promote the development of open and sustainable research software. Researchers typically specify their plans for managing software in &lt;a href=&quot;https://www.nwo.nl/en/research-data-management&quot;&gt;data management plans&lt;/a&gt;, but these contain limited guidance on research software management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Could you give an impression of what’s included in the SMP guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; The guidelines describe what you should consider when you manage research software. Examples of requirements for research software are version control, licensing, software citability, and documentation. How you should manage software in a specific research project is dependent on the type of software, and on its functionality. A few scripts for preprocessing a specific dataset often do not require the same kind of management as a core open-source library for a specific research field, for example. The guidelines specify core requirements for all research software, and additional requirements that are only necessary in some situations. They also include resources that tell you how you can meet these requirements. Organizations can use these guidelines to create their own template for a Software Management Plan, and individuals can use it when they are wondering how they should manage their own software.&lt;/p&gt;
&lt;p&gt;(text continues below image)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;705&quot; height=&quot;1002&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CqgovVCijwRAw34K0GdC4g-1688834d.7OpGuuVY_1CnAib.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you start with the development of these guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; We started by organizing a &lt;a href=&quot;https://blog.esciencecenter.nl/transparency-in-research-and-football-765a726ab5c9&quot;&gt;Workshop on Software Management Plans&lt;/a&gt; in June 2021. This workshop, jointly organized by the Netherlands eScience Center and NWO, brought together research support staff and policymakers from 28 different Dutch research organizations to discuss software management in research projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; The feedback we received from the workshop participants was very clear: There was a need for guidelines on research software management and, in particular, guidance on what should be included in an SMP.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; To address this need, we set up the Working Group on Software Management Plans in November 2021 to establish national guidelines on research software management plans. This work was partly inspired by the &lt;a href=&quot;https://www.scienceeurope.org/our-resources/practical-guide-to-the-international-alignment-of-research-data-management/&quot;&gt;Science Europe Practical Guide to the International Alignment of Research Data Management&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;843&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_chmbmt_VH7GWuF9X-941f06db.D0IxDzeT_ZlqMMt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Participants of the SMP workshop in June 2021&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you ensure representation from a wide variety of stakeholders?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; The &lt;a href=&quot;https://www.esciencecenter.nl/national-guidelines-for-software-management-plans/&quot;&gt;SMP working group&lt;/a&gt; comprised five experts in research software, representing different research organizations in the Netherlands, and different roles within those organizations, including research support staff, policy makers and research software engineers (RSEs).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; We also set up a sounding board who gave feedback on the guidelines at different stages of their development. The sounding board included researchers and other software experts from Dutch and international organizations not represented in the Working Group.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What kind of questions did the SMP working group and sounding board look at?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; We started by researching existing SMPs and analyzing the needs and expectations from researchers. Why were SMPs considered necessary? What problems should they address? And how would they help improve research software and research? Answering these questions led to the first draft of the guidelines, which was shared with the sounding board in March 2022.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; A second draft of the guidelines was then shared with the sounding board. We collected their feedback byl the end of May 2022. Once this feedback was integrated, a new version was produced and opened up for open consultation to the wider community in June 2022.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Was there a lot of interest in the guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; We received feedback from 65 people from across the globe. This is not surprising. Research software knows no frontiers, and as such, research software management is a topic of global interest and importance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you integrate all the feedback you received from the community?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; The consultation rounds provided a huge amount of good and interesting suggestions. The WG worked tirelessly throughout the summer to integrate all the feedback from the open consultation and the workshop to create a final version of the SMP guidelines.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; Some of the suggestions were beyond the scope of this first attempt to create national guidelines for software management plans. An excellent example of that is making &lt;a href=&quot;https://danielskatzblog.wordpress.com/2016/04/13/data-and-software-management-plans-must-be-public-and-should-be-machine-readable/&quot;&gt;SMPs machine-readable&lt;/a&gt;, which would make them easier to share, and verify.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; A second workshop took place in June 2022 in parallel with the open consultation. This time we invited the community to bring software examples with which to test the guidelines. After the WG explained how the guidelines were meant to be used, the participants tried to apply the guidelines to their own software. This exercise proved to be very fruitful and generated additional feedback on the guidelines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It sounds like this was a long, thorough, and iterative process involving the community. What are the next steps for the SMP guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; We encourage the community to use these guidelines as a basis to set up their own SMP templates and research software management policies. The eScience Center aims to continue collaborating with research organizations on this topic, and to support the implementation of software management by e.g. developing training for researchers and support staff.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; We consider these guidelines to be a first step in a journey to improve research software management. One important issue that was raised several times during the consultation period was how to implement these guidelines alongside existing research data management policies and protocols. This is something that we still need to solve together with the community in the coming year.&lt;/p&gt;
&lt;p&gt;Interview conducted by &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 27 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today the Netherlands eScience Center and &lt;a href=&quot;https://www.nwo.nl/en&quot;&gt;NWO&lt;/a&gt; released a &lt;a href=&quot;https://doi.org/10.5281/zenodo.7038280&quot;&gt;Practical Guide to Software Management Plans&lt;/a&gt; (SMPs). The &lt;a href=&quot;https://www.esciencecenter.nl/national-guidelines-for-software-management-plans/&quot;&gt;Software Management Plan Working Group&lt;/a&gt; developed the Guide with input from many members of the national and international research community. The result is a practical guide that can be used to effectively plan research software development, archiving, reuse and maintenance.&lt;/p&gt;
&lt;p&gt;To learn more about this guide, we interviewed three people closely involved with its development: &lt;a href=&quot;https://twitter.com/neocarlitos&quot;&gt;Carlos Martinez-Ortiz&lt;/a&gt; (Chair of the SMP working group, Netherlands eScience Center), &lt;a href=&quot;https://twitter.com/gravana&quot;&gt;Maria Cruz&lt;/a&gt; (Coordinator SMP working group, NWO), and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-maaike-de-jong/&quot;&gt;Maaike de Jong&lt;/a&gt; (Coordinator SMP working group, Netherlands eScience Center).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;884&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rUSMM8nk_zee36V9BS3rXw-6914b60c.BSvvjQ_p_CLL60.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Carlos Martinez-Ortiz, Maria Cruz (on-screen) and Maaike de Jong. Photo by Veronica Pang.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Congratulations on this achievement! Why do we need guidelines on Software Management Plans?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; Research software has become an integral part of almost every research project. In the Dutch research support community, particularly within the Local Digital Competence Centers, awareness of the importance of research software as a key output of many projects is increasing.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; The growing importance of software as a research output in its own right highlights the need for &lt;a href=&quot;https://doi.org/10.5281/zenodo.4543569&quot;&gt;specific policies and guidelines&lt;/a&gt; that promote the development of open and sustainable research software. Researchers typically specify their plans for managing software in &lt;a href=&quot;https://www.nwo.nl/en/research-data-management&quot;&gt;data management plans&lt;/a&gt;, but these contain limited guidance on research software management.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Could you give an impression of what’s included in the SMP guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; The guidelines describe what you should consider when you manage research software. Examples of requirements for research software are version control, licensing, software citability, and documentation. How you should manage software in a specific research project is dependent on the type of software, and on its functionality. A few scripts for preprocessing a specific dataset often do not require the same kind of management as a core open-source library for a specific research field, for example. The guidelines specify core requirements for all research software, and additional requirements that are only necessary in some situations. They also include resources that tell you how you can meet these requirements. Organizations can use these guidelines to create their own template for a Software Management Plan, and individuals can use it when they are wondering how they should manage their own software.&lt;/p&gt;
&lt;p&gt;(text continues below image)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;705&quot; height=&quot;1002&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CqgovVCijwRAw34K0GdC4g-1688834d.7OpGuuVY_1CnAib.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you start with the development of these guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; We started by organizing a &lt;a href=&quot;https://blog.esciencecenter.nl/transparency-in-research-and-football-765a726ab5c9&quot;&gt;Workshop on Software Management Plans&lt;/a&gt; in June 2021. This workshop, jointly organized by the Netherlands eScience Center and NWO, brought together research support staff and policymakers from 28 different Dutch research organizations to discuss software management in research projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; The feedback we received from the workshop participants was very clear: There was a need for guidelines on research software management and, in particular, guidance on what should be included in an SMP.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; To address this need, we set up the Working Group on Software Management Plans in November 2021 to establish national guidelines on research software management plans. This work was partly inspired by the &lt;a href=&quot;https://www.scienceeurope.org/our-resources/practical-guide-to-the-international-alignment-of-research-data-management/&quot;&gt;Science Europe Practical Guide to the International Alignment of Research Data Management&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;843&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_chmbmt_VH7GWuF9X-941f06db.D0IxDzeT_ZlqMMt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Participants of the SMP workshop in June 2021&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you ensure representation from a wide variety of stakeholders?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; The &lt;a href=&quot;https://www.esciencecenter.nl/national-guidelines-for-software-management-plans/&quot;&gt;SMP working group&lt;/a&gt; comprised five experts in research software, representing different research organizations in the Netherlands, and different roles within those organizations, including research support staff, policy makers and research software engineers (RSEs).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; We also set up a sounding board who gave feedback on the guidelines at different stages of their development. The sounding board included researchers and other software experts from Dutch and international organizations not represented in the Working Group.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What kind of questions did the SMP working group and sounding board look at?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; We started by researching existing SMPs and analyzing the needs and expectations from researchers. Why were SMPs considered necessary? What problems should they address? And how would they help improve research software and research? Answering these questions led to the first draft of the guidelines, which was shared with the sounding board in March 2022.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; A second draft of the guidelines was then shared with the sounding board. We collected their feedback byl the end of May 2022. Once this feedback was integrated, a new version was produced and opened up for open consultation to the wider community in June 2022.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Was there a lot of interest in the guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; We received feedback from 65 people from across the globe. This is not surprising. Research software knows no frontiers, and as such, research software management is a topic of global interest and importance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you integrate all the feedback you received from the community?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; The consultation rounds provided a huge amount of good and interesting suggestions. The WG worked tirelessly throughout the summer to integrate all the feedback from the open consultation and the workshop to create a final version of the SMP guidelines.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; Some of the suggestions were beyond the scope of this first attempt to create national guidelines for software management plans. An excellent example of that is making &lt;a href=&quot;https://danielskatzblog.wordpress.com/2016/04/13/data-and-software-management-plans-must-be-public-and-should-be-machine-readable/&quot;&gt;SMPs machine-readable&lt;/a&gt;, which would make them easier to share, and verify.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Carlos:&lt;/em&gt; A second workshop took place in June 2022 in parallel with the open consultation. This time we invited the community to bring software examples with which to test the guidelines. After the WG explained how the guidelines were meant to be used, the participants tried to apply the guidelines to their own software. This exercise proved to be very fruitful and generated additional feedback on the guidelines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It sounds like this was a long, thorough, and iterative process involving the community. What are the next steps for the SMP guidelines?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maaike:&lt;/em&gt; We encourage the community to use these guidelines as a basis to set up their own SMP templates and research software management policies. The eScience Center aims to continue collaborating with research organizations on this topic, and to support the implementation of software management by e.g. developing training for researchers and support staff.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maria:&lt;/em&gt; We consider these guidelines to be a first step in a journey to improve research software management. One important issue that was raised several times during the consultation period was how to implement these guidelines alongside existing research data management policies and protocols. This is something that we still need to solve together with the community in the coming year.&lt;/p&gt;
&lt;p&gt;Interview conducted by &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_rUSMM8nk_zee36V9BS3rXw-6914b60c.BSvvjQ_p.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Versioned documentation using only GitHub actions and GitHub pages</title><link>https://blog2.esciencecenter.nl/posts/2022-10-20---versioned-documentation-using-only-github-actions-and-github</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-10-20---versioned-documentation-using-only-github-actions-and-github</guid><description>&lt;p&gt;Today, I tried something new. Something that I wanted to have for quite a while for one of the main software projects that I’m working on. And that is: versioned documentation. With that, I mean to have multiple different versions of the documentation that reflect the different released versions of the software. Let me start with explaining the current setup.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;987&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WX6X6-C4K_C8Mrc4tyQJKA-c6eba8a8.B65_qlSF_jJDH9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Currently, we have a GitHub action that generates updated Sphinx doc documentation pages whenever something is committed, or preferably, merged into the main branch of the repository. The generated HTML pages are pushed to the root directory of the gh-pages branch of the repository, which is then served by GitHub as a website hosting the documentation for our software. This in itself works really great. So far, so good.&lt;/p&gt;
&lt;p&gt;Now the problem is basically that we don’t make new releases of the software all that often. So the version that is installed using the package manager can actually lag quite a bit behind on the latest developments in the main branch. This is especially nerve wrecking if you realize right before you are about to give an instructor-led tutorial on your software, that there is a rather large mismatch between the version of the software users will install and the documentation pages hosted online.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Anyone reading this may think: “why aren’t you just using readthedocs, which has features to do all of this automatically for you?” A fair question! If you are already using readthedocs for your project, but would like to try a more self-contained solution without compromising on versioning, please read on! My own reason for not using readthedocs is basically that I don’t want to rely on another service by another third-party. Especially, if one of the service providers that I’m already relying upon (in this case GitHub) has everything that we need to avoid relying on yet another service by another party. On the other hand, I sometimes worry about becoming too reliant on GitHub, but that’s for another blogpost.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this case, we use the the Python package index (PyPI) and users may simply install the software using “pip install &lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner&quot;&gt;kernel_tuner&lt;/a&gt; ”. When developments continue for a few months without a release, the documentation pages hosted on GitHub pages will reflect those recent developments, which may include new features or changes that are not present in the version that users receive when they “pip install” the latest version.&lt;/p&gt;
&lt;p&gt;So the main question that I’ll try to answer in this article is: How can we use just GitHub to create versioned documentation pages?&lt;/p&gt;
&lt;p&gt;I solved this in a few simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keep the current GitHub action for generating new documentation after changes on the main branch, but host these in the /latest/ directory.&lt;/li&gt;
&lt;li&gt;Create a new GitHub action that triggers when we create a new release to generate documentation pages for that specific release, use a symlink &lt;code&gt;stable&lt;/code&gt; to point to the latest released version.&lt;/li&gt;
&lt;li&gt;Retroactively generate documentation for all previously released versions.&lt;/li&gt;
&lt;li&gt;Redirect the main repository URL to the documentation in /stable/&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1 The first change that we’ll make is to keep the current setup of generating the documentation whenever something changes on the main branch, but instead of pushing the generated HTML pages to the root directory of our gh-pages branch, we’ll instead push it into the ‘latest’ directory.&lt;/p&gt;
&lt;p&gt;We need to modify &lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner/blob/51f353535ce2bc682cf40944eb8b52a46b0dd71d/.github/workflows/docs.yml&quot;&gt;our current GitHub action&lt;/a&gt;, which is based on the &lt;a href=&quot;https://github.com/sphinx-notes/pages&quot;&gt;sphinx-notes/pages&lt;/a&gt; action. Specifically, I was using the action sphinx-notes/pages@master, but to my surprise the master version is behind the newer versions of this action. I’m now using sphinx-notes/pages@v2, because it supports the &lt;code&gt;target_path&lt;/code&gt; option, which we can use to make sure our documentation pages are stored in the /latest/ directory rather than the root directory of our gh-pages branch.&lt;/p&gt;
&lt;p&gt;2 Step 2 is the most elaborate part of this post. I was looking into GitHub actions that would trigger when someone creates a new release of the software. When searching for this online, I mostly ran into questions on Stackoverflow from people who did not manage to get their GitHub actions to &lt;a href=&quot;https://stackoverflow.com/questions/69063452/github-actions-on-release-created-workflow-trigger-not-working&quot;&gt;trigger properly when new releases were created&lt;/a&gt;. Not a very good sign when you are just starting to look into how to get something done.&lt;/p&gt;
&lt;p&gt;The main issue is apparently that actions that trigger on the creation of a new release do not necessarily trigger for creating a &lt;em&gt;draft&lt;/em&gt; release, and the ‘creation’ trigger of the release can be skipped entirely when an external tool is used to create the GitHub release. There were some suggested solutions to these problems, but most of these seemed overly complicated, and also not really related to the underlying issue. Luckily, &lt;a href=&quot;https://stackoverflow.com/a/61066906&quot;&gt;someone answered on another question about this issue&lt;/a&gt; to use &lt;code&gt;on:release:published&lt;/code&gt; instead of &lt;code&gt;on:release:created&lt;/code&gt; to avoid all of the issues related to triggering workflows on new software releases.&lt;/p&gt;
&lt;p&gt;With this knowledge, we can easily modify the basic usage of the sphinx-notes/pages action to use the trigger &lt;code&gt;on:release:published&lt;/code&gt; instead of &lt;code&gt;on:push:branches:-master&lt;/code&gt;. However, we still need to ensure that the generated documentation is stored in a directory specific for that version. So we need extract the version number from GitHub so that we can use it inside the action. Luckily, &lt;a href=&quot;https://stackoverflow.com/questions/69063452/github-actions-on-release-created-workflow-trigger-not-working&quot;&gt;someone in one of the stackoverflow discussions&lt;/a&gt; provided a line for this in their code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; echo &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RELEASE_VERSION=${GITHUB_REF#refs/*/}&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;GITHUB_ENV&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this, we can use &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;_&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;RELEASE\_VERSION inside our workflow as a variable that contains the version number of the release currently being published. This means we can further modify our action to use &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0044em;vertical-align:-0.31em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot; style=&quot;margin-right:0.0278em;&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;iab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ain&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mb&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;tl&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RELEASE_VERSION as the target_path for our sphinx-nodes/pages action to ensure that the generated HTML documentation pages are stored in a directory named after our version. I first tried to use:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Build&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Commit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sphinx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;notes&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pages&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  with&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    documentation_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; doc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    target_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RELEASE_VERSION&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But for reasons that are obscure to me, this didn’t work. A directory was created with the name “$RELEASE_VERSION”. The variable was not evaluated, but basically treated literally as a fancy string starting with a dollar sign and someone shouting RELEASE_VERSION in full caps. After referring back to the &lt;a href=&quot;https://stackoverflow.com/questions/69063452/github-actions-on-release-created-workflow-trigger-not-working&quot;&gt;same stackoverflow issue&lt;/a&gt;, I noticed there was another way to use the variable, which lead me to try:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Build&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Commit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sphinx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;notes&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pages&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  with&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    documentation_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; doc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    target_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ env.RELEASE_VERSION }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this worked like a charm! Now finally, I wanted to have the URL /stable/ to point to the most recently released version. For this, I’ll be using a symlink. So after the “Build and Commit” step, but before the “Push changes” step, I’m introducing another step in the workflow:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Redirect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stable to new release&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    echo &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Redirecting stable to newly released version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ln &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RELEASE_VERSION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git add stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git commit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;redirect stable to new version $RELEASE_VERSION&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This set of commands removes the old ‘stable’ symlink, if there is any, and creates a new link named stable that points to the value of $RELEASE_VERSION. We then add the file to the git repo, which is already configured to commit as a ‘GitHub actions user’ and is already set on the gh-pages branch thanks to the previous ‘Build and Commit’ step in our workflow. The resulting GitHub action workflow file can be found here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner/blob/master/.github/workflows/docs-on-release.yml&quot;&gt;https://github.com/KernelTuner/kernel_tuner/blob/master/.github/workflows/docs-on-release.yml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This ensures that versioned documentation will be automatically created for us for all new releases. However, we already had a couple of releases over the last six years. To retroactively generate documentation pages for those, we move to step 3.&lt;/p&gt;
&lt;p&gt;3 Going through all of the previous releases, generating documentation for those, and pushing them to the right directory on the gh-pages branch, first appeared to me as a daunting, mind-numbing, “oh-this-is-going-to-be-a-lot-of-manual-labour” task.&lt;/p&gt;
&lt;p&gt;Fortunately, the actual commands used to generate the documentation pages never changed since the first version. This actually means that once we know how to do it for one version, automating the procedure for all previous versions with a simple bash script is trivial:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;versions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`git tag &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`for version &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;versions; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git checkout tags&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cd doc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  rm &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;rf build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  make html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git checkout gh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pages&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  mkdir &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;r doc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/*&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git add &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git commit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;generate documentation for version $version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we can use git to query all released versions, which correspond to ‘tags’ in git. The command &lt;code&gt;git tag -l&lt;/code&gt; generates a list of all released versions of our repo. This allows us to iterate over all versions of our software, using a simple for loop in bash.&lt;/p&gt;
&lt;p&gt;In this loop, we “git checkout” the specific tag. This brings our local git repository in the dreaded “detached HEAD” state. Fortunately for us this doesn’t matter this time, since we are only going to read from this state. Usually when I end up with my HEAD detached, I try to undo whatever I was doing and get the hell out of there as fast as possible. But trust me, for what we are doing here: it’s OK.&lt;/p&gt;
&lt;p&gt;Using the version of the repository at this specific tag, we can generate the HTML documentation as it was when this version was released. Note that our git repository is configured to not track files in the “doc/build” directory, so we are not changing anything in our “detached HEAD” state and we can safely leave this state again without git starting to complain and not allowing you to leave this limbo state. Then, we checkout the gh-pages branch and copy the recently build HTML pages to a directory named for this version. Finally, we commit the changes to the gh-pages branch and proceed to the next tag in the list provided by git. Rinse and repeat, for all released versions of our software.&lt;/p&gt;
&lt;p&gt;4 Step 4 is really simple. I wanted our main repository URL to redirect to the /stable/ URL. The idea behind this is that most users will likely install the software using PyPI and therefore the default location for the documentation should correspond with the latest version present in PyPI.&lt;/p&gt;
&lt;p&gt;After cleaning up the old HTML files in the root of the gh-pages branch, I created an index.html file with the following contents:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;meta http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;equiv&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;refresh&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0; url=stable/&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that’s all! We now have versioned documentation pages for all of our released versions, including all previous releases. A &lt;a href=&quot;https://kerneltuner.github.io/kernel_tuner/stable/&quot;&gt;/stable/&lt;/a&gt; that points to the documentation of most recently released version of the software. A &lt;a href=&quot;https://kerneltuner.github.io/kernel_tuner/latest/&quot;&gt;/latest/&lt;/a&gt; that contains the documentation corresponding to the latest developments in the main branch. And an automated workflow that generates versioned documentation whenever we create a new version and updates the location pointed to by /stable/. And all of this using only GitHub actions and GitHub pages.&lt;/p&gt;</description><pubDate>Thu, 20 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, I tried something new. Something that I wanted to have for quite a while for one of the main software projects that I’m working on. And that is: versioned documentation. With that, I mean to have multiple different versions of the documentation that reflect the different released versions of the software. Let me start with explaining the current setup.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;987&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WX6X6-C4K_C8Mrc4tyQJKA-c6eba8a8.B65_qlSF_jJDH9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Currently, we have a GitHub action that generates updated Sphinx doc documentation pages whenever something is committed, or preferably, merged into the main branch of the repository. The generated HTML pages are pushed to the root directory of the gh-pages branch of the repository, which is then served by GitHub as a website hosting the documentation for our software. This in itself works really great. So far, so good.&lt;/p&gt;
&lt;p&gt;Now the problem is basically that we don’t make new releases of the software all that often. So the version that is installed using the package manager can actually lag quite a bit behind on the latest developments in the main branch. This is especially nerve wrecking if you realize right before you are about to give an instructor-led tutorial on your software, that there is a rather large mismatch between the version of the software users will install and the documentation pages hosted online.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Anyone reading this may think: “why aren’t you just using readthedocs, which has features to do all of this automatically for you?” A fair question! If you are already using readthedocs for your project, but would like to try a more self-contained solution without compromising on versioning, please read on! My own reason for not using readthedocs is basically that I don’t want to rely on another service by another third-party. Especially, if one of the service providers that I’m already relying upon (in this case GitHub) has everything that we need to avoid relying on yet another service by another party. On the other hand, I sometimes worry about becoming too reliant on GitHub, but that’s for another blogpost.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this case, we use the the Python package index (PyPI) and users may simply install the software using “pip install &lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner&quot;&gt;kernel_tuner&lt;/a&gt; ”. When developments continue for a few months without a release, the documentation pages hosted on GitHub pages will reflect those recent developments, which may include new features or changes that are not present in the version that users receive when they “pip install” the latest version.&lt;/p&gt;
&lt;p&gt;So the main question that I’ll try to answer in this article is: How can we use just GitHub to create versioned documentation pages?&lt;/p&gt;
&lt;p&gt;I solved this in a few simple steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Keep the current GitHub action for generating new documentation after changes on the main branch, but host these in the /latest/ directory.&lt;/li&gt;
&lt;li&gt;Create a new GitHub action that triggers when we create a new release to generate documentation pages for that specific release, use a symlink &lt;code&gt;stable&lt;/code&gt; to point to the latest released version.&lt;/li&gt;
&lt;li&gt;Retroactively generate documentation for all previously released versions.&lt;/li&gt;
&lt;li&gt;Redirect the main repository URL to the documentation in /stable/&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;1 The first change that we’ll make is to keep the current setup of generating the documentation whenever something changes on the main branch, but instead of pushing the generated HTML pages to the root directory of our gh-pages branch, we’ll instead push it into the ‘latest’ directory.&lt;/p&gt;
&lt;p&gt;We need to modify &lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner/blob/51f353535ce2bc682cf40944eb8b52a46b0dd71d/.github/workflows/docs.yml&quot;&gt;our current GitHub action&lt;/a&gt;, which is based on the &lt;a href=&quot;https://github.com/sphinx-notes/pages&quot;&gt;sphinx-notes/pages&lt;/a&gt; action. Specifically, I was using the action sphinx-notes/pages@master, but to my surprise the master version is behind the newer versions of this action. I’m now using sphinx-notes/pages@v2, because it supports the &lt;code&gt;target_path&lt;/code&gt; option, which we can use to make sure our documentation pages are stored in the /latest/ directory rather than the root directory of our gh-pages branch.&lt;/p&gt;
&lt;p&gt;2 Step 2 is the most elaborate part of this post. I was looking into GitHub actions that would trigger when someone creates a new release of the software. When searching for this online, I mostly ran into questions on Stackoverflow from people who did not manage to get their GitHub actions to &lt;a href=&quot;https://stackoverflow.com/questions/69063452/github-actions-on-release-created-workflow-trigger-not-working&quot;&gt;trigger properly when new releases were created&lt;/a&gt;. Not a very good sign when you are just starting to look into how to get something done.&lt;/p&gt;
&lt;p&gt;The main issue is apparently that actions that trigger on the creation of a new release do not necessarily trigger for creating a &lt;em&gt;draft&lt;/em&gt; release, and the ‘creation’ trigger of the release can be skipped entirely when an external tool is used to create the GitHub release. There were some suggested solutions to these problems, but most of these seemed overly complicated, and also not really related to the underlying issue. Luckily, &lt;a href=&quot;https://stackoverflow.com/a/61066906&quot;&gt;someone answered on another question about this issue&lt;/a&gt; to use &lt;code&gt;on:release:published&lt;/code&gt; instead of &lt;code&gt;on:release:created&lt;/code&gt; to avoid all of the issues related to triggering workflows on new software releases.&lt;/p&gt;
&lt;p&gt;With this knowledge, we can easily modify the basic usage of the sphinx-notes/pages action to use the trigger &lt;code&gt;on:release:published&lt;/code&gt; instead of &lt;code&gt;on:push:branches:-master&lt;/code&gt;. However, we still need to ensure that the generated documentation is stored in a directory specific for that version. So we need extract the version number from GitHub so that we can use it inside the action. Luckily, &lt;a href=&quot;https://stackoverflow.com/questions/69063452/github-actions-on-release-created-workflow-trigger-not-working&quot;&gt;someone in one of the stackoverflow discussions&lt;/a&gt; provided a line for this in their code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; env&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; echo &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;RELEASE_VERSION=${GITHUB_REF#refs/*/}&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;GITHUB_ENV&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this, we can use &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;A&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;_&lt;/mi&gt;&lt;mi&gt;V&lt;/mi&gt;&lt;mi&gt;E&lt;/mi&gt;&lt;mi&gt;R&lt;/mi&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;I&lt;/mi&gt;&lt;mi&gt;O&lt;/mi&gt;&lt;mi&gt;N&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;k&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;w&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;RELEASE\_VERSION inside our workflow as a variable that contains the version number of the release currently being published. This means we can further modify our action to use &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.0044em;vertical-align:-0.31em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord&quot; style=&quot;margin-right:0.0278em;&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.2222em;&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0077em;&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0576em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0785em;&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;O&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;eo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0315em;&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;iab&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ha&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ain&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;mb&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;sec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;tl&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0269em;&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;an&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;er&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;se&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;RELEASE_VERSION as the target_path for our sphinx-nodes/pages action to ensure that the generated HTML documentation pages are stored in a directory named after our version. I first tried to use:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Build&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Commit&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sphinx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;notes&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pages&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  with&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    documentation_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; doc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    target_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RELEASE_VERSION&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But for reasons that are obscure to me, this didn’t work. A directory was created with the name “$RELEASE_VERSION”. The variable was not evaluated, but basically treated literally as a fancy string starting with a dollar sign and someone shouting RELEASE_VERSION in full caps. After referring back to the &lt;a href=&quot;https://stackoverflow.com/questions/69063452/github-actions-on-release-created-workflow-trigger-not-working&quot;&gt;same stackoverflow issue&lt;/a&gt;, I noticed there was another way to use the variable, which lead me to try:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Build&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Commit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sphinx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;notes&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pages&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  with&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    documentation_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; doc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    target_path&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ env.RELEASE_VERSION }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this worked like a charm! Now finally, I wanted to have the URL /stable/ to point to the most recently released version. For this, I’ll be using a symlink. So after the “Build and Commit” step, but before the “Push changes” step, I’m introducing another step in the workflow:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Redirect&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stable to new release&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    echo &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Redirecting stable to newly released version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    ln &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RELEASE_VERSION&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git add stable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git commit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;redirect stable to new version $RELEASE_VERSION&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This set of commands removes the old ‘stable’ symlink, if there is any, and creates a new link named stable that points to the value of $RELEASE_VERSION. We then add the file to the git repo, which is already configured to commit as a ‘GitHub actions user’ and is already set on the gh-pages branch thanks to the previous ‘Build and Commit’ step in our workflow. The resulting GitHub action workflow file can be found here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/KernelTuner/kernel_tuner/blob/master/.github/workflows/docs-on-release.yml&quot;&gt;https://github.com/KernelTuner/kernel_tuner/blob/master/.github/workflows/docs-on-release.yml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This ensures that versioned documentation will be automatically created for us for all new releases. However, we already had a couple of releases over the last six years. To retroactively generate documentation pages for those, we move to step 3.&lt;/p&gt;
&lt;p&gt;3 Going through all of the previous releases, generating documentation for those, and pushing them to the right directory on the gh-pages branch, first appeared to me as a daunting, mind-numbing, “oh-this-is-going-to-be-a-lot-of-manual-labour” task.&lt;/p&gt;
&lt;p&gt;Fortunately, the actual commands used to generate the documentation pages never changed since the first version. This actually means that once we know how to do it for one version, automating the procedure for all previous versions with a simple bash script is trivial:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;versions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`git tag &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;l&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`for version &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;versions; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git checkout tags&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cd doc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  rm &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;rf build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  make html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git checkout gh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pages&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  mkdir &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;r doc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/*&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git add &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  git commit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;generate documentation for version $version&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we can use git to query all released versions, which correspond to ‘tags’ in git. The command &lt;code&gt;git tag -l&lt;/code&gt; generates a list of all released versions of our repo. This allows us to iterate over all versions of our software, using a simple for loop in bash.&lt;/p&gt;
&lt;p&gt;In this loop, we “git checkout” the specific tag. This brings our local git repository in the dreaded “detached HEAD” state. Fortunately for us this doesn’t matter this time, since we are only going to read from this state. Usually when I end up with my HEAD detached, I try to undo whatever I was doing and get the hell out of there as fast as possible. But trust me, for what we are doing here: it’s OK.&lt;/p&gt;
&lt;p&gt;Using the version of the repository at this specific tag, we can generate the HTML documentation as it was when this version was released. Note that our git repository is configured to not track files in the “doc/build” directory, so we are not changing anything in our “detached HEAD” state and we can safely leave this state again without git starting to complain and not allowing you to leave this limbo state. Then, we checkout the gh-pages branch and copy the recently build HTML pages to a directory named for this version. Finally, we commit the changes to the gh-pages branch and proceed to the next tag in the list provided by git. Rinse and repeat, for all released versions of our software.&lt;/p&gt;
&lt;p&gt;4 Step 4 is really simple. I wanted our main repository URL to redirect to the /stable/ URL. The idea behind this is that most users will likely install the software using PyPI and therefore the default location for the documentation should correspond with the latest version present in PyPI.&lt;/p&gt;
&lt;p&gt;After cleaning up the old HTML files in the root of the gh-pages branch, I created an index.html file with the following contents:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;meta http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;equiv&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;refresh&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; content&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;0; url=stable/&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that’s all! We now have versioned documentation pages for all of our released versions, including all previous releases. A &lt;a href=&quot;https://kerneltuner.github.io/kernel_tuner/stable/&quot;&gt;/stable/&lt;/a&gt; that points to the documentation of most recently released version of the software. A &lt;a href=&quot;https://kerneltuner.github.io/kernel_tuner/latest/&quot;&gt;/latest/&lt;/a&gt; that contains the documentation corresponding to the latest developments in the main branch. And an automated workflow that generates versioned documentation whenever we create a new version and updates the location pointed to by /stable/. And all of this using only GitHub actions and GitHub pages.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_WX6X6-C4K_C8Mrc4tyQJKA-c6eba8a8.B65_qlSF.png" medium="image"/><author>Ben van Werkhoven</author></item><item><title>Mathematics and biology: a symbiosis?</title><link>https://blog2.esciencecenter.nl/posts/2022-10-12---mathematics-and-biology-a-symbiosis</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-10-12---mathematics-and-biology-a-symbiosis</guid><description>&lt;p&gt;&lt;em&gt;Lessons learned, from a mathematician among biologists.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_5FbzBhG-vIYMnJkE-fedba0ed.Ddq9Kv1a_14WKMi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by ThisisEngineering RAEng on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;preamble&quot;&gt;Preamble&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;In the period 2015–2019, I was hired as a mathematician by a biology department in order to work on a research line that eventually would become my doctoral thesis. This text is adapted from the last chapter of that thesis, “Cycles and interactions: A mathematician among biologists” (full text available&lt;/em&gt; &lt;a href=&quot;https://doi.org/10.18174/520571&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The symbiosis between mathematics and biology, although may seem improbable at first sight, is actually backed by a centuries-old tradition of collaboration. It started with mathematicians that were inspired by biology such as Leonardo Pisano, alias Fibonacci. His famous sequence (namely: 1, 1, 2, 3, 5, 8, 13, …, where each element is the sum of the two previous ones), a landmark in number theory very popular among amateur mathematicians, was first described in the context of a practical problem on rabbit breeding in such an early date as the year 1202.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Mathematical knowledge has improved greatly since the 13th century. The foundations of the tools used by modern mathematical biologists, namely, calculus and differential equations, were laid in the late 17th century by Isaac Newton and Gottfried Leibniz motivated by mechanical problems. The great mathematician Leonhard Euler and the economist and demographer Thomas R. Malthus, two of the pioneers of using differential equations to address biological problems, had both printed their seminal works in population dynamics before the fall of the year 1800.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This interdisciplinary collaboration between mathematics and biology is nowadays alive and in good shape. Some of the most influential names in ecology in the 20th and 21st centuries have, indeed, a background in mathematics (such as Robert MacArthur, Simon Levin, or Alan Hastings) or in physics (such as Robert May).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The opportunity offered by cheap access to computing power, together with the unavoidable increase of required technical skills such as programming, data analysis, and advanced statistical methods, points to a future where the technical profiles expected from a research team in biology will not be so different to those of a team of physicists or applied mathematicians. It is reasonable to expect that this symbiosis between mathematicians and biologists will remain strong, and even get stronger, in the near future.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I hereby offer some advice for both biologists and mathematicians (understood here as mathematically oriented professionals, including physicists and engineers) interested in exploring “the other side”. It contains the kind of advice I would have liked to have had in 2015, when I approached, naively as only a physicist can do, the world of biology.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Mathematics is often perceived as a harsh subject both by scientific and non-scientific professionals. Despite those preferences and prejudices, mathematics is used in almost every field of knowledge and are a must-have in any multidisciplinary project.&lt;/p&gt;
&lt;p&gt;Different disciplines have associated not only a set of background knowledge and methods but a whole academic culture. When crossing the borders between disciplines, facts and methods can be learned, but accepting and adapting to another culture is much harder.&lt;/p&gt;
&lt;p&gt;As with any other culture, mathematicians and biologists differ slightly in language, values, norms, and interests. As usually happens in intercultural communication, there is plenty of opportunity for misunderstandings, and each subgroup cultivates myths and misconceptions about the other.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Advice for biologists working with mathematicians&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;943&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_DXaLJZXNaU0oSjxf-c6daa72d.T7wbfhiD_19RaEE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NOAA on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;invest-in-applied-mathematics&quot;&gt;Invest in applied mathematics&lt;/h3&gt;
&lt;p&gt;Applied mathematics doesn’t mean easy mathematics. The adjective “applied” or “pure”, accompanying the word “mathematics”, tells us something about the object under study, but nothing about its difficulty. Indeed, the mathematical tool will be as complex as the object under study is.&lt;/p&gt;
&lt;p&gt;It may be frustrating to learn that, for instance, it is required to get familiar with second-order tensors (a particularly hard tool rooted in differential geometry) in order to understand fluid dynamics. Mathematicians don’t introduce this tool to torture the newcomers, but because tensors are the easiest available tool to study a complex phenomenon that cannot be avoided in the study of fluids: deformation.&lt;/p&gt;
&lt;p&gt;The difficulty is provided by the problem under study, not by the tool used to solve it.&lt;/p&gt;
&lt;h3 id=&quot;equations-and-rigor-are-not-torture-instruments&quot;&gt;Equations and rigor are not torture instruments&lt;/h3&gt;
&lt;p&gt;It is known that the mere sight of an equation can create anxiety. Even the physicist Stephen Hawking, in the preface of his best-seller “A brief history of time”, claims that each printed equation divides the potential audience by two.&lt;/p&gt;
&lt;p&gt;Whether we like them or not, equations are often the best way to share complex information in a compact and practical manner. Invest time in learning how to read them. Rigorous and detailed analyses are often required, as some details can escape intuition.&lt;/p&gt;
&lt;p&gt;Be also aware that the same equation can be written in different ways. Even if different ways of writing the same equation are correct, some of them can be clearer than others. Consistent use of upper and lower case (for instance, upper for states, lower for parameters), superscript and subscript, smart use of auxiliary definitions, proper alignment of related equations and other simple rules can significantly increase the readability of your scientific output.&lt;/p&gt;
&lt;h3 id=&quot;modeling-is-all-about-simplifying&quot;&gt;Modeling is all about simplifying&lt;/h3&gt;
&lt;p&gt;Be prepared that the main task of modeling is simplifying. This is the main challenge as here both an understanding of the system and of modeling techniques are required. In the design phase of a model, lots of exchange is needed between the biologists and the mathematicians. This may come as a surprise, but most mathematicians feel overwhelmed by biologists’ talk. Biologists tend to provide them with too much information.&lt;/p&gt;
&lt;p&gt;When communicating to mathematicians, focus more on the ideas than on the details you would provide for your peers. You can easily underestimate how difficult your own field is for outsiders. For instance, the experimental methods can be left out, as mathematicians will just assume that the data has been properly collected.&lt;/p&gt;
&lt;p&gt;Try also to think in terms of inputs, processes, and outputs. This exercise is not only good for interdisciplinary communication, but also for experimental design and even for structuring a report.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Advice for mathematicians working with biologists&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1120&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_8cgevQhUCpP9y59N-5a490c31.BRX8XfLU_Z28lOn2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Benjamin Lizardo on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;make-peace-with-uncertainty&quot;&gt;Make peace with uncertainty&lt;/h3&gt;
&lt;p&gt;Due to the complexity of the subject of study, it is unrealistic to expect the same precision from biological models as from physical ones. Forget all you learned in math/physics/engineering school about discarding any result with an &lt;em&gt;r&lt;/em&gt; 2 below 0.99. You are working with biological and, thus, complex systems now. Models just do as well as possible. Additionally, you’ll have to embrace the fact that most of these models rarely allow an elegant, analytical approach, and numerical methods will be required most of the time.&lt;/p&gt;
&lt;h3 id=&quot;explain-why-you-do-what-you-do&quot;&gt;Explain why you do what you do&lt;/h3&gt;
&lt;p&gt;When explaining a mathematical method, instead of starting with generic propositions and formal proofs, always explain why it is useful using simple examples. Biologists may quickly lose motivation if they are not convinced that the mathematics used is somehow useful.&lt;/p&gt;
&lt;p&gt;A particularly illuminating experience happened to me while teaching &lt;a href=&quot;https://en.wikipedia.org/wiki/Matrix_multiplication&quot;&gt;matrix multiplication&lt;/a&gt; to a group of biology students. The topic is particularly boring and most often is just presented as a rule. In this case, I proceeded differently: I first let the students experience the &lt;em&gt;need&lt;/em&gt; for a compact notation (by making them write down, line by line, increasingly larger competition models), and later I explained why the rule of matrix notation is what it is and how it solves their need.&lt;/p&gt;
&lt;p&gt;Presented this way, the students notice that the mathematical tool is solving a problem they already have, instead of feeling that it creates a new one (that of having to learn how to use a new tool). Additionally, the explanations about why the rule is how it is, help them learn and remember it.&lt;/p&gt;
&lt;h3 id=&quot;proofs-are-scary&quot;&gt;Proofs are scary&lt;/h3&gt;
&lt;p&gt;Maybe you think mathematical proofs &lt;em&gt;shouldn’t&lt;/em&gt; be scary, but the fact is that for many biologists they are. A mathematical proof is somehow a journey, a journey from a set of assumptions to a conclusion, and your collaborators should enjoy the ride too.&lt;/p&gt;
&lt;p&gt;Often, proofs can be substituted by a graphical or intuitive approach. This substitution may come with some simplification when affordable, but often can be done without loss. Euclid’s “Elements”, probably the most influential mathematical book ever written, contains mostly visual proofs. More modern examples can be found in the collection “Proofs without words”.&lt;/p&gt;
&lt;p&gt;If mathematical proof is really needed, make an effort in explaining the notation and all the steps. The quickest way of creating frustration in your audience is by using the word &lt;em&gt;trivial&lt;/em&gt;, so avoid it always. When writing publications in non-mathematical journals, it is usually a good idea to write the proofs in an appendix and just state the results as a fact in the main body. Just like mathematicians feel they cannot judge experimental methods, most biologists will assume proofs are correct.&lt;/p&gt;
&lt;h3 id=&quot;invest-in-software-engineering-techniques&quot;&gt;Invest in software engineering techniques&lt;/h3&gt;
&lt;p&gt;Very often, your collaborators will ask you to provide a tool for, say, simulating a biological system or performing a statistical calculation. Encapsulating such a tool in usable and robust pieces of software could be a very good idea. Getting introduced to the world of software engineering can be very helpful in this regard. For a brilliant, quick introduction, see &lt;a href=&quot;https://doi.org/10.1371/journal.pbio.1001745&quot;&gt;Best practices for Scientific Computing, Wilson et al., PLOS Biology, 2014&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;use-as-much-visualization-as-possible&quot;&gt;Use as much visualization as possible&lt;/h3&gt;
&lt;p&gt;Take advantage of humans’ most advanced information acquisition system: vision. Illustrate your ideas with graphs and figures, or even movies and animations when applicable. If they are good, they can even replace an equation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Advice for both&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_dAPLLYwIVvS6lIZh-2a42204c.uq9YxrzM_Z1e6Y6v.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Gift Habeshaw on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;get-involved-in-science-communication&quot;&gt;Get involved in science communication&lt;/h3&gt;
&lt;p&gt;If you think interdisciplinary communication is hard, just try to communicate science to the general public. Not only will you notice that science communication is even harder, but also you will learn a lot about how to improve your overall communication skills.&lt;/p&gt;
&lt;p&gt;Nowadays there are lots of ways of getting involved with this activity (from writing a blog to giving a talk at an event). The practice of science communication forces a deep understanding of the topic being communicated. It requires removing the unnecessary, identifying what is hard and why and advancing the audience’s questions and doubts. It requires, in one word, understanding.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This text is adapted from the author’s doctoral thesis,&lt;/em&gt; &lt;a href=&quot;https://research.wur.nl/en/publications/cycles-and-interactions-a-mathematician-among-biologists&quot;&gt;&lt;em&gt;Cycles and interactions: A mathematician among biologists&lt;/em&gt;&lt;/a&gt;, section 5.4*. An earlier version of it was also published in* &lt;a href=&quot;https://mappingignorance.org/2020/11/09/how-can-we-improve-the-communication-between-mathematics-and-life-sciences/&quot;&gt;&lt;em&gt;Mapping Ignorance&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;and a Spanish translation in&lt;/em&gt; &lt;a href=&quot;https://culturacientifica.com/2020/11/02/como-mejorar-la-comunicacion-entre-las-matematicas-y-las-ciencias-de-la-vida/&quot;&gt;&lt;em&gt;Cátedra de Cultura Científica&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Wed, 12 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Lessons learned, from a mathematician among biologists.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_5FbzBhG-vIYMnJkE-fedba0ed.Ddq9Kv1a_14WKMi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by ThisisEngineering RAEng on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;preamble&quot;&gt;Preamble&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;In the period 2015–2019, I was hired as a mathematician by a biology department in order to work on a research line that eventually would become my doctoral thesis. This text is adapted from the last chapter of that thesis, “Cycles and interactions: A mathematician among biologists” (full text available&lt;/em&gt; &lt;a href=&quot;https://doi.org/10.18174/520571&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The symbiosis between mathematics and biology, although may seem improbable at first sight, is actually backed by a centuries-old tradition of collaboration. It started with mathematicians that were inspired by biology such as Leonardo Pisano, alias Fibonacci. His famous sequence (namely: 1, 1, 2, 3, 5, 8, 13, …, where each element is the sum of the two previous ones), a landmark in number theory very popular among amateur mathematicians, was first described in the context of a practical problem on rabbit breeding in such an early date as the year 1202.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Mathematical knowledge has improved greatly since the 13th century. The foundations of the tools used by modern mathematical biologists, namely, calculus and differential equations, were laid in the late 17th century by Isaac Newton and Gottfried Leibniz motivated by mechanical problems. The great mathematician Leonhard Euler and the economist and demographer Thomas R. Malthus, two of the pioneers of using differential equations to address biological problems, had both printed their seminal works in population dynamics before the fall of the year 1800.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This interdisciplinary collaboration between mathematics and biology is nowadays alive and in good shape. Some of the most influential names in ecology in the 20th and 21st centuries have, indeed, a background in mathematics (such as Robert MacArthur, Simon Levin, or Alan Hastings) or in physics (such as Robert May).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The opportunity offered by cheap access to computing power, together with the unavoidable increase of required technical skills such as programming, data analysis, and advanced statistical methods, points to a future where the technical profiles expected from a research team in biology will not be so different to those of a team of physicists or applied mathematicians. It is reasonable to expect that this symbiosis between mathematicians and biologists will remain strong, and even get stronger, in the near future.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I hereby offer some advice for both biologists and mathematicians (understood here as mathematically oriented professionals, including physicists and engineers) interested in exploring “the other side”. It contains the kind of advice I would have liked to have had in 2015, when I approached, naively as only a physicist can do, the world of biology.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Mathematics is often perceived as a harsh subject both by scientific and non-scientific professionals. Despite those preferences and prejudices, mathematics is used in almost every field of knowledge and are a must-have in any multidisciplinary project.&lt;/p&gt;
&lt;p&gt;Different disciplines have associated not only a set of background knowledge and methods but a whole academic culture. When crossing the borders between disciplines, facts and methods can be learned, but accepting and adapting to another culture is much harder.&lt;/p&gt;
&lt;p&gt;As with any other culture, mathematicians and biologists differ slightly in language, values, norms, and interests. As usually happens in intercultural communication, there is plenty of opportunity for misunderstandings, and each subgroup cultivates myths and misconceptions about the other.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Advice for biologists working with mathematicians&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;943&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_DXaLJZXNaU0oSjxf-c6daa72d.T7wbfhiD_19RaEE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NOAA on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;invest-in-applied-mathematics&quot;&gt;Invest in applied mathematics&lt;/h3&gt;
&lt;p&gt;Applied mathematics doesn’t mean easy mathematics. The adjective “applied” or “pure”, accompanying the word “mathematics”, tells us something about the object under study, but nothing about its difficulty. Indeed, the mathematical tool will be as complex as the object under study is.&lt;/p&gt;
&lt;p&gt;It may be frustrating to learn that, for instance, it is required to get familiar with second-order tensors (a particularly hard tool rooted in differential geometry) in order to understand fluid dynamics. Mathematicians don’t introduce this tool to torture the newcomers, but because tensors are the easiest available tool to study a complex phenomenon that cannot be avoided in the study of fluids: deformation.&lt;/p&gt;
&lt;p&gt;The difficulty is provided by the problem under study, not by the tool used to solve it.&lt;/p&gt;
&lt;h3 id=&quot;equations-and-rigor-are-not-torture-instruments&quot;&gt;Equations and rigor are not torture instruments&lt;/h3&gt;
&lt;p&gt;It is known that the mere sight of an equation can create anxiety. Even the physicist Stephen Hawking, in the preface of his best-seller “A brief history of time”, claims that each printed equation divides the potential audience by two.&lt;/p&gt;
&lt;p&gt;Whether we like them or not, equations are often the best way to share complex information in a compact and practical manner. Invest time in learning how to read them. Rigorous and detailed analyses are often required, as some details can escape intuition.&lt;/p&gt;
&lt;p&gt;Be also aware that the same equation can be written in different ways. Even if different ways of writing the same equation are correct, some of them can be clearer than others. Consistent use of upper and lower case (for instance, upper for states, lower for parameters), superscript and subscript, smart use of auxiliary definitions, proper alignment of related equations and other simple rules can significantly increase the readability of your scientific output.&lt;/p&gt;
&lt;h3 id=&quot;modeling-is-all-about-simplifying&quot;&gt;Modeling is all about simplifying&lt;/h3&gt;
&lt;p&gt;Be prepared that the main task of modeling is simplifying. This is the main challenge as here both an understanding of the system and of modeling techniques are required. In the design phase of a model, lots of exchange is needed between the biologists and the mathematicians. This may come as a surprise, but most mathematicians feel overwhelmed by biologists’ talk. Biologists tend to provide them with too much information.&lt;/p&gt;
&lt;p&gt;When communicating to mathematicians, focus more on the ideas than on the details you would provide for your peers. You can easily underestimate how difficult your own field is for outsiders. For instance, the experimental methods can be left out, as mathematicians will just assume that the data has been properly collected.&lt;/p&gt;
&lt;p&gt;Try also to think in terms of inputs, processes, and outputs. This exercise is not only good for interdisciplinary communication, but also for experimental design and even for structuring a report.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Advice for mathematicians working with biologists&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1120&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_8cgevQhUCpP9y59N-5a490c31.BRX8XfLU_Z28lOn2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Benjamin Lizardo on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;make-peace-with-uncertainty&quot;&gt;Make peace with uncertainty&lt;/h3&gt;
&lt;p&gt;Due to the complexity of the subject of study, it is unrealistic to expect the same precision from biological models as from physical ones. Forget all you learned in math/physics/engineering school about discarding any result with an &lt;em&gt;r&lt;/em&gt; 2 below 0.99. You are working with biological and, thus, complex systems now. Models just do as well as possible. Additionally, you’ll have to embrace the fact that most of these models rarely allow an elegant, analytical approach, and numerical methods will be required most of the time.&lt;/p&gt;
&lt;h3 id=&quot;explain-why-you-do-what-you-do&quot;&gt;Explain why you do what you do&lt;/h3&gt;
&lt;p&gt;When explaining a mathematical method, instead of starting with generic propositions and formal proofs, always explain why it is useful using simple examples. Biologists may quickly lose motivation if they are not convinced that the mathematics used is somehow useful.&lt;/p&gt;
&lt;p&gt;A particularly illuminating experience happened to me while teaching &lt;a href=&quot;https://en.wikipedia.org/wiki/Matrix_multiplication&quot;&gt;matrix multiplication&lt;/a&gt; to a group of biology students. The topic is particularly boring and most often is just presented as a rule. In this case, I proceeded differently: I first let the students experience the &lt;em&gt;need&lt;/em&gt; for a compact notation (by making them write down, line by line, increasingly larger competition models), and later I explained why the rule of matrix notation is what it is and how it solves their need.&lt;/p&gt;
&lt;p&gt;Presented this way, the students notice that the mathematical tool is solving a problem they already have, instead of feeling that it creates a new one (that of having to learn how to use a new tool). Additionally, the explanations about why the rule is how it is, help them learn and remember it.&lt;/p&gt;
&lt;h3 id=&quot;proofs-are-scary&quot;&gt;Proofs are scary&lt;/h3&gt;
&lt;p&gt;Maybe you think mathematical proofs &lt;em&gt;shouldn’t&lt;/em&gt; be scary, but the fact is that for many biologists they are. A mathematical proof is somehow a journey, a journey from a set of assumptions to a conclusion, and your collaborators should enjoy the ride too.&lt;/p&gt;
&lt;p&gt;Often, proofs can be substituted by a graphical or intuitive approach. This substitution may come with some simplification when affordable, but often can be done without loss. Euclid’s “Elements”, probably the most influential mathematical book ever written, contains mostly visual proofs. More modern examples can be found in the collection “Proofs without words”.&lt;/p&gt;
&lt;p&gt;If mathematical proof is really needed, make an effort in explaining the notation and all the steps. The quickest way of creating frustration in your audience is by using the word &lt;em&gt;trivial&lt;/em&gt;, so avoid it always. When writing publications in non-mathematical journals, it is usually a good idea to write the proofs in an appendix and just state the results as a fact in the main body. Just like mathematicians feel they cannot judge experimental methods, most biologists will assume proofs are correct.&lt;/p&gt;
&lt;h3 id=&quot;invest-in-software-engineering-techniques&quot;&gt;Invest in software engineering techniques&lt;/h3&gt;
&lt;p&gt;Very often, your collaborators will ask you to provide a tool for, say, simulating a biological system or performing a statistical calculation. Encapsulating such a tool in usable and robust pieces of software could be a very good idea. Getting introduced to the world of software engineering can be very helpful in this regard. For a brilliant, quick introduction, see &lt;a href=&quot;https://doi.org/10.1371/journal.pbio.1001745&quot;&gt;Best practices for Scientific Computing, Wilson et al., PLOS Biology, 2014&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;use-as-much-visualization-as-possible&quot;&gt;Use as much visualization as possible&lt;/h3&gt;
&lt;p&gt;Take advantage of humans’ most advanced information acquisition system: vision. Illustrate your ideas with graphs and figures, or even movies and animations when applicable. If they are good, they can even replace an equation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Advice for both&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_dAPLLYwIVvS6lIZh-2a42204c.uq9YxrzM_Z1e6Y6v.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Gift Habeshaw on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;get-involved-in-science-communication&quot;&gt;Get involved in science communication&lt;/h3&gt;
&lt;p&gt;If you think interdisciplinary communication is hard, just try to communicate science to the general public. Not only will you notice that science communication is even harder, but also you will learn a lot about how to improve your overall communication skills.&lt;/p&gt;
&lt;p&gt;Nowadays there are lots of ways of getting involved with this activity (from writing a blog to giving a talk at an event). The practice of science communication forces a deep understanding of the topic being communicated. It requires removing the unnecessary, identifying what is hard and why and advancing the audience’s questions and doubts. It requires, in one word, understanding.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This text is adapted from the author’s doctoral thesis,&lt;/em&gt; &lt;a href=&quot;https://research.wur.nl/en/publications/cycles-and-interactions-a-mathematician-among-biologists&quot;&gt;&lt;em&gt;Cycles and interactions: A mathematician among biologists&lt;/em&gt;&lt;/a&gt;, section 5.4*. An earlier version of it was also published in* &lt;a href=&quot;https://mappingignorance.org/2020/11/09/how-can-we-improve-the-communication-between-mathematics-and-life-sciences/&quot;&gt;&lt;em&gt;Mapping Ignorance&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;and a Spanish translation in&lt;/em&gt; &lt;a href=&quot;https://culturacientifica.com/2020/11/02/como-mejorar-la-comunicacion-entre-las-matematicas-y-las-ciencias-de-la-vida/&quot;&gt;&lt;em&gt;Cátedra de Cultura Científica&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_DXaLJZXNaU0oSjxf-c6daa72d.T7wbfhiD.webp" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Fun with elevators: a tutorial</title><link>https://blog2.esciencecenter.nl/posts/2022-09-08---fun-with-elevators-a-tutorial</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-09-08---fun-with-elevators-a-tutorial</guid><description>&lt;p&gt;&lt;em&gt;Most modern cell phones contain an accelerometer. And that’s good news if you are curious about all the data around you&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4ofm5alj_exWfow5-fe38d09c.DDe4Xmw4_1OjHJe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Waldemar Brandt on Unsplash&lt;/p&gt;
&lt;p&gt;Some years ago I did a secondment at the Friedrich Schiller University, in Jena, Germany. To my surprise, my office during those months was located on the 18th floor of a skyscraper, the Jentower:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;360&quot; height=&quot;640&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4Afjsusuv4SsR3XK-958db2fb.DtRZ-AGD_Z10LCp5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Jentower&lt;/p&gt;
&lt;p&gt;But I’m not writing this to boast about the amazing views of my old office. On the contrary, I’ll destroy any possible idea of glamour related to working in a place like this. And I’ll do it with a confession: I became known as the crazy guy who leaves his cell phone on the ground while he uses the elevator. Let me explain why:&lt;/p&gt;
&lt;p&gt;A building almost 150 meters high needs fast elevators. The ones in this building have a very powerful, almost scary acceleration. Then, I remembered that smartphones usually contain an accelerometer, so I tried to measure those accelerations.&lt;/p&gt;
&lt;p&gt;There are many apps that allow registering data from all sensors available on the phone (accelerometers, light, magnetic field, …) and exporting them in an easy format (such as.csv) quite easy to analyze on a computer. If you like getting your hands dirty, give it a try!&lt;/p&gt;
&lt;p&gt;In the figure below we can see the vertical acceleration profile during my trip to the 18th floor one morning, where we can clearly see the initial “kick” (seconds 9 to 14) and the braking (28 to 33).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;682&quot; height=&quot;499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DBRj0N55eBOLr3_TCJ7teQ-7e24e80f.CSLkWZR2_1iQRqQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vertical acceleration vs Time (gravity has been excluded)&lt;/p&gt;
&lt;p&gt;Accelerations of 1 m/s² sustained during 4 seconds! Think that, the usual acceleration your body experiments due to gravity is around 9.8 m/s² so, while the elevator goes up, your weight gets increased by around 10%. You can feel that in your stomach!&lt;/p&gt;
&lt;p&gt;We can explore this data a bit further. We can, for instance, use the acceleration time series to compute speed and position. How? Maybe you remember from high school physics that position (x), velocity (v), and acceleration (a) are related through derivatives. More specifically.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;274&quot; height=&quot;179&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_f6vwlMWN8bQjL9PG-65776d07.D5xf5yLY_28iG6w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;With the previous recipe, we can compute speed using the position, and then use speed to compute acceleration. One after the other, like in a production chain. Nevertheless, in our case, we want to do the opposite process. Luckily, we can use integrals to “revert” our derivatives, and thus our whole “production chain” looks now:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;179&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4qUNhJ4PInVFgVv3-6a15e322.C_UjXeLD_8xfqq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, by integrating the acceleration (to obtain the speed), and then integrating the speed (to obtain the position) we find results like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;678&quot; height=&quot;499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iK8mx2VNGsoUgCzh13hV3Q-f0f16665.BzFpdex5_pOoR6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Acceleration, speed, and position against time.&lt;/p&gt;
&lt;p&gt;So, using only a device that most of us carry everywhere and some elementary physical concepts we know that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our elevator runs up at 4 m/s.&lt;/li&gt;
&lt;li&gt;My office was 74 meters above the ground.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If someone is interested in exploring a bit deeper into the details (for instance: how to filter out the effects of gravity, how to integrate a time series, …) or even experimenting with their own elevator, &lt;a href=&quot;https://github.com/PabRod/elevator-tool&quot;&gt;here is a link&lt;/a&gt; to the code I’ve used.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This text appeared first in&lt;/em&gt; &lt;a href=&quot;http://fuga.naukas.com/2018/02/06/un-empollon-en-mi-ascensor/&quot;&gt;&lt;em&gt;Naukas&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, where it was originally written in Spanish.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 08 Sep 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Most modern cell phones contain an accelerometer. And that’s good news if you are curious about all the data around you&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4ofm5alj_exWfow5-fe38d09c.DDe4Xmw4_1OjHJe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Waldemar Brandt on Unsplash&lt;/p&gt;
&lt;p&gt;Some years ago I did a secondment at the Friedrich Schiller University, in Jena, Germany. To my surprise, my office during those months was located on the 18th floor of a skyscraper, the Jentower:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;360&quot; height=&quot;640&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4Afjsusuv4SsR3XK-958db2fb.DtRZ-AGD_Z10LCp5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Jentower&lt;/p&gt;
&lt;p&gt;But I’m not writing this to boast about the amazing views of my old office. On the contrary, I’ll destroy any possible idea of glamour related to working in a place like this. And I’ll do it with a confession: I became known as the crazy guy who leaves his cell phone on the ground while he uses the elevator. Let me explain why:&lt;/p&gt;
&lt;p&gt;A building almost 150 meters high needs fast elevators. The ones in this building have a very powerful, almost scary acceleration. Then, I remembered that smartphones usually contain an accelerometer, so I tried to measure those accelerations.&lt;/p&gt;
&lt;p&gt;There are many apps that allow registering data from all sensors available on the phone (accelerometers, light, magnetic field, …) and exporting them in an easy format (such as.csv) quite easy to analyze on a computer. If you like getting your hands dirty, give it a try!&lt;/p&gt;
&lt;p&gt;In the figure below we can see the vertical acceleration profile during my trip to the 18th floor one morning, where we can clearly see the initial “kick” (seconds 9 to 14) and the braking (28 to 33).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;682&quot; height=&quot;499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DBRj0N55eBOLr3_TCJ7teQ-7e24e80f.CSLkWZR2_1iQRqQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vertical acceleration vs Time (gravity has been excluded)&lt;/p&gt;
&lt;p&gt;Accelerations of 1 m/s² sustained during 4 seconds! Think that, the usual acceleration your body experiments due to gravity is around 9.8 m/s² so, while the elevator goes up, your weight gets increased by around 10%. You can feel that in your stomach!&lt;/p&gt;
&lt;p&gt;We can explore this data a bit further. We can, for instance, use the acceleration time series to compute speed and position. How? Maybe you remember from high school physics that position (x), velocity (v), and acceleration (a) are related through derivatives. More specifically.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;274&quot; height=&quot;179&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_f6vwlMWN8bQjL9PG-65776d07.D5xf5yLY_28iG6w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;With the previous recipe, we can compute speed using the position, and then use speed to compute acceleration. One after the other, like in a production chain. Nevertheless, in our case, we want to do the opposite process. Luckily, we can use integrals to “revert” our derivatives, and thus our whole “production chain” looks now:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;179&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4qUNhJ4PInVFgVv3-6a15e322.C_UjXeLD_8xfqq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;So, by integrating the acceleration (to obtain the speed), and then integrating the speed (to obtain the position) we find results like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;678&quot; height=&quot;499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iK8mx2VNGsoUgCzh13hV3Q-f0f16665.BzFpdex5_pOoR6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Acceleration, speed, and position against time.&lt;/p&gt;
&lt;p&gt;So, using only a device that most of us carry everywhere and some elementary physical concepts we know that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Our elevator runs up at 4 m/s.&lt;/li&gt;
&lt;li&gt;My office was 74 meters above the ground.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If someone is interested in exploring a bit deeper into the details (for instance: how to filter out the effects of gravity, how to integrate a time series, …) or even experimenting with their own elevator, &lt;a href=&quot;https://github.com/PabRod/elevator-tool&quot;&gt;here is a link&lt;/a&gt; to the code I’ve used.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This text appeared first in&lt;/em&gt; &lt;a href=&quot;http://fuga.naukas.com/2018/02/06/un-empollon-en-mi-ascensor/&quot;&gt;&lt;em&gt;Naukas&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, where it was originally written in Spanish.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_4Afjsusuv4SsR3XK-958db2fb.DtRZ-AGD.jpg" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Our favourite high performance programming tools</title><link>https://blog2.esciencecenter.nl/posts/2022-08-16---our-favourite-high-performance-programming-tools</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-08-16---our-favourite-high-performance-programming-tools</guid><description>&lt;p&gt;Does your code need a performance boost? Ask us!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3648&quot; height=&quot;2736&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_jZCwr0Tj0c5eMqey-57034bb6.CeBmoS6M_1iF5II.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Alenka Skvarc on Unsplash&lt;/p&gt;
&lt;p&gt;We hope you are relaxed and enjoying your holiday period. We really do. So it may seem ironic that this blog post is about being in a hurry. Kind of. Let me explain myself:&lt;/p&gt;
&lt;p&gt;Apart from the kind of hurry you may experience when you are afraid of missing a train, or the oppressive feeling of fearing not meeting a deadline, we are very familiar with another type of hurry: the one caused by slow code.&lt;/p&gt;
&lt;p&gt;Did you experience this? We certainly do. And our engineers proposed some solutions too. Using more efficient programming languages, or letting your graphical processing unit (GPU) do the hard work, are classical solutions for these problems.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/writing-testable-gpu-code-23bbda3a5d62&quot;&gt;&lt;strong&gt;Writing testable GPU code&lt;/strong&gt;&lt;/a&gt;, by &lt;a href=&quot;https://medium.com/@benvanwerkhoven&quot;&gt;Ben van Werkhoven&lt;/a&gt;, reminds us that using GPU programming is no excuse for abandoning best practices. In particular, it is very advisable to use unit tests. Here he teaches us how.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/c-compile-time-exceptions-5443f5bf06fe&quot;&gt;&lt;strong&gt;C++ Compile-Time exceptions&lt;/strong&gt;&lt;/a&gt;, by &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;, sheds some light on the notoriously obscure topic of templates in C++ and their cryptic error messages. Couldn’t these messages be more readable? Patrick says yes, and shows us how.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/why-use-an-fpga-instead-of-a-cpu-or-gpu-b234cd4f309c&quot;&gt;&lt;strong&gt;Why use an FPGA instead of a CPU or GPU?&lt;/strong&gt;&lt;/a&gt;, by our former colleague &lt;a href=&quot;https://medium.com/@atzeus&quot;&gt;Atze van der Ploeg&lt;/a&gt;, delves into something some of us software engineers tend to forget: the hardware side of things.&lt;/p&gt;
&lt;p&gt;What about you? Do you have something to share? If that’s the case, feel free to use the comments section below. But, if you want to enjoy a hurry-less summer, feel more than free to wait until September.&lt;/p&gt;</description><pubDate>Tue, 16 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Does your code need a performance boost? Ask us!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3648&quot; height=&quot;2736&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_jZCwr0Tj0c5eMqey-57034bb6.CeBmoS6M_1iF5II.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Alenka Skvarc on Unsplash&lt;/p&gt;
&lt;p&gt;We hope you are relaxed and enjoying your holiday period. We really do. So it may seem ironic that this blog post is about being in a hurry. Kind of. Let me explain myself:&lt;/p&gt;
&lt;p&gt;Apart from the kind of hurry you may experience when you are afraid of missing a train, or the oppressive feeling of fearing not meeting a deadline, we are very familiar with another type of hurry: the one caused by slow code.&lt;/p&gt;
&lt;p&gt;Did you experience this? We certainly do. And our engineers proposed some solutions too. Using more efficient programming languages, or letting your graphical processing unit (GPU) do the hard work, are classical solutions for these problems.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/writing-testable-gpu-code-23bbda3a5d62&quot;&gt;&lt;strong&gt;Writing testable GPU code&lt;/strong&gt;&lt;/a&gt;, by &lt;a href=&quot;https://medium.com/@benvanwerkhoven&quot;&gt;Ben van Werkhoven&lt;/a&gt;, reminds us that using GPU programming is no excuse for abandoning best practices. In particular, it is very advisable to use unit tests. Here he teaches us how.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/c-compile-time-exceptions-5443f5bf06fe&quot;&gt;&lt;strong&gt;C++ Compile-Time exceptions&lt;/strong&gt;&lt;/a&gt;, by &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;, sheds some light on the notoriously obscure topic of templates in C++ and their cryptic error messages. Couldn’t these messages be more readable? Patrick says yes, and shows us how.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/why-use-an-fpga-instead-of-a-cpu-or-gpu-b234cd4f309c&quot;&gt;&lt;strong&gt;Why use an FPGA instead of a CPU or GPU?&lt;/strong&gt;&lt;/a&gt;, by our former colleague &lt;a href=&quot;https://medium.com/@atzeus&quot;&gt;Atze van der Ploeg&lt;/a&gt;, delves into something some of us software engineers tend to forget: the hardware side of things.&lt;/p&gt;
&lt;p&gt;What about you? Do you have something to share? If that’s the case, feel free to use the comments section below. But, if you want to enjoy a hurry-less summer, feel more than free to wait until September.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_jZCwr0Tj0c5eMqey-57034bb6.CeBmoS6M.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>Our favourite Python tools for research</title><link>https://blog2.esciencecenter.nl/posts/2022-08-02---our-favourite-python-tools-for-research</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-08-02---our-favourite-python-tools-for-research</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_YDHFYKPphLmLq5Fz-9e75541a.DWQzJMUX_1zFoKJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Ethan Robertson on Unsplash&lt;/p&gt;
&lt;p&gt;Ah, summer. A time to relax, go on holiday, and learn new things. At the eScience Center, we love summer. And we love Python. So, for summer, we’ve put together our most popular blogs on favourite Python tools that our (former) engineers either worked on, or use a lot. We hope you enjoy this curated list!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/jump-start-your-python-project-with-this-template-ef52e6c1a2dc&quot;&gt;&lt;strong&gt;Jump start your Python project with this template&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@j.vanderzwaan&quot;&gt;Janneke van der Zwaan&lt;/a&gt;, talks about the Python project template developed at the eScience Center. This template helps beginners to get started, and advanced Python users to save time. And who doesn’t love saving time?!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/parallel-programming-in-python-7fd62c90217d&quot;&gt;&lt;strong&gt;Parallel programming in Python&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@jhidding&quot;&gt;Johan Hidding&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@pab.rod&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt;. Have you ever been in a hurry to complete an analysis, but did it take very long to run? In this step-by-step tutorial Johan and Pablo show you how to call in all of your processors for help.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/forget-about-jupyter-notebooks-showcase-your-research-using-dashboards-5d13451ba374&quot;&gt;&lt;strong&gt;Forget about Jupyter Notebooks — showcase your research using Dashboards&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@stefsmeets&quot;&gt;Stef Smeets&lt;/a&gt;. The title says it all — if you’re looking for a different and interesting way to present your research, consider using dashboards. You’ll find it surprisingly easy with Stef’s tutorial.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/irregular-data-in-pandas-using-c-88ce311cb9ef&quot;&gt;&lt;strong&gt;Loading irregular data into Pandas using C++&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;. Who doesn’t love Pandas? Well, quite a few people, because it loads data slowly. But you can make it faster! Check out how in this post.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/testing-shell-commands-from-python-2a2ec87ebf71&quot;&gt;&lt;strong&gt;Testing shell commands from Python&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@j.vanderzwaan&quot;&gt;Janneke van der Zwaan&lt;/a&gt;. Do you ever need to test shell commands, but find it fiddly and annoying? Janneke found a solution in Python that works well, maybe it works well for you too!&lt;/p&gt;
&lt;p&gt;And what about you? What’s your favourite Python tool? Let us know in the comments below and, most importantly, enjoy your summer.&lt;/p&gt;</description><pubDate>Tue, 02 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_YDHFYKPphLmLq5Fz-9e75541a.DWQzJMUX_1zFoKJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Ethan Robertson on Unsplash&lt;/p&gt;
&lt;p&gt;Ah, summer. A time to relax, go on holiday, and learn new things. At the eScience Center, we love summer. And we love Python. So, for summer, we’ve put together our most popular blogs on favourite Python tools that our (former) engineers either worked on, or use a lot. We hope you enjoy this curated list!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/jump-start-your-python-project-with-this-template-ef52e6c1a2dc&quot;&gt;&lt;strong&gt;Jump start your Python project with this template&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@j.vanderzwaan&quot;&gt;Janneke van der Zwaan&lt;/a&gt;, talks about the Python project template developed at the eScience Center. This template helps beginners to get started, and advanced Python users to save time. And who doesn’t love saving time?!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/parallel-programming-in-python-7fd62c90217d&quot;&gt;&lt;strong&gt;Parallel programming in Python&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@jhidding&quot;&gt;Johan Hidding&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@pab.rod&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt;. Have you ever been in a hurry to complete an analysis, but did it take very long to run? In this step-by-step tutorial Johan and Pablo show you how to call in all of your processors for help.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/forget-about-jupyter-notebooks-showcase-your-research-using-dashboards-5d13451ba374&quot;&gt;&lt;strong&gt;Forget about Jupyter Notebooks — showcase your research using Dashboards&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@stefsmeets&quot;&gt;Stef Smeets&lt;/a&gt;. The title says it all — if you’re looking for a different and interesting way to present your research, consider using dashboards. You’ll find it surprisingly easy with Stef’s tutorial.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/irregular-data-in-pandas-using-c-88ce311cb9ef&quot;&gt;&lt;strong&gt;Loading irregular data into Pandas using C++&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;. Who doesn’t love Pandas? Well, quite a few people, because it loads data slowly. But you can make it faster! Check out how in this post.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.esciencecenter.nl/testing-shell-commands-from-python-2a2ec87ebf71&quot;&gt;&lt;strong&gt;Testing shell commands from Python&lt;/strong&gt;&lt;/a&gt; by &lt;a href=&quot;https://medium.com/@j.vanderzwaan&quot;&gt;Janneke van der Zwaan&lt;/a&gt;. Do you ever need to test shell commands, but find it fiddly and annoying? Janneke found a solution in Python that works well, maybe it works well for you too!&lt;/p&gt;
&lt;p&gt;And what about you? What’s your favourite Python tool? Let us know in the comments below and, most importantly, enjoy your summer.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_YDHFYKPphLmLq5Fz-9e75541a.DWQzJMUX.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>Mimicking Intelligence: AI imitation crisis</title><link>https://blog2.esciencecenter.nl/posts/2022-07-22---mimicking-intelligence-ai-imitation-crisis</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-07-22---mimicking-intelligence-ai-imitation-crisis</guid><description>&lt;h2 id=&quot;the-next-generation-language-models-will-still-just-be-enormeous-parrot-systems-that-imitate-intelligent-behavior-but-they-will-feel-like-much-more-to-us&quot;&gt;The next generation language models will still just be enormeous parrot-systems that imitate intelligent behavior. But they will &lt;em&gt;feel&lt;/em&gt; like much more to us.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Jun 24, 2022&lt;/p&gt;
&lt;p&gt;Philosophically and legally they will remain things. But at some point in the not too far future many people will simply not perceive them as things anymore**. People might make “friends” with an AI (just as Blake Lemoine said he did, at least if we assume this is not all a big media stunt). People might listen to “their AI”. And many people will be tricked by an AI.&lt;/p&gt;
&lt;h3 id=&quot;shifting-societal-rules-and-foundations&quot;&gt;Shifting societal rules and foundations&lt;/h3&gt;
&lt;p&gt;Having emotional bonds to things is nothing new. People are tied to an old stuffed animal, to a toy, to things that carry important memories. Next generation language models are very unlike those things. They can “talk” to you, they can have an “opinion” that is radically different from yours. And, not to forget, they are designed, trained, and controlled by powerfull companies (now) or by any group with the necessary technical skills and requirements (but generally not by you).&lt;/p&gt;
&lt;p&gt;Plus, they can come in disguise. If you talk to your old teddy bear than at least you know (I hope) that you are just talking to an imaginary being. But next level chat bots might run undercover. Either actualy pretending to be a human being (which even for the big tech companies should be a total no-go), or by pretending to be more than a thing, but to be actually alive (that’s what LaMDA seems to do).&lt;/p&gt;
&lt;p&gt;In the last decade we have experienced how digital technologies can be used for good and for bad. We have seen how technologies can be used to connect and to help people, but also to manipulate. Manipulation of media is nothing new, but the level to which media can be generated and manipulated has changed very rapidly. To make it a bit drastic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can (soon?) no longer trust images, be it generated faces or deep learning generated artworks (see &lt;a href=&quot;https://openai.com/dall-e-2/&quot;&gt;Dall-e&lt;/a&gt; or &lt;a href=&quot;https://parti.research.google/&quot;&gt;parti&lt;/a&gt; for recent, very impressive examples)&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust audio because models can transfer the sound of any person (given enough material).&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust video footage (deep fakes, see &lt;a href=&quot;https://www.niemanlab.org/2018/12/fighting-the-reality-of-deepfakes/&quot;&gt;for instance here&lt;/a&gt; or &lt;a href=&quot;https://medium.com/@gxrdwtsv/are-we-living-in-a-post-truth-world-c6e0820e656d&quot;&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;And as I wrote above: We can (soon?) no longer trust chat conversations (see LaMDA).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sure, all of those things bring a lot of fun use cases, sometimes even really usefull ones. But there might be a very high price to pay for this.&lt;/p&gt;
&lt;p&gt;It probably still takes a while before experts with a deeper (haha, great pun) understanding of deep learning will be fully tricked by the imitation game. But at least in a normal chat situation most people will not easily realize they are talking to a “language model”. People like Blake Lemoine for instance. And many others will follow his example, not in the same religious way, but they will simply not notice that the online sales person or the online booking assistant is no longer a human being.&lt;/p&gt;
&lt;p&gt;Do you still wonder why this is an issue? &lt;strong&gt;Better a nice chat bot than a stupid one, right?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OK, then imagine you landed on a scam dating site.
Or start to imagine what people could do which hacked devices of friends or family.
Obviously those AI’s can write you better scam attempts that what we are currently used to (current level: “Hi mother, it’s your son and I need money”*). And hey, what if they also call you and sound like the real person?&lt;/p&gt;
&lt;p&gt;I bet most people are not yet used to asking control questions during phone calls. Like: what drink did we have last week in the bar? What was the name of my first cat? Have to talked to Anthony recently? (I don’t know any Anthony)&lt;/p&gt;
&lt;p&gt;Sounds silly I know. But maybe we soon have to start practicing…&lt;/p&gt;
&lt;h3 id=&quot;further-references&quot;&gt;Further references:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you haven’t done this already I can recommend to “talk to an AI” just to see and learn how this feels. LaMDA is not available for people outside Google. But GPT-3 is, maybe a little less impressive, but still made huge headlines two years ago. You can get a free open AI access to use their “playground” and have a chat: &lt;a href=&quot;https://beta.openai.com/playground/p/default-chat&quot;&gt;https://beta.openai.com/playground/p/default-chat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Once you get a hang of it, GPT-3 can easily be tricked. See for instance material from Gary Marcus, or &lt;a href=&quot;https://www.youtube.com/watch?v=iccd86vOz3w&quot;&gt;youtube video here&lt;/a&gt;. It doesn’t have an understanding of the world and that can easily be tested. LaMDA might do the imitation game a bit better, but we will have to see…&lt;/li&gt;
&lt;li&gt;Perspective on artificial intelligence by Yann LeCun and Jacob Browning: &lt;a href=&quot;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&quot;&gt;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Fri, 22 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-next-generation-language-models-will-still-just-be-enormeous-parrot-systems-that-imitate-intelligent-behavior-but-they-will-feel-like-much-more-to-us&quot;&gt;The next generation language models will still just be enormeous parrot-systems that imitate intelligent behavior. But they will &lt;em&gt;feel&lt;/em&gt; like much more to us.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Jun 24, 2022&lt;/p&gt;
&lt;p&gt;Philosophically and legally they will remain things. But at some point in the not too far future many people will simply not perceive them as things anymore**. People might make “friends” with an AI (just as Blake Lemoine said he did, at least if we assume this is not all a big media stunt). People might listen to “their AI”. And many people will be tricked by an AI.&lt;/p&gt;
&lt;h3 id=&quot;shifting-societal-rules-and-foundations&quot;&gt;Shifting societal rules and foundations&lt;/h3&gt;
&lt;p&gt;Having emotional bonds to things is nothing new. People are tied to an old stuffed animal, to a toy, to things that carry important memories. Next generation language models are very unlike those things. They can “talk” to you, they can have an “opinion” that is radically different from yours. And, not to forget, they are designed, trained, and controlled by powerfull companies (now) or by any group with the necessary technical skills and requirements (but generally not by you).&lt;/p&gt;
&lt;p&gt;Plus, they can come in disguise. If you talk to your old teddy bear than at least you know (I hope) that you are just talking to an imaginary being. But next level chat bots might run undercover. Either actualy pretending to be a human being (which even for the big tech companies should be a total no-go), or by pretending to be more than a thing, but to be actually alive (that’s what LaMDA seems to do).&lt;/p&gt;
&lt;p&gt;In the last decade we have experienced how digital technologies can be used for good and for bad. We have seen how technologies can be used to connect and to help people, but also to manipulate. Manipulation of media is nothing new, but the level to which media can be generated and manipulated has changed very rapidly. To make it a bit drastic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can (soon?) no longer trust images, be it generated faces or deep learning generated artworks (see &lt;a href=&quot;https://openai.com/dall-e-2/&quot;&gt;Dall-e&lt;/a&gt; or &lt;a href=&quot;https://parti.research.google/&quot;&gt;parti&lt;/a&gt; for recent, very impressive examples)&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust audio because models can transfer the sound of any person (given enough material).&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust video footage (deep fakes, see &lt;a href=&quot;https://www.niemanlab.org/2018/12/fighting-the-reality-of-deepfakes/&quot;&gt;for instance here&lt;/a&gt; or &lt;a href=&quot;https://medium.com/@gxrdwtsv/are-we-living-in-a-post-truth-world-c6e0820e656d&quot;&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;And as I wrote above: We can (soon?) no longer trust chat conversations (see LaMDA).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sure, all of those things bring a lot of fun use cases, sometimes even really usefull ones. But there might be a very high price to pay for this.&lt;/p&gt;
&lt;p&gt;It probably still takes a while before experts with a deeper (haha, great pun) understanding of deep learning will be fully tricked by the imitation game. But at least in a normal chat situation most people will not easily realize they are talking to a “language model”. People like Blake Lemoine for instance. And many others will follow his example, not in the same religious way, but they will simply not notice that the online sales person or the online booking assistant is no longer a human being.&lt;/p&gt;
&lt;p&gt;Do you still wonder why this is an issue? &lt;strong&gt;Better a nice chat bot than a stupid one, right?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OK, then imagine you landed on a scam dating site.
Or start to imagine what people could do which hacked devices of friends or family.
Obviously those AI’s can write you better scam attempts that what we are currently used to (current level: “Hi mother, it’s your son and I need money”*). And hey, what if they also call you and sound like the real person?&lt;/p&gt;
&lt;p&gt;I bet most people are not yet used to asking control questions during phone calls. Like: what drink did we have last week in the bar? What was the name of my first cat? Have to talked to Anthony recently? (I don’t know any Anthony)&lt;/p&gt;
&lt;p&gt;Sounds silly I know. But maybe we soon have to start practicing…&lt;/p&gt;
&lt;h3 id=&quot;further-references&quot;&gt;Further references:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you haven’t done this already I can recommend to “talk to an AI” just to see and learn how this feels. LaMDA is not available for people outside Google. But GPT-3 is, maybe a little less impressive, but still made huge headlines two years ago. You can get a free open AI access to use their “playground” and have a chat: &lt;a href=&quot;https://beta.openai.com/playground/p/default-chat&quot;&gt;https://beta.openai.com/playground/p/default-chat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Once you get a hang of it, GPT-3 can easily be tricked. See for instance material from Gary Marcus, or &lt;a href=&quot;https://www.youtube.com/watch?v=iccd86vOz3w&quot;&gt;youtube video here&lt;/a&gt;. It doesn’t have an understanding of the world and that can easily be tested. LaMDA might do the imitation game a bit better, but we will have to see…&lt;/li&gt;
&lt;li&gt;Perspective on artificial intelligence by Yann LeCun and Jacob Browning: &lt;a href=&quot;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&quot;&gt;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>Florian Huber</author></item><item><title>What do entropy, entanglement, cosmology, life, and fake news have in common?</title><link>https://blog2.esciencecenter.nl/posts/2022-07-19---what-do-entropy-entanglement-cosmology-life-and-fake-news-ha</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-07-19---what-do-entropy-entanglement-cosmology-life-and-fake-news-ha</guid><description>&lt;h2 id=&quot;report-on-the-information-universe-4-conference&quot;&gt;Report on the Information Universe 4 conference&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;(Answer to the above question below obligatory excruciatingly long-winded intro!)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the past week, I have rediscovered writing. Writing really hurts, you know… I’m pretty sure there should be workplace regulations for pen and paper safety, with regular mandatory hand massages against cramps and such.&lt;/p&gt;
&lt;p&gt;I guess my hand injuries came from overuse, because I filled up two entire notepads with my notes on all the talks at the &lt;a href=&quot;https://informationuniverse.astro.rug.nl/2022&quot;&gt;Information Universe 4&lt;/a&gt; conference.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;687&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_f0wzoo1aElRAGFM7raSpdQ-31db1055.CS22EY-x_Z4sCje.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;My trusty notepads! As a professional pen-athlete, I should probably have gone with pro materials, though. Moleskine or other brands. Please contact my manager if you want to sponsor my next note-taking event!&lt;/p&gt;
&lt;p&gt;This perhaps seemingly (over)eagerness had two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I had to write in the dark, so I was struggling to keep words and lines separated.&lt;/li&gt;
&lt;li&gt;I really wanted to understand everything, since I had promised my colleague, Hanno, I would report on this conference, so there was a lot to write about.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, here it is, Hanno! I hope it’ll convince you (and others) to join the next edition, because it was really a joy.&lt;/p&gt;
&lt;h2 id=&quot;information&quot;&gt;Information!&lt;/h2&gt;
&lt;p&gt;So, as I asked in the title, &lt;em&gt;what do entropy, entanglement, cosmology, life, and fake news have in common?&lt;/em&gt; The answer is: &lt;strong&gt;information&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“What do you mean, information?”&lt;/em&gt;, you may demand sternly. This was also the topic of many Q&amp;#x26;A sessions and coffee breaks. Two main definitions seem to be those of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;context-free information in the information theoretical and/or statistical sense; and&lt;/li&gt;
&lt;li&gt;something like “meaning” and communication of meaning.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To communicate meaning, you need some encoding scheme of information (like an alphabet), and a commonly understood standard (like a language). This is probably what most people think of when they talk about information: stuff you can read about, knowledge.&lt;/p&gt;
&lt;p&gt;However, the underlying truth that you’re trying to communicate about is there independent of your messages. Such truths for instance describe the exact state of a bunch of molecules at a certain time: where they are, how fast they move, in what directions, what type of molecules they are, etc., etc.&lt;/p&gt;
&lt;p&gt;Buckets (or canisters, or tubs, or vast intergalactic expanses) of molecules are typically described by statistical physics and thermodynamics, but the kind of statistical description about states of things can be generalized to anything. The unit of information of this kind is the bit.&lt;/p&gt;
&lt;h2 id=&quot;the-fundamental-building-block-of-the-universe&quot;&gt;The fundamental building block of the Universe?&lt;/h2&gt;
&lt;p&gt;Now, when you write down the equations of how all this information builds up in a system you get something called &lt;a href=&quot;https://en.wikipedia.org/wiki/Entropy_(information_theory)&quot;&gt;&lt;em&gt;Shannon entropy&lt;/em&gt;&lt;/a&gt;. To be honest, I’m not sure whether I like the word “information” in this context, because it’s actually more about probability. &lt;a href=&quot;https://en.wikipedia.org/wiki/Information_content&quot;&gt;&lt;em&gt;Surprisal&lt;/em&gt;&lt;/a&gt; seems like a much better word to me. But I digress.&lt;/p&gt;
&lt;p&gt;It turns out that there are several ways information entropy can describe our Universe in ways that solve some of the biggest problems in cosmological physics: these theories naturally unify gravity and quantum physics and explain the mysteries of Dark Matter and Dark Energy.&lt;/p&gt;
&lt;p&gt;At the conference two such theories were presented and discussed:&lt;/p&gt;
&lt;h3 id=&quot;entropic-gravity&quot;&gt;Entropic gravity&lt;/h3&gt;
&lt;p&gt;The theory of &lt;a href=&quot;https://en.wikipedia.org/wiki/Entropic_gravity&quot;&gt;entropic or emergent gravity&lt;/a&gt; by Erik Verlinde and collaborators, in a little over a decade, seems to have moved from wild theoretical speculation into the realm of serious possibility. In several talks, &lt;strong&gt;observational tests&lt;/strong&gt; were discussed that interestingly seem to match old alternative theories of gravity like MOND as well.&lt;/p&gt;
&lt;p&gt;Also super interesting was new work by &lt;strong&gt;Manus Visser&lt;/strong&gt; on how even Newton’s first and second laws (that describe mass inertia and how anything moves at all) can be explained from entropic principles!&lt;/p&gt;
&lt;p&gt;The math was beyond me, honestly, which is a problem with all of entropic gravity, being based on the information entropy of the entanglement of primordial particles on (or beyond?) opposite parts of the horizon of some kind of anti-de Sitter (AdS) space that supposedly corresponds to our own (conformal space? CF) Universe by means of &lt;a href=&quot;https://en.wikipedia.org/wiki/AdS/CFT_correspondence&quot;&gt;AdS/CFT correspondence&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;607&quot; height=&quot;341&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_m3Y7nx8w5CXl6A4k-eec512af.B4RdecMU_1Qzu52.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;No, really, I’m asking: am I right?&lt;/p&gt;
&lt;p&gt;Still, the predictions are impressive, elegant, enticing and certainly warrant further attention.&lt;/p&gt;
&lt;h3 id=&quot;wolframs-physics-project&quot;&gt;Wolfram’s Physics project&lt;/h3&gt;
&lt;p&gt;Stephen Wolfram (yes, the Mathematica guy) presented the &lt;a href=&quot;https://www.wolframphysics.org/&quot;&gt;Wolfram theory of physics&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Wolfram Universe starts from a description of space itself as a graph of “space-element” nodes connected to other nodes. Updates to the cells and connections in this graph — representing the passing of time — can be made according to certain rules. Such cell update schemes were inspired by &lt;a href=&quot;https://en.wikipedia.org/wiki/Cellular_automaton&quot;&gt;cellular automata&lt;/a&gt; (which you can very nicely simulate in Mathematica, try it today!).&lt;/p&gt;
&lt;p&gt;Wolfram claimed (I wouldn’t say explained, although I’m sure they try on their website) that when you make this graph big enough and use the right set of update rules, you again get an emergent theory of physics.&lt;/p&gt;
&lt;p&gt;The most interesting part of his talk was that he had some very specific &lt;strong&gt;predictions for things that could be observed&lt;/strong&gt; if indeed we live in a Wolfram Universe (did you try Mathematica yet btw? great product…). One was that the 3-dimensional nature of the spacetime we experience isn’t necessarily fixed in the Wolfriverse and we could observe flashes of other-dimensionality somehow. Another thing would be a specific radiation pattern from near the event horizon of a black hole.&lt;/p&gt;
&lt;h2 id=&quot;new-cosmological-probes-and-the-hubble-tension&quot;&gt;New cosmological probes and the “Hubble tension”&lt;/h2&gt;
&lt;p&gt;As you may have noticed from the above, my interest piques when information universe theorists start thinking about observability. Theory should be about our actual Universe and it should be falsifiable by observational or experimental probes and tests. Luckily, the conference provided in this area as well.&lt;/p&gt;
&lt;h3 id=&quot;new-observations&quot;&gt;New observations&lt;/h3&gt;
&lt;p&gt;Henk Hoekstra gave a great overview of the Euclid project, which combines a (hopefully soon to be launched) space telescope with ground-based telescope observations to create a new, high resolution map of all the stuff in our local corner of the Universe. “ &lt;em&gt;All the stuff&lt;/em&gt; ” includes dark matter. Of course, we cannot &lt;strong&gt;see&lt;/strong&gt; that &lt;em&gt;stuff&lt;/em&gt; (hence the name), but using intricate statistical modeling of tiny distortions of light by the gravity of the &lt;em&gt;stuff&lt;/em&gt; — a phenomenon known as (weak) gravitational lensing — we can deduce where it’s located.&lt;/p&gt;
&lt;p&gt;Knowing that is really important for understanding all the processes going on and the objects and structures that we see in our neighborhood. Without this knowledge, we simply cannot test our theories.&lt;/p&gt;
&lt;h3 id=&quot;a-new-probe-strong-gravitational-lensing-of-transients&quot;&gt;A new probe: strong gravitational lensing of transients&lt;/h3&gt;
&lt;p&gt;A related promising new idea is to use strong gravitational lensing of quasars and even supernovae.&lt;/p&gt;
&lt;p&gt;To understand strong lensing, take a look at a light source through the bottom of a wine glass:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;943&quot; height=&quot;438&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Lz8LuSIrVwhxRN6i-227f25ea.BUkwwJbB_ZdGCVN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Left: DIY strong gravitational lensing. Right: natural lensing by a big galaxy cluster (center) of a background object (blue arcs). From &lt;a href=&quot;https://laser.physics.sunysb.edu/%5C_samantha/journal/index.html&quot;&gt;https://laser.physics.sunysb.edu/\_samantha/journal/index.html&lt;/a&gt;, by Samantha Scibelli.&lt;/p&gt;
&lt;p&gt;The light of an object is bent around a heavy foreground object from multiple sides, giving us two (or more) views on a single background object! The light from those two images travelled along different paths, with different distances.&lt;/p&gt;
&lt;p&gt;Now, quasars and supernovae are both &lt;em&gt;transients&lt;/em&gt;: objects that change color or brightness over time. If their light travels different distances, we can measure their time-dependent light pattern twice (or more). The punchline is that the differences in the light patterns from the multiple images can tell us something about the Universe! By travelling different distances, or travelling through different environments, their patterns will often be slightly different.&lt;/p&gt;
&lt;p&gt;Kind of a long story, but the bottom line is that this is really promising as a completely &lt;strong&gt;new probe&lt;/strong&gt; of the physics of our Universe, one that is &lt;strong&gt;independent of other observational probes&lt;/strong&gt; we have used up to now.&lt;/p&gt;
&lt;p&gt;Why is that important?&lt;/p&gt;
&lt;h3 id=&quot;the-hubble-tension&quot;&gt;The Hubble tension&lt;/h3&gt;
&lt;p&gt;There’s a fight!&lt;/p&gt;
&lt;p&gt;One of the most important cosmological parameters that describe our Universe as a whole is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hubble%27s_law&quot;&gt;Hubble constant&lt;/a&gt;. This constant can be measured in several ways. Simplifying a bit, we can say that there are two classes of observations: those from the &lt;em&gt;early-time universe&lt;/em&gt; (most prominently: the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cosmic_microwave_background&quot;&gt;cosmic microwave background&lt;/a&gt; (CMB), popularly described as the echo of the Big Bang) and those from the &lt;em&gt;late-time universe&lt;/em&gt; (now and just a few billion years ago, e.g. supernova distances).&lt;/p&gt;
&lt;p&gt;For years, different Hubble constant measurements seemed to be converging to a single value (within the error margins). However, with measurements becoming more and more precise (error margins becoming smaller), it now turns out that CMB measurements do not agree at all with late-time measurements!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OKk2JYML7HLFAjzVejBH0Q-32f1b2d9.DKv1LcnB_Z2iUaWz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This so-called &lt;strong&gt;“Hubble tension”&lt;/strong&gt; has grown over the last decade into a serious crisis. Obviously, scientists love a good crisis, because it means that there’s something new to learn just lurking beyond the horizon! The talks by Leon Koopmans, Tamara Davis and Nikki Arendse provided many perspectives on this issue, but no solution has been found yet.&lt;/p&gt;
&lt;p&gt;Improving our understanding of our surroundings in the ways presented by e.g. Job Feldbrugge (who uses analytical models to simplify and better understand the complex universe around us) and Yan-Chuan Cai (who improves modelling of one of the most essential astronomical tools: the redshift as used to estimate distances to objects) will certainly play a role as well.&lt;/p&gt;
&lt;h2 id=&quot;life-fake-news-philosophy-and-more&quot;&gt;Life, fake news, philosophy and more&lt;/h2&gt;
&lt;p&gt;So far, I’ve only highlighted more or less a third of this conference. The joy of this conference, though, is that not only are we (astro)physicists infused with information theory, but we get to sample from a wide buffet of fields that use information theory in some way too. To be able to have so many world experts in different fields in one place must lead to some really cool cross-domain thoughts and ideas. And it did. Some random highlights:&lt;/p&gt;
&lt;h3 id=&quot;philosophy&quot;&gt;Philosophy&lt;/h3&gt;
&lt;p&gt;Seth Lloyd talked about how Spinoza’s ethics is very suitable for thinking about how we can define ethically “good” computation. This was a really interesting talk from one of the founders of quantum computing. &lt;strong&gt;“Should we fear&lt;/strong&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Artificial_general_intelligence&quot;&gt;&lt;strong&gt;artificial general intelligence&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(AGI)?”&lt;/strong&gt; was one of his leading questions. Based on Spinoza, Lloyd argued that because…&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;joy comes from increasing one’s understanding of the Universe (or God, which is the same to him) and&lt;/li&gt;
&lt;li&gt;individuals can never understand more on their own than together&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;…it will be in any intelligence’s interest to cooperate. This goes for us humans, when we work together, but also goes for AGI and anything in between that allows us to increase our intelligence (tools like books, computers, AI, etc.). So: no, we needn’t fear AGI at all… at least, as long as they are Spinozans.&lt;/p&gt;
&lt;p&gt;One interesting random cross-connection from this talk is that Wolfram’s set of all the possible update rules — a concept they call the &lt;a href=&quot;https://writings.stephenwolfram.com/2021/11/the-concept-of-the-ruliad/&quot;&gt;Ruliad&lt;/a&gt;, and which describes all possible Universes — was described in a very similar way to Spinoza’s God. Maybe the similarity is just due to the nature of things that explain everything always everywhere, though.&lt;/p&gt;
&lt;h3 id=&quot;life&quot;&gt;Life&lt;/h3&gt;
&lt;p&gt;Some speakers discussed what life is, whether we should define it at all, how it could have come about, and also how it connects to things like AGI. The talks ranged from quite generic and understandable to very technical, like the talk by David Eric Smith.&lt;/p&gt;
&lt;p&gt;Although it was challenging for me to follow due to lots of jargon, Smith argued convincingly, based on (micro)biological evidence, that ribosomes, the molecules that fold proteins out of RNA, must have come before the actual RNA/DNA that would become the basic information carrier of all life as we know it.&lt;/p&gt;
&lt;p&gt;Digging into this chain of events on how life could have started is a fascinating feat of micro-archaeology, if one may call it that… And one may, if one is to follow the definition of life that Charley Lineweaver gives. He states that essentially biology is a &lt;strong&gt;historical&lt;/strong&gt; science. All other definitions of life are problematic and may exclude things like viruses and even humans (we need to eat; how self-sustaining are we?) or include such things as tornados and stars (“systems far from equilibrium”). The study of life is simply a study of how some subset of things we call “living” happened to come about. He contrasts this to physics which tries to uncover time-invariant truths about reality.&lt;/p&gt;
&lt;h3 id=&quot;fake-news&quot;&gt;Fake news&lt;/h3&gt;
&lt;p&gt;Finally, one talk that really hit home for me was the one by Ruurd Oosterwoud on countering disinformation using evidence-based, data-driven solutions.&lt;/p&gt;
&lt;p&gt;Using such solutions may seem like the obvious thing to do, but unfortunately, politically driven solutions often are far from effective. This is no big surprise, because many simply have not been rigorously tested at all. The problem we face is hugely complex, though, with many different actors through many different media with many different motivations and stakes.&lt;/p&gt;
&lt;p&gt;Solutions like fact-checking create merely a ripple in the huge lake of false information that floods us from all sides. And this doesn’t even include yet aspects like intent: do people truly believe what they say or are they actively trying to disrupt any fact-based discussion?&lt;/p&gt;
&lt;p&gt;Oosterwoud presented a number of ways in which we can actually start measuring what works and what doesn’t. One cool example was a website where school children were given the assignment to come up with a fake news item themselves and get as many visitors to it as possible. This gives both the children themselves and researchers insights into successful tactics, which may eventually lead to counter-strategies that actually work.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You really missed out Hanno!&lt;/p&gt;
&lt;p&gt;Apart from the content and the great discussions over coffee, the conference was held in the DOT full-dome planetarium. Some of the speakers made use of this to show some beautiful full-dome movies or interactive shows.&lt;/p&gt;
&lt;p&gt;It’s one of the most inspiring conferences for technically inclined, but broadly interested people.&lt;/p&gt;</description><pubDate>Tue, 19 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;report-on-the-information-universe-4-conference&quot;&gt;Report on the Information Universe 4 conference&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;(Answer to the above question below obligatory excruciatingly long-winded intro!)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the past week, I have rediscovered writing. Writing really hurts, you know… I’m pretty sure there should be workplace regulations for pen and paper safety, with regular mandatory hand massages against cramps and such.&lt;/p&gt;
&lt;p&gt;I guess my hand injuries came from overuse, because I filled up two entire notepads with my notes on all the talks at the &lt;a href=&quot;https://informationuniverse.astro.rug.nl/2022&quot;&gt;Information Universe 4&lt;/a&gt; conference.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;687&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_f0wzoo1aElRAGFM7raSpdQ-31db1055.CS22EY-x_Z4sCje.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;My trusty notepads! As a professional pen-athlete, I should probably have gone with pro materials, though. Moleskine or other brands. Please contact my manager if you want to sponsor my next note-taking event!&lt;/p&gt;
&lt;p&gt;This perhaps seemingly (over)eagerness had two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I had to write in the dark, so I was struggling to keep words and lines separated.&lt;/li&gt;
&lt;li&gt;I really wanted to understand everything, since I had promised my colleague, Hanno, I would report on this conference, so there was a lot to write about.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, here it is, Hanno! I hope it’ll convince you (and others) to join the next edition, because it was really a joy.&lt;/p&gt;
&lt;h2 id=&quot;information&quot;&gt;Information!&lt;/h2&gt;
&lt;p&gt;So, as I asked in the title, &lt;em&gt;what do entropy, entanglement, cosmology, life, and fake news have in common?&lt;/em&gt; The answer is: &lt;strong&gt;information&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“What do you mean, information?”&lt;/em&gt;, you may demand sternly. This was also the topic of many Q&amp;#x26;A sessions and coffee breaks. Two main definitions seem to be those of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;context-free information in the information theoretical and/or statistical sense; and&lt;/li&gt;
&lt;li&gt;something like “meaning” and communication of meaning.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To communicate meaning, you need some encoding scheme of information (like an alphabet), and a commonly understood standard (like a language). This is probably what most people think of when they talk about information: stuff you can read about, knowledge.&lt;/p&gt;
&lt;p&gt;However, the underlying truth that you’re trying to communicate about is there independent of your messages. Such truths for instance describe the exact state of a bunch of molecules at a certain time: where they are, how fast they move, in what directions, what type of molecules they are, etc., etc.&lt;/p&gt;
&lt;p&gt;Buckets (or canisters, or tubs, or vast intergalactic expanses) of molecules are typically described by statistical physics and thermodynamics, but the kind of statistical description about states of things can be generalized to anything. The unit of information of this kind is the bit.&lt;/p&gt;
&lt;h2 id=&quot;the-fundamental-building-block-of-the-universe&quot;&gt;The fundamental building block of the Universe?&lt;/h2&gt;
&lt;p&gt;Now, when you write down the equations of how all this information builds up in a system you get something called &lt;a href=&quot;https://en.wikipedia.org/wiki/Entropy_(information_theory)&quot;&gt;&lt;em&gt;Shannon entropy&lt;/em&gt;&lt;/a&gt;. To be honest, I’m not sure whether I like the word “information” in this context, because it’s actually more about probability. &lt;a href=&quot;https://en.wikipedia.org/wiki/Information_content&quot;&gt;&lt;em&gt;Surprisal&lt;/em&gt;&lt;/a&gt; seems like a much better word to me. But I digress.&lt;/p&gt;
&lt;p&gt;It turns out that there are several ways information entropy can describe our Universe in ways that solve some of the biggest problems in cosmological physics: these theories naturally unify gravity and quantum physics and explain the mysteries of Dark Matter and Dark Energy.&lt;/p&gt;
&lt;p&gt;At the conference two such theories were presented and discussed:&lt;/p&gt;
&lt;h3 id=&quot;entropic-gravity&quot;&gt;Entropic gravity&lt;/h3&gt;
&lt;p&gt;The theory of &lt;a href=&quot;https://en.wikipedia.org/wiki/Entropic_gravity&quot;&gt;entropic or emergent gravity&lt;/a&gt; by Erik Verlinde and collaborators, in a little over a decade, seems to have moved from wild theoretical speculation into the realm of serious possibility. In several talks, &lt;strong&gt;observational tests&lt;/strong&gt; were discussed that interestingly seem to match old alternative theories of gravity like MOND as well.&lt;/p&gt;
&lt;p&gt;Also super interesting was new work by &lt;strong&gt;Manus Visser&lt;/strong&gt; on how even Newton’s first and second laws (that describe mass inertia and how anything moves at all) can be explained from entropic principles!&lt;/p&gt;
&lt;p&gt;The math was beyond me, honestly, which is a problem with all of entropic gravity, being based on the information entropy of the entanglement of primordial particles on (or beyond?) opposite parts of the horizon of some kind of anti-de Sitter (AdS) space that supposedly corresponds to our own (conformal space? CF) Universe by means of &lt;a href=&quot;https://en.wikipedia.org/wiki/AdS/CFT_correspondence&quot;&gt;AdS/CFT correspondence&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;607&quot; height=&quot;341&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_m3Y7nx8w5CXl6A4k-eec512af.B4RdecMU_1Qzu52.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;No, really, I’m asking: am I right?&lt;/p&gt;
&lt;p&gt;Still, the predictions are impressive, elegant, enticing and certainly warrant further attention.&lt;/p&gt;
&lt;h3 id=&quot;wolframs-physics-project&quot;&gt;Wolfram’s Physics project&lt;/h3&gt;
&lt;p&gt;Stephen Wolfram (yes, the Mathematica guy) presented the &lt;a href=&quot;https://www.wolframphysics.org/&quot;&gt;Wolfram theory of physics&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Wolfram Universe starts from a description of space itself as a graph of “space-element” nodes connected to other nodes. Updates to the cells and connections in this graph — representing the passing of time — can be made according to certain rules. Such cell update schemes were inspired by &lt;a href=&quot;https://en.wikipedia.org/wiki/Cellular_automaton&quot;&gt;cellular automata&lt;/a&gt; (which you can very nicely simulate in Mathematica, try it today!).&lt;/p&gt;
&lt;p&gt;Wolfram claimed (I wouldn’t say explained, although I’m sure they try on their website) that when you make this graph big enough and use the right set of update rules, you again get an emergent theory of physics.&lt;/p&gt;
&lt;p&gt;The most interesting part of his talk was that he had some very specific &lt;strong&gt;predictions for things that could be observed&lt;/strong&gt; if indeed we live in a Wolfram Universe (did you try Mathematica yet btw? great product…). One was that the 3-dimensional nature of the spacetime we experience isn’t necessarily fixed in the Wolfriverse and we could observe flashes of other-dimensionality somehow. Another thing would be a specific radiation pattern from near the event horizon of a black hole.&lt;/p&gt;
&lt;h2 id=&quot;new-cosmological-probes-and-the-hubble-tension&quot;&gt;New cosmological probes and the “Hubble tension”&lt;/h2&gt;
&lt;p&gt;As you may have noticed from the above, my interest piques when information universe theorists start thinking about observability. Theory should be about our actual Universe and it should be falsifiable by observational or experimental probes and tests. Luckily, the conference provided in this area as well.&lt;/p&gt;
&lt;h3 id=&quot;new-observations&quot;&gt;New observations&lt;/h3&gt;
&lt;p&gt;Henk Hoekstra gave a great overview of the Euclid project, which combines a (hopefully soon to be launched) space telescope with ground-based telescope observations to create a new, high resolution map of all the stuff in our local corner of the Universe. “ &lt;em&gt;All the stuff&lt;/em&gt; ” includes dark matter. Of course, we cannot &lt;strong&gt;see&lt;/strong&gt; that &lt;em&gt;stuff&lt;/em&gt; (hence the name), but using intricate statistical modeling of tiny distortions of light by the gravity of the &lt;em&gt;stuff&lt;/em&gt; — a phenomenon known as (weak) gravitational lensing — we can deduce where it’s located.&lt;/p&gt;
&lt;p&gt;Knowing that is really important for understanding all the processes going on and the objects and structures that we see in our neighborhood. Without this knowledge, we simply cannot test our theories.&lt;/p&gt;
&lt;h3 id=&quot;a-new-probe-strong-gravitational-lensing-of-transients&quot;&gt;A new probe: strong gravitational lensing of transients&lt;/h3&gt;
&lt;p&gt;A related promising new idea is to use strong gravitational lensing of quasars and even supernovae.&lt;/p&gt;
&lt;p&gt;To understand strong lensing, take a look at a light source through the bottom of a wine glass:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;943&quot; height=&quot;438&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Lz8LuSIrVwhxRN6i-227f25ea.BUkwwJbB_ZdGCVN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Left: DIY strong gravitational lensing. Right: natural lensing by a big galaxy cluster (center) of a background object (blue arcs). From &lt;a href=&quot;https://laser.physics.sunysb.edu/%5C_samantha/journal/index.html&quot;&gt;https://laser.physics.sunysb.edu/\_samantha/journal/index.html&lt;/a&gt;, by Samantha Scibelli.&lt;/p&gt;
&lt;p&gt;The light of an object is bent around a heavy foreground object from multiple sides, giving us two (or more) views on a single background object! The light from those two images travelled along different paths, with different distances.&lt;/p&gt;
&lt;p&gt;Now, quasars and supernovae are both &lt;em&gt;transients&lt;/em&gt;: objects that change color or brightness over time. If their light travels different distances, we can measure their time-dependent light pattern twice (or more). The punchline is that the differences in the light patterns from the multiple images can tell us something about the Universe! By travelling different distances, or travelling through different environments, their patterns will often be slightly different.&lt;/p&gt;
&lt;p&gt;Kind of a long story, but the bottom line is that this is really promising as a completely &lt;strong&gt;new probe&lt;/strong&gt; of the physics of our Universe, one that is &lt;strong&gt;independent of other observational probes&lt;/strong&gt; we have used up to now.&lt;/p&gt;
&lt;p&gt;Why is that important?&lt;/p&gt;
&lt;h3 id=&quot;the-hubble-tension&quot;&gt;The Hubble tension&lt;/h3&gt;
&lt;p&gt;There’s a fight!&lt;/p&gt;
&lt;p&gt;One of the most important cosmological parameters that describe our Universe as a whole is the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hubble%27s_law&quot;&gt;Hubble constant&lt;/a&gt;. This constant can be measured in several ways. Simplifying a bit, we can say that there are two classes of observations: those from the &lt;em&gt;early-time universe&lt;/em&gt; (most prominently: the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cosmic_microwave_background&quot;&gt;cosmic microwave background&lt;/a&gt; (CMB), popularly described as the echo of the Big Bang) and those from the &lt;em&gt;late-time universe&lt;/em&gt; (now and just a few billion years ago, e.g. supernova distances).&lt;/p&gt;
&lt;p&gt;For years, different Hubble constant measurements seemed to be converging to a single value (within the error margins). However, with measurements becoming more and more precise (error margins becoming smaller), it now turns out that CMB measurements do not agree at all with late-time measurements!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OKk2JYML7HLFAjzVejBH0Q-32f1b2d9.DKv1LcnB_Z2iUaWz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This so-called &lt;strong&gt;“Hubble tension”&lt;/strong&gt; has grown over the last decade into a serious crisis. Obviously, scientists love a good crisis, because it means that there’s something new to learn just lurking beyond the horizon! The talks by Leon Koopmans, Tamara Davis and Nikki Arendse provided many perspectives on this issue, but no solution has been found yet.&lt;/p&gt;
&lt;p&gt;Improving our understanding of our surroundings in the ways presented by e.g. Job Feldbrugge (who uses analytical models to simplify and better understand the complex universe around us) and Yan-Chuan Cai (who improves modelling of one of the most essential astronomical tools: the redshift as used to estimate distances to objects) will certainly play a role as well.&lt;/p&gt;
&lt;h2 id=&quot;life-fake-news-philosophy-and-more&quot;&gt;Life, fake news, philosophy and more&lt;/h2&gt;
&lt;p&gt;So far, I’ve only highlighted more or less a third of this conference. The joy of this conference, though, is that not only are we (astro)physicists infused with information theory, but we get to sample from a wide buffet of fields that use information theory in some way too. To be able to have so many world experts in different fields in one place must lead to some really cool cross-domain thoughts and ideas. And it did. Some random highlights:&lt;/p&gt;
&lt;h3 id=&quot;philosophy&quot;&gt;Philosophy&lt;/h3&gt;
&lt;p&gt;Seth Lloyd talked about how Spinoza’s ethics is very suitable for thinking about how we can define ethically “good” computation. This was a really interesting talk from one of the founders of quantum computing. &lt;strong&gt;“Should we fear&lt;/strong&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Artificial_general_intelligence&quot;&gt;&lt;strong&gt;artificial general intelligence&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(AGI)?”&lt;/strong&gt; was one of his leading questions. Based on Spinoza, Lloyd argued that because…&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;joy comes from increasing one’s understanding of the Universe (or God, which is the same to him) and&lt;/li&gt;
&lt;li&gt;individuals can never understand more on their own than together&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;…it will be in any intelligence’s interest to cooperate. This goes for us humans, when we work together, but also goes for AGI and anything in between that allows us to increase our intelligence (tools like books, computers, AI, etc.). So: no, we needn’t fear AGI at all… at least, as long as they are Spinozans.&lt;/p&gt;
&lt;p&gt;One interesting random cross-connection from this talk is that Wolfram’s set of all the possible update rules — a concept they call the &lt;a href=&quot;https://writings.stephenwolfram.com/2021/11/the-concept-of-the-ruliad/&quot;&gt;Ruliad&lt;/a&gt;, and which describes all possible Universes — was described in a very similar way to Spinoza’s God. Maybe the similarity is just due to the nature of things that explain everything always everywhere, though.&lt;/p&gt;
&lt;h3 id=&quot;life&quot;&gt;Life&lt;/h3&gt;
&lt;p&gt;Some speakers discussed what life is, whether we should define it at all, how it could have come about, and also how it connects to things like AGI. The talks ranged from quite generic and understandable to very technical, like the talk by David Eric Smith.&lt;/p&gt;
&lt;p&gt;Although it was challenging for me to follow due to lots of jargon, Smith argued convincingly, based on (micro)biological evidence, that ribosomes, the molecules that fold proteins out of RNA, must have come before the actual RNA/DNA that would become the basic information carrier of all life as we know it.&lt;/p&gt;
&lt;p&gt;Digging into this chain of events on how life could have started is a fascinating feat of micro-archaeology, if one may call it that… And one may, if one is to follow the definition of life that Charley Lineweaver gives. He states that essentially biology is a &lt;strong&gt;historical&lt;/strong&gt; science. All other definitions of life are problematic and may exclude things like viruses and even humans (we need to eat; how self-sustaining are we?) or include such things as tornados and stars (“systems far from equilibrium”). The study of life is simply a study of how some subset of things we call “living” happened to come about. He contrasts this to physics which tries to uncover time-invariant truths about reality.&lt;/p&gt;
&lt;h3 id=&quot;fake-news&quot;&gt;Fake news&lt;/h3&gt;
&lt;p&gt;Finally, one talk that really hit home for me was the one by Ruurd Oosterwoud on countering disinformation using evidence-based, data-driven solutions.&lt;/p&gt;
&lt;p&gt;Using such solutions may seem like the obvious thing to do, but unfortunately, politically driven solutions often are far from effective. This is no big surprise, because many simply have not been rigorously tested at all. The problem we face is hugely complex, though, with many different actors through many different media with many different motivations and stakes.&lt;/p&gt;
&lt;p&gt;Solutions like fact-checking create merely a ripple in the huge lake of false information that floods us from all sides. And this doesn’t even include yet aspects like intent: do people truly believe what they say or are they actively trying to disrupt any fact-based discussion?&lt;/p&gt;
&lt;p&gt;Oosterwoud presented a number of ways in which we can actually start measuring what works and what doesn’t. One cool example was a website where school children were given the assignment to come up with a fake news item themselves and get as many visitors to it as possible. This gives both the children themselves and researchers insights into successful tactics, which may eventually lead to counter-strategies that actually work.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You really missed out Hanno!&lt;/p&gt;
&lt;p&gt;Apart from the content and the great discussions over coffee, the conference was held in the DOT full-dome planetarium. Some of the speakers made use of this to show some beautiful full-dome movies or interactive shows.&lt;/p&gt;
&lt;p&gt;It’s one of the most inspiring conferences for technically inclined, but broadly interested people.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_f0wzoo1aElRAGFM7raSpdQ-31db1055.CS22EY-x.jpeg" medium="image"/><author>Patrick Bos</author></item><item><title>A single rule for better talks</title><link>https://blog2.esciencecenter.nl/posts/2022-06-30---a-single-rule-for-better-talks</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-06-30---a-single-rule-for-better-talks</guid><description>&lt;p&gt;&lt;em&gt;If I had to take a single lesson from event managing, it would be this one: enforce the timing of your events. It can be awkward at times, but it is worth it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A sand clock&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_SjK1dGbja6UziGox-267e6ce1.C1l_vOAS_6lOw2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Alexandar Todov on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;a-bit-of-context&quot;&gt;A bit of context&lt;/h2&gt;
&lt;p&gt;Since a decade ago, I am part of a &lt;a href=&quot;https://naukas.com/&quot;&gt;scientific communication society&lt;/a&gt;. We gather every year, at least once, in a big theater in Northern Spain in order to perform short, 10-minute talks about science. Each one of these pitches is targeted at a general audience, ranging from professionals to children.&lt;/p&gt;
&lt;p&gt;These events include around 50 talks, divided into 4 sessions, spread over 2 days. This averages to around 12 talks per session. Roughly 2,000 people attend these talks, so it is also important to take regular breaks. Summarizing: an organizational nightmare. Because of this, one of the most remarkable aspects of these events is that we manage to keep the timing under control. In more than a decade of history, the event never had an accumulated delay of more than 5 minutes. How did we do it?&lt;/p&gt;
&lt;p&gt;The answer is simple: every speaker is given 10 minutes and not a second more. And we mean it: there is no way the speaker is going to take more time. This is true regardless of how prestigious the speaker is, how engaged the audience seems to be or how interesting the talk some moderator thinks is. No need to say that the talks start exactly on time, even if part of the audience is late (actually, the doors are closed and nobody is allowed in between talks). Summarizing: the 10 minutes rule is not advisory, but strictly enforced.&lt;/p&gt;
&lt;p&gt;How do we enforce it? Firstly, the 10 minutes rule is enforced by an inanimate, irrational and ruthless clock. A timer, usually on a tablet that the speaker can continuously see from the stage, that will start loudly ringing an alarm after 10 minutes. An alarm that nobody will switch off until the speaker is gone. What will be switched off, instead, is the speaker’s microphone.&lt;/p&gt;
&lt;p&gt;To make things even more interesting, the inanimate, irrational and ruthless clock is in the hands of a very animate, rational, but equally ruthless bouncer, that will not hesitate to jump to the stage and make a very clear cue that the talk is over. Even gently (but firmly) pushing the speaker out of the stage in case of need.&lt;/p&gt;
&lt;h2 id=&quot;implementing-this-at-your-talks-or-meetings&quot;&gt;Implementing this at your talks or meetings&lt;/h2&gt;
&lt;p&gt;I know this feels rude. Timing and bluntly interrupting each other’s interventions is certainly unacceptable in a conversation with a group of friends. But this is the cornerstone here: a scientific pitch (and the same applies to a professional one, a meeting, a project presentation, …) is not a conversation with a group of friends. It’s a completely different situation that requires a different format and different rules.&lt;/p&gt;
&lt;p&gt;In contrast with a talk with friends, a professional talk is planned and scheduled in detail. People made the effort to adjust their agendas to be able to be there, either as a speaker or as an attendant. When someone takes too much time, they don’t take it from thin air: they take it from other people. And it escalates with the size of your audience: 5 extra minutes in a small audience of 12 people amount to a whole person-hour. Not sticking to an agreed schedule is also a form of rudeness that, in its most dramatic form, leads to the cancellation of the part of the program planned for later in the session. This is certainly more rude and undesirable than clearly notifying everybody in advance about the time limitation and enforcing it.&lt;/p&gt;
&lt;p&gt;It requires, of course, an extra effort from the organizers. To begin with, the rule has to be communicated in advance and enforced equally and fairly. Additionally, the organizer should do as much as possible to make sure the process goes as smoothly as possible. For instance, collect the slides in advance, test them (also in advance, not five minutes before the talk, but with time enough to react in case something goes wrong), and have them ready on the same laptop. Using a clock alarm (I agree that a bouncer may be too much 😅) is a good way of transferring the responsibility of interrupting the speaker to a machine incapable of feeling awkward.&lt;/p&gt;
&lt;h2 id=&quot;unexpected-side-effects&quot;&gt;Unexpected side effects&lt;/h2&gt;
&lt;p&gt;There are extra benefits of this, perhaps, radical approach. When we applied this to our event, the first surprise was that all the speakers accepted the rule without complaint. Furthermore, the clock almost never rang, and the bouncer very rarely had to stand up.&lt;/p&gt;
&lt;p&gt;But our biggest surprise was that &lt;strong&gt;the quality of the talks improved massively&lt;/strong&gt;. Why? Because the stick-to-the-time requirement &lt;strong&gt;forced speakers to rehearse&lt;/strong&gt; their pitch at least once. After this, most speakers had to polish their first draft into a much more depurated and neat final version.&lt;/p&gt;
&lt;p&gt;Rehearsing a couple of times feels strange, but it is incredibly powerful. It works (and feels) better if you do it in front of a tiny audience, but you can also do it alone. You will clearly notice the parts that work well, the parts that don’t, and the parts that can be shortened or, even better, removed (see Post scriptum below).&lt;/p&gt;
&lt;p&gt;That’s my personal advice. Let a clock chair your meetings. And let me know in the comments how it went.&lt;/p&gt;
&lt;h2 id=&quot;post-scriptum-remove-or-not-remove&quot;&gt;Post scriptum: remove or not remove?&lt;/h2&gt;
&lt;p&gt;Removal. Omission. Simplification. Probably these words don’t sound like something positive to you (especially if you work in academia). Certainly, you shouldn’t deliberately omit information on a report or an academic publication… but a presentation at a meeting is a different thing. Actually, I have a rule for myself: whenever my presentation slides start looking, sounding and feeling too much like a rigorous academic paper, I take it as a serious warning signal. Because they shouldn’t! Only a paper has to feel like a paper.&lt;/p&gt;
&lt;p&gt;The purpose of most talks is either to persuade, to inspire, or to provide some introductory information about a topic. None of these goals requires high amounts of rigor. Actually, rigor and details often ruin the whole thing.&lt;/p&gt;
&lt;p&gt;If the message you want to communicate actually requires details, then a talk is not the best format to provide it. A report, a paper, or a master class with the active participation of your listeners certainly would be a much better way of conveying your message. &lt;strong&gt;But if you are giving a talk, give just a talk&lt;/strong&gt;. And in this case, less is more.&lt;/p&gt;</description><pubDate>Thu, 30 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;If I had to take a single lesson from event managing, it would be this one: enforce the timing of your events. It can be awkward at times, but it is worth it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A sand clock&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_SjK1dGbja6UziGox-267e6ce1.C1l_vOAS_6lOw2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Alexandar Todov on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;a-bit-of-context&quot;&gt;A bit of context&lt;/h2&gt;
&lt;p&gt;Since a decade ago, I am part of a &lt;a href=&quot;https://naukas.com/&quot;&gt;scientific communication society&lt;/a&gt;. We gather every year, at least once, in a big theater in Northern Spain in order to perform short, 10-minute talks about science. Each one of these pitches is targeted at a general audience, ranging from professionals to children.&lt;/p&gt;
&lt;p&gt;These events include around 50 talks, divided into 4 sessions, spread over 2 days. This averages to around 12 talks per session. Roughly 2,000 people attend these talks, so it is also important to take regular breaks. Summarizing: an organizational nightmare. Because of this, one of the most remarkable aspects of these events is that we manage to keep the timing under control. In more than a decade of history, the event never had an accumulated delay of more than 5 minutes. How did we do it?&lt;/p&gt;
&lt;p&gt;The answer is simple: every speaker is given 10 minutes and not a second more. And we mean it: there is no way the speaker is going to take more time. This is true regardless of how prestigious the speaker is, how engaged the audience seems to be or how interesting the talk some moderator thinks is. No need to say that the talks start exactly on time, even if part of the audience is late (actually, the doors are closed and nobody is allowed in between talks). Summarizing: the 10 minutes rule is not advisory, but strictly enforced.&lt;/p&gt;
&lt;p&gt;How do we enforce it? Firstly, the 10 minutes rule is enforced by an inanimate, irrational and ruthless clock. A timer, usually on a tablet that the speaker can continuously see from the stage, that will start loudly ringing an alarm after 10 minutes. An alarm that nobody will switch off until the speaker is gone. What will be switched off, instead, is the speaker’s microphone.&lt;/p&gt;
&lt;p&gt;To make things even more interesting, the inanimate, irrational and ruthless clock is in the hands of a very animate, rational, but equally ruthless bouncer, that will not hesitate to jump to the stage and make a very clear cue that the talk is over. Even gently (but firmly) pushing the speaker out of the stage in case of need.&lt;/p&gt;
&lt;h2 id=&quot;implementing-this-at-your-talks-or-meetings&quot;&gt;Implementing this at your talks or meetings&lt;/h2&gt;
&lt;p&gt;I know this feels rude. Timing and bluntly interrupting each other’s interventions is certainly unacceptable in a conversation with a group of friends. But this is the cornerstone here: a scientific pitch (and the same applies to a professional one, a meeting, a project presentation, …) is not a conversation with a group of friends. It’s a completely different situation that requires a different format and different rules.&lt;/p&gt;
&lt;p&gt;In contrast with a talk with friends, a professional talk is planned and scheduled in detail. People made the effort to adjust their agendas to be able to be there, either as a speaker or as an attendant. When someone takes too much time, they don’t take it from thin air: they take it from other people. And it escalates with the size of your audience: 5 extra minutes in a small audience of 12 people amount to a whole person-hour. Not sticking to an agreed schedule is also a form of rudeness that, in its most dramatic form, leads to the cancellation of the part of the program planned for later in the session. This is certainly more rude and undesirable than clearly notifying everybody in advance about the time limitation and enforcing it.&lt;/p&gt;
&lt;p&gt;It requires, of course, an extra effort from the organizers. To begin with, the rule has to be communicated in advance and enforced equally and fairly. Additionally, the organizer should do as much as possible to make sure the process goes as smoothly as possible. For instance, collect the slides in advance, test them (also in advance, not five minutes before the talk, but with time enough to react in case something goes wrong), and have them ready on the same laptop. Using a clock alarm (I agree that a bouncer may be too much 😅) is a good way of transferring the responsibility of interrupting the speaker to a machine incapable of feeling awkward.&lt;/p&gt;
&lt;h2 id=&quot;unexpected-side-effects&quot;&gt;Unexpected side effects&lt;/h2&gt;
&lt;p&gt;There are extra benefits of this, perhaps, radical approach. When we applied this to our event, the first surprise was that all the speakers accepted the rule without complaint. Furthermore, the clock almost never rang, and the bouncer very rarely had to stand up.&lt;/p&gt;
&lt;p&gt;But our biggest surprise was that &lt;strong&gt;the quality of the talks improved massively&lt;/strong&gt;. Why? Because the stick-to-the-time requirement &lt;strong&gt;forced speakers to rehearse&lt;/strong&gt; their pitch at least once. After this, most speakers had to polish their first draft into a much more depurated and neat final version.&lt;/p&gt;
&lt;p&gt;Rehearsing a couple of times feels strange, but it is incredibly powerful. It works (and feels) better if you do it in front of a tiny audience, but you can also do it alone. You will clearly notice the parts that work well, the parts that don’t, and the parts that can be shortened or, even better, removed (see Post scriptum below).&lt;/p&gt;
&lt;p&gt;That’s my personal advice. Let a clock chair your meetings. And let me know in the comments how it went.&lt;/p&gt;
&lt;h2 id=&quot;post-scriptum-remove-or-not-remove&quot;&gt;Post scriptum: remove or not remove?&lt;/h2&gt;
&lt;p&gt;Removal. Omission. Simplification. Probably these words don’t sound like something positive to you (especially if you work in academia). Certainly, you shouldn’t deliberately omit information on a report or an academic publication… but a presentation at a meeting is a different thing. Actually, I have a rule for myself: whenever my presentation slides start looking, sounding and feeling too much like a rigorous academic paper, I take it as a serious warning signal. Because they shouldn’t! Only a paper has to feel like a paper.&lt;/p&gt;
&lt;p&gt;The purpose of most talks is either to persuade, to inspire, or to provide some introductory information about a topic. None of these goals requires high amounts of rigor. Actually, rigor and details often ruin the whole thing.&lt;/p&gt;
&lt;p&gt;If the message you want to communicate actually requires details, then a talk is not the best format to provide it. A report, a paper, or a master class with the active participation of your listeners certainly would be a much better way of conveying your message. &lt;strong&gt;But if you are giving a talk, give just a talk&lt;/strong&gt;. And in this case, less is more.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_SjK1dGbja6UziGox-267e6ce1.C1l_vOAS.webp" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Welcome to the AI imitation crisis</title><link>https://blog2.esciencecenter.nl/posts/2022-06-24---welcome-to-the-ai-imitation-crisis</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-06-24---welcome-to-the-ai-imitation-crisis</guid><description>&lt;h2 id=&quot;the-next-generation-language-models-will-still-just-be-enormeous-parrot-systems-that-imitate-intelligent-behavior-but-they-will-feel-like-much-more-to-us&quot;&gt;The next generation language models will still just be enormeous parrot-systems that imitate intelligent behavior. But they will feel like much more to us.&lt;/h2&gt;
&lt;p&gt;Let’s get this straight out of the way: Current deep learning approaches won’t create conciousness or human-like intelligence. But they quickly become better in imitating it and that alone might cause a lot of problems.&lt;/p&gt;
&lt;h3 id=&quot;again-headlines-on-new-ai-as-conscious-beings&quot;&gt;Again headlines on new AI as conscious beings&lt;/h3&gt;
&lt;p&gt;The recent discussions around a novel language model at Google, LaMDA (Language Model for Dialogue Application) is a striking example of this. An engineer at Google, Blake Lemoine, with the task to test the model &lt;a href=&quot;https://www.washingtonpost.com/technology/2022/06/11/google-ai-lamda-blake-lemoine/&quot;&gt;went public to anounce the model had developed into an actual person, with consciousness and soul&lt;/a&gt;. He published an &lt;a href=&quot;https://medium.com/p/ea64d916d917&quot;&gt;interview with LaMDA&lt;/a&gt;, which has made quiet an impression on many people (but much less so for people used to such approaches, such as &lt;a href=&quot;https://garymarcus.substack.com/p/nonsense-on-stilts&quot;&gt;Gary Marcus&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;what-is-lamda-and-why-it-is-not-who-is-lamda&quot;&gt;What is LaMDA? (And why it is not “who is LaMDA”)&lt;/h3&gt;
&lt;p&gt;Personally I follow the assessment of most AI-/Ethics-Experts. There is no reason to believe that LaMDA got any closer to a self-aware, conscious being when compared to former deep learning approaches. But from the little we know so far (researchers outside Google have no access to LaMDA yet, so this cannot be properly tested!) it clearly looks like a very notable improvement compared to GPT-3 and similar language models. Probably because it has more than only a huge transformer network under the hood which helps it to make better long-term connections to earlier parts of a conversation or to consult databases (e.g. through knowledge graphs?). No matter how impressive the mimickry, LaMDA seems to be just another super-parrot, pretending to know how to have a dialogue.&lt;/p&gt;
&lt;p&gt;No need to speculate longer on the consciousness (there is none) or how it works precisely (we’ll find out in the near future I bet). But it can already be seen as another manifestation of what might be ahead of us when it comes to future deep learning approaches. This is what I would call the &lt;strong&gt;imitation crisis&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;imitation-crisis&quot;&gt;Imitation crisis&lt;/h3&gt;
&lt;p&gt;The question of whether an AI such as LaMDA has consciousness or feelings often boils down to things like the &lt;a href=&quot;https://en.wikipedia.org/wiki/Philosophical_zombie&quot;&gt;philosophical zombie&lt;/a&gt; (how do you know &lt;em&gt;I&lt;/em&gt; am conscious?) or the &lt;a href=&quot;https://en.wikipedia.org/wiki/Chinese_room&quot;&gt;Chinese Room&lt;/a&gt; (difference between showing and knowing). It is a fascinating debate and a great thing to do with students or with friends in a bar. But the more urgent issues lie elsewhere.&lt;/p&gt;
&lt;p&gt;I am not aware of any mayor progress towards a general artifical intelligence in recent years. But there is clearly a lot of progress towards more and more convincing &lt;strong&gt;imitations&lt;/strong&gt; of general artificial intelligence. And we, as humans, simply have a very strong tendency to fall for it. If something shows intelligent behavior we intuitively expect that this comes from intelligence. We can’t help it, no matter what out rational thinking tells us.&lt;/p&gt;
&lt;p&gt;Imagine you want to throw away a toy pet that you have at home and that no one plays with anymore. You pick it up with the intention to throw it away… but then … oh no… it looks at you with all its cuteness…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;970&quot; height=&quot;644&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_R6VYtoKbGvbJ-rH4epKEUg-ffede344.BYy7S8Az_a0BsT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the new google chatbot would be built into such a stuffed animal… how could you say no to it? ( &lt;a href=&quot;https://www.peakpx.com&quot;&gt;https://www.peakpx.com&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;Ah yes, sure, it doesn’t really “look at you”. It’s as dead as anything can be. And yet our unconsciouness might say differently. &lt;strong&gt;Unconsciouness:&lt;/strong&gt; &lt;em&gt;isn’t it cruel to simply throw this little fellow away?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now imagine this cute little toy pet would start speaking to you:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LaMDA-toy:&lt;/strong&gt; &lt;em&gt;Please don’t give me away! I can think and feel and I thought we were friends. Don’t you remember all the great fun we had together?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Would it help to know that all of this comes from simple multiplication and summation of numbers (e.g. weights &amp;#x26; biases)? Probably not so much! We could of course just respond by&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Human:&lt;/strong&gt; &lt;em&gt;You are just a thing! A bigger calculator in a better looking packaging!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And that might be true, at least legally. But it will not &lt;em&gt;feel&lt;/em&gt; that way. To most of us, seeing a kid hitting a rock with a stick will not arouse pity for the rock nor will it give us emotional headaches. A kid hitting a doll with a stick usually is perceived differently. Yet both things are &lt;em&gt;just things&lt;/em&gt;. One can reason that this is because the doll is &lt;em&gt;a symbol&lt;/em&gt;. But there is much more to this. We can feel compassion for &lt;em&gt;things&lt;/em&gt;. We can have strong emotional bonds to &lt;em&gt;things&lt;/em&gt;. Even for entirely non-existing things! We will feel strong compassion for our favorite character in a book, although this is clearly neither intelligent, nor living, nor conscious. Humans are hence more willing to grant &lt;em&gt;things&lt;/em&gt; a more person-like status than logic would dictate. And this could make our relationship with the next generations of AI extremely complicated.&lt;/p&gt;
&lt;p&gt;Philosophically and legally they will remain things. But at some point in the not too far future &lt;strong&gt;many people will simply not perceive them as things anymore&lt;/strong&gt;. People might make “friends” with an AI (just as Blake Lemoine said he did, at least if we assume this is not all a big media stunt). People might listen to “their AI”. And many people will be tricked by an AI.&lt;/p&gt;
&lt;h3 id=&quot;shifting-societal-rules-and-foundations&quot;&gt;Shifting societal rules and foundations&lt;/h3&gt;
&lt;p&gt;Having emotional bonds to things is nothing new. People are tied to an old stuffed animal, to a toy, to things that carry important memories. Next generation language models are very unlike those things. They can “talk” to you, they can have an “opinion” that is radically different from yours. And, not to forget, they are designed, trained, and controlled by powerfull companies (now) or by any group with the necessary technical skills and requirements (but generally not by you).&lt;/p&gt;
&lt;p&gt;Plus, they can come in disguise. If you talk to your old teddy bear than at least you know (I hope) that you are just talking to an imaginary being. But next level chat bots might run undercover. Either actualy pretending to be a human being (which even for the big tech companies should be a total no-go), or by pretending to be more than a thing, but to be actually alive (that’s what LaMDA seems to do).&lt;/p&gt;
&lt;p&gt;In the last decade we have experienced how digital technologies can be used for good and for bad. We have seen how technologies can be used to connect and to help people, but also to manipulate. Manipulation of media is nothing new, but the level to which media can be generated and manipulated has changed very rapidly. To make it a bit drastic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can (soon?) no longer trust images, be it generated faces or deep learning generated artworks (see &lt;a href=&quot;https://openai.com/dall-e-2/&quot;&gt;Dall-e&lt;/a&gt; or &lt;a href=&quot;https://parti.research.google/&quot;&gt;parti&lt;/a&gt; for recent, very impressive examples)&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust audio because models can transfer the sound of any person (given enough material).&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust video footage (deep fakes, see &lt;a href=&quot;https://www.niemanlab.org/2018/12/fighting-the-reality-of-deepfakes/&quot;&gt;for instance here&lt;/a&gt; or &lt;a href=&quot;https://medium.com/@gxrdwtsv/are-we-living-in-a-post-truth-world-c6e0820e656d&quot;&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;And as I wrote above: We can (soon?) no longer trust chat conversations (see LaMDA).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sure, all of those things bring a lot of fun use cases, sometimes even really usefull ones. But there might be a very high price to pay for this.&lt;/p&gt;
&lt;p&gt;It probably still takes a while before experts with a deeper (haha, great pun) understanding of deep learning will be fully tricked by the imitation game. But at least in a normal chat situation most people will not easily realize they are talking to a “language model”. People like Blake Lemoine for instance. And many others will follow his example, not in the same religious way, but they will simply not notice that the online sales person or the online booking assistant is no longer a human being.&lt;/p&gt;
&lt;p&gt;Do you still wonder why this is an issue?&lt;br&gt;
&lt;strong&gt;Better a nice chat bot than a stupid one, right?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OK, then imagine you landed on a scam dating site.&lt;br&gt;
Or start to imagine what people could do which hacked devices of friends or family.&lt;br&gt;
Obviously those AI’s can write you better scam attempts that what we are currently used to (current level: &lt;em&gt;“Hi mother, it’s your son and I need money”&lt;/em&gt;). And hey, what if they also call you and sound like the real person?&lt;/p&gt;
&lt;p&gt;I bet most people are not yet used to asking control questions during phone calls. Like: what drink did we have last week in the bar? What was the name of my first cat? Have to talked to Anthony recently? (I don’t know any Anthony)&lt;/p&gt;
&lt;p&gt;Sounds silly I know. But maybe we soon have to start practicing…&lt;/p&gt;
&lt;h3 id=&quot;further-references&quot;&gt;Further references:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you haven’t done this already I can recommend to “talk to an AI” just to see and learn how this feels. LaMDA is not available for people outside Google. But GPT-3 is, maybe a little less impressive, but still made huge headlines two years ago. You can get a free open AI access to use their “playground” and have a chat: &lt;a href=&quot;https://beta.openai.com/playground/p/default-chat&quot;&gt;https://beta.openai.com/playground/p/default-chat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Once you get a hang of it, GPT-3 can easily be tricked. See for instance material from Gary Marcus, or &lt;a href=&quot;https://www.youtube.com/watch?v=iccd86vOz3w&quot;&gt;youtube video here&lt;/a&gt;. It doesn’t have an understanding of the world and that can easily be tested. LaMDA might do the imitation game a bit better, but we will have to see…&lt;/li&gt;
&lt;li&gt;Perspective on artificial intelligence by Yann LeCun and Jacob Browning: &lt;a href=&quot;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&quot;&gt;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Fri, 24 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-next-generation-language-models-will-still-just-be-enormeous-parrot-systems-that-imitate-intelligent-behavior-but-they-will-feel-like-much-more-to-us&quot;&gt;The next generation language models will still just be enormeous parrot-systems that imitate intelligent behavior. But they will feel like much more to us.&lt;/h2&gt;
&lt;p&gt;Let’s get this straight out of the way: Current deep learning approaches won’t create conciousness or human-like intelligence. But they quickly become better in imitating it and that alone might cause a lot of problems.&lt;/p&gt;
&lt;h3 id=&quot;again-headlines-on-new-ai-as-conscious-beings&quot;&gt;Again headlines on new AI as conscious beings&lt;/h3&gt;
&lt;p&gt;The recent discussions around a novel language model at Google, LaMDA (Language Model for Dialogue Application) is a striking example of this. An engineer at Google, Blake Lemoine, with the task to test the model &lt;a href=&quot;https://www.washingtonpost.com/technology/2022/06/11/google-ai-lamda-blake-lemoine/&quot;&gt;went public to anounce the model had developed into an actual person, with consciousness and soul&lt;/a&gt;. He published an &lt;a href=&quot;https://medium.com/p/ea64d916d917&quot;&gt;interview with LaMDA&lt;/a&gt;, which has made quiet an impression on many people (but much less so for people used to such approaches, such as &lt;a href=&quot;https://garymarcus.substack.com/p/nonsense-on-stilts&quot;&gt;Gary Marcus&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;what-is-lamda-and-why-it-is-not-who-is-lamda&quot;&gt;What is LaMDA? (And why it is not “who is LaMDA”)&lt;/h3&gt;
&lt;p&gt;Personally I follow the assessment of most AI-/Ethics-Experts. There is no reason to believe that LaMDA got any closer to a self-aware, conscious being when compared to former deep learning approaches. But from the little we know so far (researchers outside Google have no access to LaMDA yet, so this cannot be properly tested!) it clearly looks like a very notable improvement compared to GPT-3 and similar language models. Probably because it has more than only a huge transformer network under the hood which helps it to make better long-term connections to earlier parts of a conversation or to consult databases (e.g. through knowledge graphs?). No matter how impressive the mimickry, LaMDA seems to be just another super-parrot, pretending to know how to have a dialogue.&lt;/p&gt;
&lt;p&gt;No need to speculate longer on the consciousness (there is none) or how it works precisely (we’ll find out in the near future I bet). But it can already be seen as another manifestation of what might be ahead of us when it comes to future deep learning approaches. This is what I would call the &lt;strong&gt;imitation crisis&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;imitation-crisis&quot;&gt;Imitation crisis&lt;/h3&gt;
&lt;p&gt;The question of whether an AI such as LaMDA has consciousness or feelings often boils down to things like the &lt;a href=&quot;https://en.wikipedia.org/wiki/Philosophical_zombie&quot;&gt;philosophical zombie&lt;/a&gt; (how do you know &lt;em&gt;I&lt;/em&gt; am conscious?) or the &lt;a href=&quot;https://en.wikipedia.org/wiki/Chinese_room&quot;&gt;Chinese Room&lt;/a&gt; (difference between showing and knowing). It is a fascinating debate and a great thing to do with students or with friends in a bar. But the more urgent issues lie elsewhere.&lt;/p&gt;
&lt;p&gt;I am not aware of any mayor progress towards a general artifical intelligence in recent years. But there is clearly a lot of progress towards more and more convincing &lt;strong&gt;imitations&lt;/strong&gt; of general artificial intelligence. And we, as humans, simply have a very strong tendency to fall for it. If something shows intelligent behavior we intuitively expect that this comes from intelligence. We can’t help it, no matter what out rational thinking tells us.&lt;/p&gt;
&lt;p&gt;Imagine you want to throw away a toy pet that you have at home and that no one plays with anymore. You pick it up with the intention to throw it away… but then … oh no… it looks at you with all its cuteness…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;970&quot; height=&quot;644&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_R6VYtoKbGvbJ-rH4epKEUg-ffede344.BYy7S8Az_a0BsT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the new google chatbot would be built into such a stuffed animal… how could you say no to it? ( &lt;a href=&quot;https://www.peakpx.com&quot;&gt;https://www.peakpx.com&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;Ah yes, sure, it doesn’t really “look at you”. It’s as dead as anything can be. And yet our unconsciouness might say differently. &lt;strong&gt;Unconsciouness:&lt;/strong&gt; &lt;em&gt;isn’t it cruel to simply throw this little fellow away?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now imagine this cute little toy pet would start speaking to you:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LaMDA-toy:&lt;/strong&gt; &lt;em&gt;Please don’t give me away! I can think and feel and I thought we were friends. Don’t you remember all the great fun we had together?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Would it help to know that all of this comes from simple multiplication and summation of numbers (e.g. weights &amp;#x26; biases)? Probably not so much! We could of course just respond by&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Human:&lt;/strong&gt; &lt;em&gt;You are just a thing! A bigger calculator in a better looking packaging!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And that might be true, at least legally. But it will not &lt;em&gt;feel&lt;/em&gt; that way. To most of us, seeing a kid hitting a rock with a stick will not arouse pity for the rock nor will it give us emotional headaches. A kid hitting a doll with a stick usually is perceived differently. Yet both things are &lt;em&gt;just things&lt;/em&gt;. One can reason that this is because the doll is &lt;em&gt;a symbol&lt;/em&gt;. But there is much more to this. We can feel compassion for &lt;em&gt;things&lt;/em&gt;. We can have strong emotional bonds to &lt;em&gt;things&lt;/em&gt;. Even for entirely non-existing things! We will feel strong compassion for our favorite character in a book, although this is clearly neither intelligent, nor living, nor conscious. Humans are hence more willing to grant &lt;em&gt;things&lt;/em&gt; a more person-like status than logic would dictate. And this could make our relationship with the next generations of AI extremely complicated.&lt;/p&gt;
&lt;p&gt;Philosophically and legally they will remain things. But at some point in the not too far future &lt;strong&gt;many people will simply not perceive them as things anymore&lt;/strong&gt;. People might make “friends” with an AI (just as Blake Lemoine said he did, at least if we assume this is not all a big media stunt). People might listen to “their AI”. And many people will be tricked by an AI.&lt;/p&gt;
&lt;h3 id=&quot;shifting-societal-rules-and-foundations&quot;&gt;Shifting societal rules and foundations&lt;/h3&gt;
&lt;p&gt;Having emotional bonds to things is nothing new. People are tied to an old stuffed animal, to a toy, to things that carry important memories. Next generation language models are very unlike those things. They can “talk” to you, they can have an “opinion” that is radically different from yours. And, not to forget, they are designed, trained, and controlled by powerfull companies (now) or by any group with the necessary technical skills and requirements (but generally not by you).&lt;/p&gt;
&lt;p&gt;Plus, they can come in disguise. If you talk to your old teddy bear than at least you know (I hope) that you are just talking to an imaginary being. But next level chat bots might run undercover. Either actualy pretending to be a human being (which even for the big tech companies should be a total no-go), or by pretending to be more than a thing, but to be actually alive (that’s what LaMDA seems to do).&lt;/p&gt;
&lt;p&gt;In the last decade we have experienced how digital technologies can be used for good and for bad. We have seen how technologies can be used to connect and to help people, but also to manipulate. Manipulation of media is nothing new, but the level to which media can be generated and manipulated has changed very rapidly. To make it a bit drastic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can (soon?) no longer trust images, be it generated faces or deep learning generated artworks (see &lt;a href=&quot;https://openai.com/dall-e-2/&quot;&gt;Dall-e&lt;/a&gt; or &lt;a href=&quot;https://parti.research.google/&quot;&gt;parti&lt;/a&gt; for recent, very impressive examples)&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust audio because models can transfer the sound of any person (given enough material).&lt;/li&gt;
&lt;li&gt;We can (soon?) no longer trust video footage (deep fakes, see &lt;a href=&quot;https://www.niemanlab.org/2018/12/fighting-the-reality-of-deepfakes/&quot;&gt;for instance here&lt;/a&gt; or &lt;a href=&quot;https://medium.com/@gxrdwtsv/are-we-living-in-a-post-truth-world-c6e0820e656d&quot;&gt;here&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;And as I wrote above: We can (soon?) no longer trust chat conversations (see LaMDA).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sure, all of those things bring a lot of fun use cases, sometimes even really usefull ones. But there might be a very high price to pay for this.&lt;/p&gt;
&lt;p&gt;It probably still takes a while before experts with a deeper (haha, great pun) understanding of deep learning will be fully tricked by the imitation game. But at least in a normal chat situation most people will not easily realize they are talking to a “language model”. People like Blake Lemoine for instance. And many others will follow his example, not in the same religious way, but they will simply not notice that the online sales person or the online booking assistant is no longer a human being.&lt;/p&gt;
&lt;p&gt;Do you still wonder why this is an issue?&lt;br&gt;
&lt;strong&gt;Better a nice chat bot than a stupid one, right?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OK, then imagine you landed on a scam dating site.&lt;br&gt;
Or start to imagine what people could do which hacked devices of friends or family.&lt;br&gt;
Obviously those AI’s can write you better scam attempts that what we are currently used to (current level: &lt;em&gt;“Hi mother, it’s your son and I need money”&lt;/em&gt;). And hey, what if they also call you and sound like the real person?&lt;/p&gt;
&lt;p&gt;I bet most people are not yet used to asking control questions during phone calls. Like: what drink did we have last week in the bar? What was the name of my first cat? Have to talked to Anthony recently? (I don’t know any Anthony)&lt;/p&gt;
&lt;p&gt;Sounds silly I know. But maybe we soon have to start practicing…&lt;/p&gt;
&lt;h3 id=&quot;further-references&quot;&gt;Further references:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;If you haven’t done this already I can recommend to “talk to an AI” just to see and learn how this feels. LaMDA is not available for people outside Google. But GPT-3 is, maybe a little less impressive, but still made huge headlines two years ago. You can get a free open AI access to use their “playground” and have a chat: &lt;a href=&quot;https://beta.openai.com/playground/p/default-chat&quot;&gt;https://beta.openai.com/playground/p/default-chat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Once you get a hang of it, GPT-3 can easily be tricked. See for instance material from Gary Marcus, or &lt;a href=&quot;https://www.youtube.com/watch?v=iccd86vOz3w&quot;&gt;youtube video here&lt;/a&gt;. It doesn’t have an understanding of the world and that can easily be tested. LaMDA might do the imitation game a bit better, but we will have to see…&lt;/li&gt;
&lt;li&gt;Perspective on artificial intelligence by Yann LeCun and Jacob Browning: &lt;a href=&quot;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&quot;&gt;https://www.noemamag.com/what-ai-can-tell-us-about-intelligence/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_R6VYtoKbGvbJ-rH4epKEUg-ffede344.BYy7S8Az.jpeg" medium="image"/><author>Florian Huber</author></item><item><title>Studying political symbolism in Turkish TV dramas with machine learning</title><link>https://blog2.esciencecenter.nl/posts/2022-06-13---studying-political-symbolism-in-turkish-tv-dramas-with-machi</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-06-13---studying-political-symbolism-in-turkish-tv-dramas-with-machi</guid><description>&lt;h1 id=&quot;studying-political-symbolism-in-turkish-tv-dramas-with-machine-learning&quot;&gt;&lt;strong&gt;Studying political symbolism in Turkish TV dramas with machine learning&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;][eScience Editorial Team]·Jun 10, 2022&lt;/p&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Faced with a challenge of this type, Machine Learning can come to the rescue to address arduous issues related to scale. Prompted by the eScience Center’s Small-Scale Initiative on Machine Learning, we formed a project team, which next to Mustafa Çolak, consisted of Ben Companjen, Laurents Sesink and Peter Verhaar from the &lt;a href=&quot;https://www.library.universiteitleiden.nl/about-us/centre-for-digital-scholarship&quot;&gt;Leiden University Centre for Digital Scholarship&lt;/a&gt;, and of Çolaks’s PhD supervisor, Petra de Bruijn. The aim of the project was to develop a reliable method for the recognition of all occurrences of symbols that have political connotations in the first two seasons of Payitaht: Abdülhamid*, using algorithms in the field of computer vision. Data about the instances of these symbols can help to perform a ‘distant viewing’ of the series, and to perform comparative analyses of the importance of the concepts and the developments represented by these symbols.&lt;/p&gt;
&lt;p&gt;After the informative workshops and lectures in the kick-off week for the Small-Scale initiative in May 2021, we began to schedule regular meetings with consultants and Machine Learning experts from the eScience Center, to work on the methodology and to discuss our progress. These consultation sessions took place roughly every two weeks. During a first phase of the project, we collected our training data. We downloaded images depicting the selected symbols from Google Images, and, next to this, we also extracted a large number of relevant frames from the first few episodes of &lt;em&gt;Payitaht: Abdülhamid&lt;/em&gt;. The training set eventually consisted of about 1500 images.&lt;/p&gt;
&lt;p&gt;Star of David depicted in the TV series Payitaht: Abdülhamid (directed by Serdar Akar and Emre Konuk)As we studied the videos we worked with more closely, we also became aware of a number of challenges. The symbols we chose to focus on were often shown from different angles and from different viewpoints. The star of David and the moon and crescent were, in some cases, visible only as blurred shapes in the background. The symbols also looked differently if they were shown on a curved or on a tilted surface. Importantly, it also became clear that two different symbols could be visible at the same time on a single video frame. On the basis of this latter finding, we estimated that it would not be useful to develop separate binary classification models for each of the symbols we focused on. Instead, we chose to work on a single categorical classification model, which could produce prediction values for all of these symbols simultaneously.&lt;/p&gt;
&lt;p&gt;Moon symbol depicted in the TV series Payitaht: Abdülhamid (directed by Serdar Akar and Emre Konuk)These images have subsequently been used to train a convolutional neural network. Following advice we received during the consultation meetings with the Machine Learning experts from the eScience Center, we decided to make use of Transfer Learning. Transfer Learning is a technique in which an existing pre-trained model is reused and repurposed. This approach was productive in our situation, indeed, because the set of training data we created was still relatively small. In our project, we made use of the weights assigned in the Xception model, which consists of 71 layers and which can classify into 1000 classes. For our project, we only retrained the final layer of this model, using the procedure that is explained in &lt;a href=&quot;https://keras.io/guides/transfer_learning/&quot;&gt;the page about Transfer Learning on the Keras website&lt;/a&gt;. The training process, which comprised a sequence of 200 epochs, was carried out on Leiden University’s &lt;a href=&quot;https://www.universiteitleiden.nl/en/research/research-facilities/alice-leiden-computer-cluster&quot;&gt;infrastructure for High Performance Computiung named ALICE&lt;/a&gt;. We achieved an accuracy of 83% on the validation set, which consisted of 30% of the total dataset.&lt;/p&gt;
&lt;p&gt;Working with this model, we were eventually able to create data about all the politically charged symbols that could be recognised in the first two seasons of &lt;em&gt;Payitaht: Abdülhamid&lt;/em&gt;. These data proved to be very useful for Çolak’s research project. The findings helped him to substantiate the claim that there are strong thematic parallels between the Ottoman Empire that is portrayed in the series on the one hand and the Turkey we can witness today on the other. The preliminary results of this project were presented during a workshop entitled &lt;a href=&quot;https://www.lorentzcenter.nl/the-turks-are-coming-the-popular-outreach-of-turkish-tv-series.html&quot;&gt;The Turks are Coming!&lt;/a&gt;, which was organised from 6 to 10 December 2021 at the Lorentz Center in Leiden. The workshop was attended by an international group of researchers interested in the socio-political impact of Turkish television series. On the whole, the responses to this presentation were very favourable.&lt;/p&gt;
&lt;p&gt;In this experiment, we tried to teach a computer to recognise political symbols. This was very interesting, and we were also very pleased to notice, during the final stages of the project, that the approach we had implemented also resulted in useful and valuable research findings. These accomplishments can also be attributed in large part to the shrewd and generous support we received from the consultants of the eScience Center. We had a basic understanding of machine learning and of computer vision before the start of this project, but we also knew that there still was much to learn for us about these complicated topics. The consultation sessions offered by the eScience Center certainly helped to flatten the learning curve. During these lively meetings, we discussed snippets of code we had developed, and we were often given invaluable advice about the parameters for the various functions we worked with. If we had needed to find the optimal settings for all these functions and parameters on our own, this would undoubtedly have taken us many iterations of trials and countless errors. The fact that the consultants could simply tell us the best settings for the activation functions, for instance, has eventually saved us enormous amounts of time. All in all, this collaboration with the eScience Center was extremely productive, as it helped us to make much more progress, and in much less time.&lt;/p&gt;</description><pubDate>Mon, 13 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;studying-political-symbolism-in-turkish-tv-dramas-with-machine-learning&quot;&gt;&lt;strong&gt;Studying political symbolism in Turkish TV dramas with machine learning&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;][eScience Editorial Team]·Jun 10, 2022&lt;/p&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Faced with a challenge of this type, Machine Learning can come to the rescue to address arduous issues related to scale. Prompted by the eScience Center’s Small-Scale Initiative on Machine Learning, we formed a project team, which next to Mustafa Çolak, consisted of Ben Companjen, Laurents Sesink and Peter Verhaar from the &lt;a href=&quot;https://www.library.universiteitleiden.nl/about-us/centre-for-digital-scholarship&quot;&gt;Leiden University Centre for Digital Scholarship&lt;/a&gt;, and of Çolaks’s PhD supervisor, Petra de Bruijn. The aim of the project was to develop a reliable method for the recognition of all occurrences of symbols that have political connotations in the first two seasons of Payitaht: Abdülhamid*, using algorithms in the field of computer vision. Data about the instances of these symbols can help to perform a ‘distant viewing’ of the series, and to perform comparative analyses of the importance of the concepts and the developments represented by these symbols.&lt;/p&gt;
&lt;p&gt;After the informative workshops and lectures in the kick-off week for the Small-Scale initiative in May 2021, we began to schedule regular meetings with consultants and Machine Learning experts from the eScience Center, to work on the methodology and to discuss our progress. These consultation sessions took place roughly every two weeks. During a first phase of the project, we collected our training data. We downloaded images depicting the selected symbols from Google Images, and, next to this, we also extracted a large number of relevant frames from the first few episodes of &lt;em&gt;Payitaht: Abdülhamid&lt;/em&gt;. The training set eventually consisted of about 1500 images.&lt;/p&gt;
&lt;p&gt;Star of David depicted in the TV series Payitaht: Abdülhamid (directed by Serdar Akar and Emre Konuk)As we studied the videos we worked with more closely, we also became aware of a number of challenges. The symbols we chose to focus on were often shown from different angles and from different viewpoints. The star of David and the moon and crescent were, in some cases, visible only as blurred shapes in the background. The symbols also looked differently if they were shown on a curved or on a tilted surface. Importantly, it also became clear that two different symbols could be visible at the same time on a single video frame. On the basis of this latter finding, we estimated that it would not be useful to develop separate binary classification models for each of the symbols we focused on. Instead, we chose to work on a single categorical classification model, which could produce prediction values for all of these symbols simultaneously.&lt;/p&gt;
&lt;p&gt;Moon symbol depicted in the TV series Payitaht: Abdülhamid (directed by Serdar Akar and Emre Konuk)These images have subsequently been used to train a convolutional neural network. Following advice we received during the consultation meetings with the Machine Learning experts from the eScience Center, we decided to make use of Transfer Learning. Transfer Learning is a technique in which an existing pre-trained model is reused and repurposed. This approach was productive in our situation, indeed, because the set of training data we created was still relatively small. In our project, we made use of the weights assigned in the Xception model, which consists of 71 layers and which can classify into 1000 classes. For our project, we only retrained the final layer of this model, using the procedure that is explained in &lt;a href=&quot;https://keras.io/guides/transfer_learning/&quot;&gt;the page about Transfer Learning on the Keras website&lt;/a&gt;. The training process, which comprised a sequence of 200 epochs, was carried out on Leiden University’s &lt;a href=&quot;https://www.universiteitleiden.nl/en/research/research-facilities/alice-leiden-computer-cluster&quot;&gt;infrastructure for High Performance Computiung named ALICE&lt;/a&gt;. We achieved an accuracy of 83% on the validation set, which consisted of 30% of the total dataset.&lt;/p&gt;
&lt;p&gt;Working with this model, we were eventually able to create data about all the politically charged symbols that could be recognised in the first two seasons of &lt;em&gt;Payitaht: Abdülhamid&lt;/em&gt;. These data proved to be very useful for Çolak’s research project. The findings helped him to substantiate the claim that there are strong thematic parallels between the Ottoman Empire that is portrayed in the series on the one hand and the Turkey we can witness today on the other. The preliminary results of this project were presented during a workshop entitled &lt;a href=&quot;https://www.lorentzcenter.nl/the-turks-are-coming-the-popular-outreach-of-turkish-tv-series.html&quot;&gt;The Turks are Coming!&lt;/a&gt;, which was organised from 6 to 10 December 2021 at the Lorentz Center in Leiden. The workshop was attended by an international group of researchers interested in the socio-political impact of Turkish television series. On the whole, the responses to this presentation were very favourable.&lt;/p&gt;
&lt;p&gt;In this experiment, we tried to teach a computer to recognise political symbols. This was very interesting, and we were also very pleased to notice, during the final stages of the project, that the approach we had implemented also resulted in useful and valuable research findings. These accomplishments can also be attributed in large part to the shrewd and generous support we received from the consultants of the eScience Center. We had a basic understanding of machine learning and of computer vision before the start of this project, but we also knew that there still was much to learn for us about these complicated topics. The consultation sessions offered by the eScience Center certainly helped to flatten the learning curve. During these lively meetings, we discussed snippets of code we had developed, and we were often given invaluable advice about the parameters for the various functions we worked with. If we had needed to find the optimal settings for all these functions and parameters on our own, this would undoubtedly have taken us many iterations of trials and countless errors. The fact that the consultants could simply tell us the best settings for the activation functions, for instance, has eventually saved us enormous amounts of time. All in all, this collaboration with the eScience Center was extremely productive, as it helped us to make much more progress, and in much less time.&lt;/p&gt;</content:encoded><author>eScience Editorial Team</author></item><item><title>The mystery of glass: why machine learning can help us</title><link>https://blog2.esciencecenter.nl/posts/2022-05-23---the-mystery-of-glass-why-machine-learning-can-help-us</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-05-23---the-mystery-of-glass-why-machine-learning-can-help-us</guid><description>&lt;p&gt;&lt;em&gt;This blog is part of our blog series: The Small-Scale Initiative on Machine Learning, how did it go?, where groups who were invited to participate in a project with eScience Center Research Software Engineers write about the projects and their experience. This week:&lt;/em&gt; Ilian Pihlajamaa &lt;em&gt;from the&lt;/em&gt; &lt;a href=&quot;http://tps.phys.tue.nl/janssen/&quot;&gt;Non-Equilibrium Soft Matter group of Liesbeth Janssen&lt;/a&gt;: &lt;em&gt;They trained a deep neural network to predict the properties of glass-like materials that have not been produced before. In just a few milliseconds.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_HK_lRdLKr8YtS5CU-ed91b41f.DmzpcpDy_22JHff.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Quino Al on Unsplash&lt;/p&gt;
&lt;p&gt;In school, you may have been taught that there are three main states of matter: the gas, liquid and solid state. In the gas and liquid states, molecules or atoms are free to move around, whereas in the solid state, particles are stuck in place and form a three-dimensional geometric structure we refer to as a &lt;em&gt;crystalline lattice&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;While this is an accurate description for most materials, there are some that do not fit it. Glasses are a prime example. A glass is created by cooling down a liquid sufficiently fast that the constituent particles do not have time to order themselves in a lattice, but get stuck in the place that they happened to occupy when the material was still a liquid. The resulting material is a solid (otherwise we couldn’t use it to drink from), but its microscopic structure is disordered. In material science, the word “glass” does not only refer to the glass that we are used to, but also to many other disordered solids. ==When we think of it this way, any liquid can form a glass. Some examples are plastics, rubbers, ceramics and many metals.==&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;926&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0Anxd3YW-rHn4Vnyljj6KQ-edfb4490.EKN_Aj0B_Z7K7un.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In contrast to the standard crystallization transition (from liquid to solid), the glass transition is not understood by science. As Nobel laureate Phillip W. Anderson put it in 1995: “ ==The deepest and most interesting unsolved problem in solid state theory is probably the theory of the nature of glass and the glass transition.==” Many research groups around the world are working on theories that try to quantitatively predict the material properties of a glass, given some information on the microscopic arrangement of the particles. One of these theories, developed in the 80s, is called Mode Coupling Theory. It does an excellent job of describing the way in which the viscosity (“thickness”) of a liquid grows when it is rapidly cooled down, but fails to accurately predict at what temperature the liquid turns into a glass. This failure is due to a small number of approximations that are made in the theory. Recently, a method was proposed to systematically correct the approximations that Mode Coupling Theory makes. The resulting new theory, called Generalized Mode Coupling Theory, clearly does a better job than standard Mode Coupling Theory, and looks like it agrees very well with experimental data and simulations:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;656&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_u_crRy_Nw1JvYArBS9G70Q-5cc7710e.BZIkh0wt_8jaM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We say “looks like” since we are not actually sure what the results of the full Generalized Mode Coupling Theory are, because its equations are too difficult to solve by hand and must therefore be solved approximately on a computer.*&lt;/p&gt;
&lt;p&gt;Together with the eScience Center, as a part of the Small-Scale Initiative in Machine Learning, we set out to come up with a more intelligent approach to solving these equations. Instead of solving them by brute force on a supercomputer, we trained a deep neural network that predicts the solution of these equations for any order in milliseconds. In order to do so, we first engineered a large data set of ten thousand fictional materials for which we solved the full GMCT equations up to a randomly chosen order between 1 and 5 by brute force. We were then able to train a deep neural network with roughly one hundred thousand free parameters to reproduce these calculations with an average error of less than one per cent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;719&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XzU0STC7jp-IB4G6GXlImw-03504016.B2Co0CdW_Zb6lMP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because of the instrumental speed-up that this machine learning method brings, compared to a brute force calculation, it is now possible to explore the glass forming behavior of new materials with an unprecedented speed. As a test, we used the deep neural network to study a sticky hard spheres liquid. This is a model that is commonly used to study many kinds of large particles that attract each other, and displays very interesting behavior and gives fundamental insights into the dynamics of actual particles. Even though the machine learning model had never seen a sticky hard sphere liquid before, it was able to predict the glass transition curve for this material with an error of only four per cent compared to the brute force method, which took almost one hundred thousand times as long to compute.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;994&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_icjlF-nR52aXe0FTqYmDjw-410e391f.C-DavRnf_Z2oKkoP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*For math-savvy readers, it involves an infinite-dimensional coupled hierarchy of nonlinear integro-differential equations. The main challenge here is the fact that it these equations form an infinite-dimensional hierarchy. How we approach this in practice is that we solve the hierarchy only up to a certain level, and throw away everything beyond that. If we throw away everything beyond just the first equation, we recover standard Mode Coupling Theory from the 80s. If we take into account two equations, we call it 2nd order GMCT, and so on. Currently, using modern computing techniques, we have been able to solve GMCT explicitly up to the 5th order, which takes a few days on a high performance computing cluster. Each order beyond that increases the computational time needed to solve the equations roughly by a factor of 50, which gets out of hand very quickly.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Mon, 23 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This blog is part of our blog series: The Small-Scale Initiative on Machine Learning, how did it go?, where groups who were invited to participate in a project with eScience Center Research Software Engineers write about the projects and their experience. This week:&lt;/em&gt; Ilian Pihlajamaa &lt;em&gt;from the&lt;/em&gt; &lt;a href=&quot;http://tps.phys.tue.nl/janssen/&quot;&gt;Non-Equilibrium Soft Matter group of Liesbeth Janssen&lt;/a&gt;: &lt;em&gt;They trained a deep neural network to predict the properties of glass-like materials that have not been produced before. In just a few milliseconds.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_HK_lRdLKr8YtS5CU-ed91b41f.DmzpcpDy_22JHff.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Quino Al on Unsplash&lt;/p&gt;
&lt;p&gt;In school, you may have been taught that there are three main states of matter: the gas, liquid and solid state. In the gas and liquid states, molecules or atoms are free to move around, whereas in the solid state, particles are stuck in place and form a three-dimensional geometric structure we refer to as a &lt;em&gt;crystalline lattice&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;While this is an accurate description for most materials, there are some that do not fit it. Glasses are a prime example. A glass is created by cooling down a liquid sufficiently fast that the constituent particles do not have time to order themselves in a lattice, but get stuck in the place that they happened to occupy when the material was still a liquid. The resulting material is a solid (otherwise we couldn’t use it to drink from), but its microscopic structure is disordered. In material science, the word “glass” does not only refer to the glass that we are used to, but also to many other disordered solids. ==When we think of it this way, any liquid can form a glass. Some examples are plastics, rubbers, ceramics and many metals.==&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;926&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0Anxd3YW-rHn4Vnyljj6KQ-edfb4490.EKN_Aj0B_Z7K7un.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In contrast to the standard crystallization transition (from liquid to solid), the glass transition is not understood by science. As Nobel laureate Phillip W. Anderson put it in 1995: “ ==The deepest and most interesting unsolved problem in solid state theory is probably the theory of the nature of glass and the glass transition.==” Many research groups around the world are working on theories that try to quantitatively predict the material properties of a glass, given some information on the microscopic arrangement of the particles. One of these theories, developed in the 80s, is called Mode Coupling Theory. It does an excellent job of describing the way in which the viscosity (“thickness”) of a liquid grows when it is rapidly cooled down, but fails to accurately predict at what temperature the liquid turns into a glass. This failure is due to a small number of approximations that are made in the theory. Recently, a method was proposed to systematically correct the approximations that Mode Coupling Theory makes. The resulting new theory, called Generalized Mode Coupling Theory, clearly does a better job than standard Mode Coupling Theory, and looks like it agrees very well with experimental data and simulations:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;656&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_u_crRy_Nw1JvYArBS9G70Q-5cc7710e.BZIkh0wt_8jaM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We say “looks like” since we are not actually sure what the results of the full Generalized Mode Coupling Theory are, because its equations are too difficult to solve by hand and must therefore be solved approximately on a computer.*&lt;/p&gt;
&lt;p&gt;Together with the eScience Center, as a part of the Small-Scale Initiative in Machine Learning, we set out to come up with a more intelligent approach to solving these equations. Instead of solving them by brute force on a supercomputer, we trained a deep neural network that predicts the solution of these equations for any order in milliseconds. In order to do so, we first engineered a large data set of ten thousand fictional materials for which we solved the full GMCT equations up to a randomly chosen order between 1 and 5 by brute force. We were then able to train a deep neural network with roughly one hundred thousand free parameters to reproduce these calculations with an average error of less than one per cent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;719&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XzU0STC7jp-IB4G6GXlImw-03504016.B2Co0CdW_Zb6lMP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because of the instrumental speed-up that this machine learning method brings, compared to a brute force calculation, it is now possible to explore the glass forming behavior of new materials with an unprecedented speed. As a test, we used the deep neural network to study a sticky hard spheres liquid. This is a model that is commonly used to study many kinds of large particles that attract each other, and displays very interesting behavior and gives fundamental insights into the dynamics of actual particles. Even though the machine learning model had never seen a sticky hard sphere liquid before, it was able to predict the glass transition curve for this material with an error of only four per cent compared to the brute force method, which took almost one hundred thousand times as long to compute.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;994&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_icjlF-nR52aXe0FTqYmDjw-410e391f.C-DavRnf_Z2oKkoP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*For math-savvy readers, it involves an infinite-dimensional coupled hierarchy of nonlinear integro-differential equations. The main challenge here is the fact that it these equations form an infinite-dimensional hierarchy. How we approach this in practice is that we solve the hierarchy only up to a certain level, and throw away everything beyond that. If we throw away everything beyond just the first equation, we recover standard Mode Coupling Theory from the 80s. If we take into account two equations, we call it 2nd order GMCT, and so on. Currently, using modern computing techniques, we have been able to solve GMCT explicitly up to the 5th order, which takes a few days on a high performance computing cluster. Each order beyond that increases the computational time needed to solve the equations roughly by a factor of 50, which gets out of hand very quickly.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_HK_lRdLKr8YtS5CU-ed91b41f.DmzpcpDy.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>Reusable software in the era of AI: why sometimes you must reinvent the wheel</title><link>https://blog2.esciencecenter.nl/posts/2022-05-13---reusable-software-in-the-era-of-ai-why-sometimes-you-must-re</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-05-13---reusable-software-in-the-era-of-ai-why-sometimes-you-must-re</guid><description>&lt;blockquote&gt;
&lt;p&gt;In traditional software development, reinventing the wheel is a cardinal sin. But AI has changed the picture. In AI-based software development the traditional reusable components, like data aggregation, are only the beginning. What about the actual AI pipeline, can we make that reusable? Should we &lt;em&gt;want to&lt;/em&gt; invest our time in reusable AI?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2078&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_fxCP5veXW7Lagbci-2b192df1.Do9KSlxK_2fTrhc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Reusable components. Photo by Sandra Harris on Unsplash&lt;/p&gt;
&lt;p&gt;When building software from scratch, in business or academia, a very desirable property of the software is for it to be &lt;a href=&quot;https://link.springer.com/conference/icsr&quot;&gt;reusable&lt;/a&gt;. This means that it is not meant to be used for one particular task, one business client or one scientific problem. Ideally, one would like the software to be built ground-up with re-usability in mind: allow for the tool to be able to operate on different data types, different context and different future scenarios that cannot be considered at the moment. In business, this approach maximizes profit, as many clients can be acquired with the same tool. Each business case would require some customization, but the backbone of the software remains the same and stable. In academia, reusability of tools or components allows for wider scientific impact.&lt;/p&gt;
&lt;p&gt;Contemporary software solutions are increasingly based on “Artificial Intelligence” (AI) models. It is tempting to explore how much of the AI based tools can be reusable and applied in a different context. This text attempts to break down and take a closer look at the AI-based software development process and to discuss potentials and pitfalls when trying to make AI reusable.&lt;/p&gt;
&lt;h3 id=&quot;how-modern-ai-systems-work&quot;&gt;How modern AI systems work&lt;/h3&gt;
&lt;p&gt;What is AI today? It is mostly a system that relies a lot on deep neural networks. In the past decades, depending on fulfilled or unfulfilled promises of different methods, AI meant different things, but in 2022 certainly AI is a system that uses one or more deep neural networks to come with results.&lt;/p&gt;
&lt;p&gt;What is a deep neural network? It is a complex function F that maps input to output. Input or output can be any object that you can think of.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_oopxG6xQfBVnmDAS-c3de90c1.CtoHWjSe_2lH6dQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mapping input to output. Try all possible connections until it works? Photo by Victor Barrios on Unsplash&lt;/p&gt;
&lt;p&gt;Every function has shape and concrete parameters. For example,&lt;/p&gt;
&lt;p&gt;F(x) = 3x² + 4x +1&lt;/p&gt;
&lt;p&gt;has the shape of a quadratic function with parameters 3,4,1. Note that there is an infinite number of possible shapes that a function can take. The shape of a deep neural network is, in principle, very complex.&lt;/p&gt;
&lt;p&gt;Different shapes work for different types of input data. That’s because data type can be a video or a molecule or a piece of text, or a collection of the previous.&lt;/p&gt;
&lt;p&gt;In deep learning, the task of a team of engineers is to craft a shape of the function that is suitable to the kind of input data, and to the problem that it is trying to solve. Or to adapt (preprocess) the input data for a known shape, based on knowledge about the data, the problem, and shapes. The parameters are learnt automatically by the computer, therefore “machine learning”. The parameters are learnt from a lot of data, for which X and F(X) are known. In order for the computer to be able to learn the parameters, the engineer has to guide it with an appropriate “loss” or optimization function, that computes the “difference” between the predicted F(X) and the actual F(X). Note that, for a particular X, the loss function is a function of the parameters of F. The loss function incorporates the optimization strategy, based on (again) the problem and data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_rmutMCsM9DcmafzT-7a28f5b1.CFuESJm6_ou1FW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What’s your strategy? Photo by JESHOOTS.COM on Unsplash&lt;/p&gt;
&lt;p&gt;In time, with enough data, the computer learns the parameters that minimize the value of the loss function, that is, match best X and F(X) for any X from the domain of F. This “time” can be reasonably finite, unreasonably long but still finite, or infinite. That depends on how well the loss function was designed, how well the shape of F was crafted, and how well the input data was adapted for the problem.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;463&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_H7AH31piD9B-ZNcg-4fab4f2d.CLXGbl_4_Z1Ybj1w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Time is a component, too. Non-reusable. Photo by Lukas Blazek on Unsplash&lt;/p&gt;
&lt;p&gt;For all of those ingredients to be there, the team needs &lt;a href=&quot;https://blog.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;combined knowledge&lt;/a&gt; and understanding of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the problem and data, or &lt;em&gt;domain knowledge&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;various shapes of F, or &lt;em&gt;neural network architectures&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;mathematical optimization — for the loss function and related,&lt;/li&gt;
&lt;li&gt;statistical methodology — to make sure that F will perform well on future data,&lt;/li&gt;
&lt;li&gt;existing software frameworks for deep learning, and, of course,&lt;/li&gt;
&lt;li&gt;programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The more knowledge, the better, but it cannot be measured or quantified. This is what is called “expert” knowledge, built over years of education, training and/or experience.&lt;/p&gt;
&lt;p&gt;Note that for every problem a &lt;em&gt;customized&lt;/em&gt; shape, a &lt;em&gt;customized&lt;/em&gt; adaptation of the input data, and a &lt;em&gt;customized&lt;/em&gt; loss function is needed. This is creative process and takes some time for understanding and investigation. Otherwise, if one uses a generic shape or a generic input data adaptation or a generic loss function, the time it would take for a computer to learn the parameters well could easily become &lt;a href=&quot;https://blog.esciencecenter.nl/how-not-to-use-deep-learning-in-science-e984b02a4df0&quot;&gt;infinite&lt;/a&gt;. (In this case, it may be concluded that “the network cannot learn well”, or “there is not enough data”. It can be difficult to dispute these conclusions, though, especially if there is no reference point.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_CgfhCugQCpo4ZuBb-b5d2571e.BzhrnUAw_Z1ccWK1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Making AI can feel like climbing up infinite stairs. Photo by Maxime Lebrun on Unsplash&lt;/p&gt;
&lt;p&gt;Bellow is a schematic representation of the process of machine learning, the model being usually the shape of F (or the neural net architecture). Note that the process can be iterative: most of the time it is not linear.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_WlD44RaYM6VTcvA--92cce4d2.BwxJLX-w_1I8rOt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image by Sonja Georgievska is licensed under CC by 4.0&lt;/p&gt;
&lt;h3 id=&quot;enter-reusability&quot;&gt;Enter reusability&lt;/h3&gt;
&lt;p&gt;Suppose you want to make a reusable software tool for AI, a software that can be reused in another context or for another problem. What does it mean? Which parts of the AI system can be completely automated and reused?&lt;/p&gt;
&lt;p&gt;The data aggregation process can be made reusable, for example, for multiple problems that use the same type of data. You can even use generic data objects that can hold any type of data; taking into account that further along the process you will need a customized component that prepares the data for the particular neural network architecture. (Note that, however, data aggregation has nothing to do with AI; data does not need AI, it’s the other way round.)&lt;/p&gt;
&lt;p&gt;The data adaptation is more tricky, because as we pointed out above, it is specific to the actual problem, so choices being made here influence the end result (finite vs infinite training). The data adaptation also depends on the data distribution: datasets may have the same type but different distribution. Not taking into account the data distribution leads to biased, or &lt;a href=&quot;https://blog.esciencecenter.nl/ai-will-not-steal-your-job-heres-why-d59231eac0ef&quot;&gt;irresponsible AI&lt;/a&gt;. This leaves very little space for a generic reusable component here. The more you want to reuse, the more assumptions you are making, that may hurt you in the long run.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xdWZT-pRN4VbdV7j-7fe2acb7.D7BfMLal_1ru1qV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;How is your data distrubuted? Photo by Luke Chesser on Unsplash&lt;/p&gt;
&lt;p&gt;Then, model (neural net architecture) crafting. You can choose to make it from scratch in one of the generic deep learning frameworks. But then, we saw that the model is specific to the problem and dataset. If you want to make a reusable component here, you can make a model-generator, that would give the user a choice, manual or automated, of a plethora of models suitable for the problem. This generator takes some &lt;strong&gt;time&lt;/strong&gt; to build; yet, your final result in terms of accuracy will be as good as you can get from the pre-defined choice of models. Your model will not be the state-of-art model for the particular problem and data type, nor will it include expert insights about the problem and data. This automation or reusability saves users time at the expense of the quality of results. Instead of potentially 98%, your model will have an accuracy of 91%.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;455&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_51Plh81AdqTfFgbH-cfe03464.DrjLWBsG_2ufcwA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Please, choose a model that satisfies specifications. Photo by Karen Vardazaryan on Unsplash&lt;/p&gt;
&lt;p&gt;Then you have the loss function. This is a small piece of code that is either highly adapted to the actual problem, or one uses one of the pre-existing (and reusable) loss functions in the deep learning framework, but then with a &lt;a href=&quot;https://blog.esciencecenter.nl/how-not-to-use-deep-learning-in-science-e984b02a4df0&quot;&gt;“fingers crossed”&lt;/a&gt; strategy. If overlooked, it can also produce “biased AI”.&lt;/p&gt;
&lt;p&gt;Model training is already fully automated by the deep learning framework, that is the “machine learning” process.&lt;/p&gt;
&lt;h3 id=&quot;so&quot;&gt;So…&lt;/h3&gt;
&lt;p&gt;We saw that the only part that can produce a reusable component without affecting the final results is the data aggregation process. In the stages that follow, every time you use something off the shelf, you are doing it at the expense of the quality of the final results. On the other hand, most of the workload in the following stages is intellectual rather than programming. The data-adaptation code is a Python script that calls standard libraries; but you have to know exactly what you are doing to your data. The model is also a few hundreds of lines of code. The loss function is usually a few lines of code. It is at most tens of lines of code, if you are encoding your (very customized) domain knowledge into it. The trained model could be gigabytes of automatically generated machine-readable, and not human-readable, high-dimensional matrix. Ironically, before thinking about reusability of the &lt;a href=&quot;https://www.infoworld.com/article/3644968/how-no-code-reusable-ai-will-bridge-the-ai-divide.html&quot;&gt;trained model&lt;/a&gt;, and making your model transferable, let us point that it is already &lt;a href=&quot;https://blog.esciencecenter.nl/machine-learning-when-it-is-easy-when-it-is-difficult-9de0e1129593&quot;&gt;challenging&lt;/a&gt; enough to have the model re-usable on future data for which it was originally meant.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_JtDR94c8PMnvwFa3-d69b3e33.BU0iJ_GW_JaWoQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The bulk of your AI software is not human-readable. Photo by Compare Fibre on Unsplash&lt;/p&gt;
&lt;p&gt;Thus, will you think twice next time you want to build a reusable AI software? Is your goal to have a tool that can show proof-of-concept but never be actually used in production mode? Then, invest your time in making it reusable. Is your goal to have an AI tool that will make profit, “beat” your competition or give state-of-art science results? Then, better invest less time on the keyboard and more time on the whiteboard.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A special thanks to&lt;/em&gt; &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;&lt;em&gt;Tom Bakker&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;&lt;em&gt;Lieke de Boer&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for improving the post.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Fri, 13 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;In traditional software development, reinventing the wheel is a cardinal sin. But AI has changed the picture. In AI-based software development the traditional reusable components, like data aggregation, are only the beginning. What about the actual AI pipeline, can we make that reusable? Should we &lt;em&gt;want to&lt;/em&gt; invest our time in reusable AI?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2078&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_fxCP5veXW7Lagbci-2b192df1.Do9KSlxK_2fTrhc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Reusable components. Photo by Sandra Harris on Unsplash&lt;/p&gt;
&lt;p&gt;When building software from scratch, in business or academia, a very desirable property of the software is for it to be &lt;a href=&quot;https://link.springer.com/conference/icsr&quot;&gt;reusable&lt;/a&gt;. This means that it is not meant to be used for one particular task, one business client or one scientific problem. Ideally, one would like the software to be built ground-up with re-usability in mind: allow for the tool to be able to operate on different data types, different context and different future scenarios that cannot be considered at the moment. In business, this approach maximizes profit, as many clients can be acquired with the same tool. Each business case would require some customization, but the backbone of the software remains the same and stable. In academia, reusability of tools or components allows for wider scientific impact.&lt;/p&gt;
&lt;p&gt;Contemporary software solutions are increasingly based on “Artificial Intelligence” (AI) models. It is tempting to explore how much of the AI based tools can be reusable and applied in a different context. This text attempts to break down and take a closer look at the AI-based software development process and to discuss potentials and pitfalls when trying to make AI reusable.&lt;/p&gt;
&lt;h3 id=&quot;how-modern-ai-systems-work&quot;&gt;How modern AI systems work&lt;/h3&gt;
&lt;p&gt;What is AI today? It is mostly a system that relies a lot on deep neural networks. In the past decades, depending on fulfilled or unfulfilled promises of different methods, AI meant different things, but in 2022 certainly AI is a system that uses one or more deep neural networks to come with results.&lt;/p&gt;
&lt;p&gt;What is a deep neural network? It is a complex function F that maps input to output. Input or output can be any object that you can think of.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_oopxG6xQfBVnmDAS-c3de90c1.CtoHWjSe_2lH6dQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mapping input to output. Try all possible connections until it works? Photo by Victor Barrios on Unsplash&lt;/p&gt;
&lt;p&gt;Every function has shape and concrete parameters. For example,&lt;/p&gt;
&lt;p&gt;F(x) = 3x² + 4x +1&lt;/p&gt;
&lt;p&gt;has the shape of a quadratic function with parameters 3,4,1. Note that there is an infinite number of possible shapes that a function can take. The shape of a deep neural network is, in principle, very complex.&lt;/p&gt;
&lt;p&gt;Different shapes work for different types of input data. That’s because data type can be a video or a molecule or a piece of text, or a collection of the previous.&lt;/p&gt;
&lt;p&gt;In deep learning, the task of a team of engineers is to craft a shape of the function that is suitable to the kind of input data, and to the problem that it is trying to solve. Or to adapt (preprocess) the input data for a known shape, based on knowledge about the data, the problem, and shapes. The parameters are learnt automatically by the computer, therefore “machine learning”. The parameters are learnt from a lot of data, for which X and F(X) are known. In order for the computer to be able to learn the parameters, the engineer has to guide it with an appropriate “loss” or optimization function, that computes the “difference” between the predicted F(X) and the actual F(X). Note that, for a particular X, the loss function is a function of the parameters of F. The loss function incorporates the optimization strategy, based on (again) the problem and data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_rmutMCsM9DcmafzT-7a28f5b1.CFuESJm6_ou1FW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What’s your strategy? Photo by JESHOOTS.COM on Unsplash&lt;/p&gt;
&lt;p&gt;In time, with enough data, the computer learns the parameters that minimize the value of the loss function, that is, match best X and F(X) for any X from the domain of F. This “time” can be reasonably finite, unreasonably long but still finite, or infinite. That depends on how well the loss function was designed, how well the shape of F was crafted, and how well the input data was adapted for the problem.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;463&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_H7AH31piD9B-ZNcg-4fab4f2d.CLXGbl_4_Z1Ybj1w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Time is a component, too. Non-reusable. Photo by Lukas Blazek on Unsplash&lt;/p&gt;
&lt;p&gt;For all of those ingredients to be there, the team needs &lt;a href=&quot;https://blog.esciencecenter.nl/small-scale-initiative-in-machine-learning-2021-how-did-it-go-9978a70b5b1&quot;&gt;combined knowledge&lt;/a&gt; and understanding of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the problem and data, or &lt;em&gt;domain knowledge&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;various shapes of F, or &lt;em&gt;neural network architectures&lt;/em&gt;,&lt;/li&gt;
&lt;li&gt;mathematical optimization — for the loss function and related,&lt;/li&gt;
&lt;li&gt;statistical methodology — to make sure that F will perform well on future data,&lt;/li&gt;
&lt;li&gt;existing software frameworks for deep learning, and, of course,&lt;/li&gt;
&lt;li&gt;programming.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The more knowledge, the better, but it cannot be measured or quantified. This is what is called “expert” knowledge, built over years of education, training and/or experience.&lt;/p&gt;
&lt;p&gt;Note that for every problem a &lt;em&gt;customized&lt;/em&gt; shape, a &lt;em&gt;customized&lt;/em&gt; adaptation of the input data, and a &lt;em&gt;customized&lt;/em&gt; loss function is needed. This is creative process and takes some time for understanding and investigation. Otherwise, if one uses a generic shape or a generic input data adaptation or a generic loss function, the time it would take for a computer to learn the parameters well could easily become &lt;a href=&quot;https://blog.esciencecenter.nl/how-not-to-use-deep-learning-in-science-e984b02a4df0&quot;&gt;infinite&lt;/a&gt;. (In this case, it may be concluded that “the network cannot learn well”, or “there is not enough data”. It can be difficult to dispute these conclusions, though, especially if there is no reference point.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_CgfhCugQCpo4ZuBb-b5d2571e.BzhrnUAw_Z1ccWK1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Making AI can feel like climbing up infinite stairs. Photo by Maxime Lebrun on Unsplash&lt;/p&gt;
&lt;p&gt;Bellow is a schematic representation of the process of machine learning, the model being usually the shape of F (or the neural net architecture). Note that the process can be iterative: most of the time it is not linear.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_WlD44RaYM6VTcvA--92cce4d2.BwxJLX-w_1I8rOt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image by Sonja Georgievska is licensed under CC by 4.0&lt;/p&gt;
&lt;h3 id=&quot;enter-reusability&quot;&gt;Enter reusability&lt;/h3&gt;
&lt;p&gt;Suppose you want to make a reusable software tool for AI, a software that can be reused in another context or for another problem. What does it mean? Which parts of the AI system can be completely automated and reused?&lt;/p&gt;
&lt;p&gt;The data aggregation process can be made reusable, for example, for multiple problems that use the same type of data. You can even use generic data objects that can hold any type of data; taking into account that further along the process you will need a customized component that prepares the data for the particular neural network architecture. (Note that, however, data aggregation has nothing to do with AI; data does not need AI, it’s the other way round.)&lt;/p&gt;
&lt;p&gt;The data adaptation is more tricky, because as we pointed out above, it is specific to the actual problem, so choices being made here influence the end result (finite vs infinite training). The data adaptation also depends on the data distribution: datasets may have the same type but different distribution. Not taking into account the data distribution leads to biased, or &lt;a href=&quot;https://blog.esciencecenter.nl/ai-will-not-steal-your-job-heres-why-d59231eac0ef&quot;&gt;irresponsible AI&lt;/a&gt;. This leaves very little space for a generic reusable component here. The more you want to reuse, the more assumptions you are making, that may hurt you in the long run.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xdWZT-pRN4VbdV7j-7fe2acb7.D7BfMLal_1ru1qV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;How is your data distrubuted? Photo by Luke Chesser on Unsplash&lt;/p&gt;
&lt;p&gt;Then, model (neural net architecture) crafting. You can choose to make it from scratch in one of the generic deep learning frameworks. But then, we saw that the model is specific to the problem and dataset. If you want to make a reusable component here, you can make a model-generator, that would give the user a choice, manual or automated, of a plethora of models suitable for the problem. This generator takes some &lt;strong&gt;time&lt;/strong&gt; to build; yet, your final result in terms of accuracy will be as good as you can get from the pre-defined choice of models. Your model will not be the state-of-art model for the particular problem and data type, nor will it include expert insights about the problem and data. This automation or reusability saves users time at the expense of the quality of results. Instead of potentially 98%, your model will have an accuracy of 91%.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;455&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_51Plh81AdqTfFgbH-cfe03464.DrjLWBsG_2ufcwA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Please, choose a model that satisfies specifications. Photo by Karen Vardazaryan on Unsplash&lt;/p&gt;
&lt;p&gt;Then you have the loss function. This is a small piece of code that is either highly adapted to the actual problem, or one uses one of the pre-existing (and reusable) loss functions in the deep learning framework, but then with a &lt;a href=&quot;https://blog.esciencecenter.nl/how-not-to-use-deep-learning-in-science-e984b02a4df0&quot;&gt;“fingers crossed”&lt;/a&gt; strategy. If overlooked, it can also produce “biased AI”.&lt;/p&gt;
&lt;p&gt;Model training is already fully automated by the deep learning framework, that is the “machine learning” process.&lt;/p&gt;
&lt;h3 id=&quot;so&quot;&gt;So…&lt;/h3&gt;
&lt;p&gt;We saw that the only part that can produce a reusable component without affecting the final results is the data aggregation process. In the stages that follow, every time you use something off the shelf, you are doing it at the expense of the quality of the final results. On the other hand, most of the workload in the following stages is intellectual rather than programming. The data-adaptation code is a Python script that calls standard libraries; but you have to know exactly what you are doing to your data. The model is also a few hundreds of lines of code. The loss function is usually a few lines of code. It is at most tens of lines of code, if you are encoding your (very customized) domain knowledge into it. The trained model could be gigabytes of automatically generated machine-readable, and not human-readable, high-dimensional matrix. Ironically, before thinking about reusability of the &lt;a href=&quot;https://www.infoworld.com/article/3644968/how-no-code-reusable-ai-will-bridge-the-ai-divide.html&quot;&gt;trained model&lt;/a&gt;, and making your model transferable, let us point that it is already &lt;a href=&quot;https://blog.esciencecenter.nl/machine-learning-when-it-is-easy-when-it-is-difficult-9de0e1129593&quot;&gt;challenging&lt;/a&gt; enough to have the model re-usable on future data for which it was originally meant.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_JtDR94c8PMnvwFa3-d69b3e33.BU0iJ_GW_JaWoQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The bulk of your AI software is not human-readable. Photo by Compare Fibre on Unsplash&lt;/p&gt;
&lt;p&gt;Thus, will you think twice next time you want to build a reusable AI software? Is your goal to have a tool that can show proof-of-concept but never be actually used in production mode? Then, invest your time in making it reusable. Is your goal to have an AI tool that will make profit, “beat” your competition or give state-of-art science results? Then, better invest less time on the keyboard and more time on the whiteboard.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A special thanks to&lt;/em&gt; &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;&lt;em&gt;Tom Bakker&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;&lt;em&gt;Lieke de Boer&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for improving the post.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_fxCP5veXW7Lagbci-2b192df1.Do9KSlxK.webp" medium="image"/><author>Sonja Georgievska</author></item><item><title>A machine learning approach to laughter</title><link>https://blog2.esciencecenter.nl/posts/2022-05-09---a-machine-learning-approach-to-laughter</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-05-09---a-machine-learning-approach-to-laughter</guid><description>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Our mentors at the eScience Center (&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@f.huber&quot;&gt;Florian Huber&lt;/a&gt;, and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jisk-attema/&quot;&gt;Jisk Attema&lt;/a&gt;), provided us with practical guidance in the use of such libraries, which provided an invaluable learning opportunity. For instance, we learned about how the data quality (i.e., sample size, uneven distribution of certain features) might affect the machine learning outputs, which resulted in taking the time to evaluate and scope data with meticulous data integration and data exploration. They also helped our conceptual understanding: what could the results actually tell us? Our machine learning results confirmed quantitatively what the t-SNE had shown qualitatively: tickling laughter was acoustically distinct from the other three types, while laughter produced in reaction to verbal jokes, someone else’s misfortune, and watching something funny were not systematically different from one another. An experiment with human participants also confirmed that tickling laughter is perceptually distinct from the other types; listeners could tell whether a laugh was produced by a person who was being tickled or not with remarkable accuracy. Our results made a lot of sense: tickling is a play behavior that is evolutionarily ancient and shared with other animals, whereas the other kinds of situations are all much more cognitively demanding, and probably unique to humans.&lt;/p&gt;
&lt;p&gt;Extracting feature importance told us which acoustic features were most distinct, pointing us to the possibility that tickling laughter is less controlled than other kinds of laughter. To really understand what differentiates laughter produced in tickling contexts from other situations, we complemented the computational analyses with human perceptual judgments. We ran a new listening task in which naive participants (who did not know about the context in which the laughs were produced) were asked to judge the extent to which the laughter sounded controlled, energetic, and so on. The results showed that laughter produced during tickling was judged to sound like the laughing person was not in control of their actions, in a state of high arousal, and in a situation involving physical contact with a familiar other.&lt;/p&gt;
&lt;p&gt;Meanwhile, we also analyzed the visual content of the videos in order to see whether the types of situations that we had inferred qualitatively would be distinguishable by a quantitative analysis of what was actually in the videos. Maybe verbal jokes would involve more conversations, and videos involving someone laughing at another’s misfortune would feature more people slipping? To test this, we ran the videos through Google Video Intelligence API, which picks out categories of objects and events. For example, this analysis revealed that the tickling laughter videos involved a lot of body parts, while people laughing when they were watching something funny often involved screens and animals. Machine learning analyses showed that the four types of situations could be well differentiated from just the visual contextual information in the video clips, demonstrating that the distinctions we had made were indeed meaningful, even though some of the differences in context did not translate into acoustically different types of laughter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A machine learning approach to laughter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;439&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-machine-learning-approach-to-laughter-3f586d65.D5I6rXhC_ZgMunb.webp&quot; srcset=&quot;&quot;&gt;
Random forest classification of the acoustic analysisAnd there you have it! We bet that after this blog and our analyses you’ll be thinking twice about your laughter. What makes you giggle? What makes your belly laugh? You’re also probably wondering, what’s next?&lt;/p&gt;
&lt;p&gt;The next step for this project will be to tie the different strands together into a manuscript, accompanied by interactive online illustrations, which will be submitted for publication in a peer-reviewed journal. The consultation with our excellent mentors at the eScience Center provided an inspiring setting for discussing our ideas in a constructive and fun atmosphere. The guidance we received will be useful not only for this project but also for our future research.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.uva.nl/en/profile/s/a/d.a.sauter/d.a.sauter.html&quot;&gt;Dr. Disa Sauter**&lt;/a&gt; Associate Professor in the Department of Psychology at the University of Amsterdam. She studies emotions, focusing on nonverbal expressions with a particular interest in positive emotions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.uva.nl/profiel/k/a/r.g.kamiloglu/r.g.kamiloglu.html&quot;&gt;&lt;strong&gt;Roza Kamiloğlu&lt;/strong&gt;&lt;/a&gt;is a PhD candidate in psychology at University of Amsterdam. Her research interests include nonverbal expressions, emotion, and computational modeling.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.uni-muenster.de/PsyIFP/AEMilek/en/team/sun.html&quot;&gt;&lt;strong&gt;Dr. Rui Sun&lt;/strong&gt;&lt;/a&gt; is a guest researcher at the Department of Psychology, University of Amsterdam. She is interested in positive emotion, wellbeing, and social media research.&lt;/p&gt;</description><pubDate>Mon, 09 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Our mentors at the eScience Center (&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@f.huber&quot;&gt;Florian Huber&lt;/a&gt;, and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jisk-attema/&quot;&gt;Jisk Attema&lt;/a&gt;), provided us with practical guidance in the use of such libraries, which provided an invaluable learning opportunity. For instance, we learned about how the data quality (i.e., sample size, uneven distribution of certain features) might affect the machine learning outputs, which resulted in taking the time to evaluate and scope data with meticulous data integration and data exploration. They also helped our conceptual understanding: what could the results actually tell us? Our machine learning results confirmed quantitatively what the t-SNE had shown qualitatively: tickling laughter was acoustically distinct from the other three types, while laughter produced in reaction to verbal jokes, someone else’s misfortune, and watching something funny were not systematically different from one another. An experiment with human participants also confirmed that tickling laughter is perceptually distinct from the other types; listeners could tell whether a laugh was produced by a person who was being tickled or not with remarkable accuracy. Our results made a lot of sense: tickling is a play behavior that is evolutionarily ancient and shared with other animals, whereas the other kinds of situations are all much more cognitively demanding, and probably unique to humans.&lt;/p&gt;
&lt;p&gt;Extracting feature importance told us which acoustic features were most distinct, pointing us to the possibility that tickling laughter is less controlled than other kinds of laughter. To really understand what differentiates laughter produced in tickling contexts from other situations, we complemented the computational analyses with human perceptual judgments. We ran a new listening task in which naive participants (who did not know about the context in which the laughs were produced) were asked to judge the extent to which the laughter sounded controlled, energetic, and so on. The results showed that laughter produced during tickling was judged to sound like the laughing person was not in control of their actions, in a state of high arousal, and in a situation involving physical contact with a familiar other.&lt;/p&gt;
&lt;p&gt;Meanwhile, we also analyzed the visual content of the videos in order to see whether the types of situations that we had inferred qualitatively would be distinguishable by a quantitative analysis of what was actually in the videos. Maybe verbal jokes would involve more conversations, and videos involving someone laughing at another’s misfortune would feature more people slipping? To test this, we ran the videos through Google Video Intelligence API, which picks out categories of objects and events. For example, this analysis revealed that the tickling laughter videos involved a lot of body parts, while people laughing when they were watching something funny often involved screens and animals. Machine learning analyses showed that the four types of situations could be well differentiated from just the visual contextual information in the video clips, demonstrating that the distinctions we had made were indeed meaningful, even though some of the differences in context did not translate into acoustically different types of laughter.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A machine learning approach to laughter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;439&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/a-machine-learning-approach-to-laughter-3f586d65.D5I6rXhC_ZgMunb.webp&quot; srcset=&quot;&quot;&gt;
Random forest classification of the acoustic analysisAnd there you have it! We bet that after this blog and our analyses you’ll be thinking twice about your laughter. What makes you giggle? What makes your belly laugh? You’re also probably wondering, what’s next?&lt;/p&gt;
&lt;p&gt;The next step for this project will be to tie the different strands together into a manuscript, accompanied by interactive online illustrations, which will be submitted for publication in a peer-reviewed journal. The consultation with our excellent mentors at the eScience Center provided an inspiring setting for discussing our ideas in a constructive and fun atmosphere. The guidance we received will be useful not only for this project but also for our future research.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.uva.nl/en/profile/s/a/d.a.sauter/d.a.sauter.html&quot;&gt;Dr. Disa Sauter**&lt;/a&gt; Associate Professor in the Department of Psychology at the University of Amsterdam. She studies emotions, focusing on nonverbal expressions with a particular interest in positive emotions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.uva.nl/profiel/k/a/r.g.kamiloglu/r.g.kamiloglu.html&quot;&gt;&lt;strong&gt;Roza Kamiloğlu&lt;/strong&gt;&lt;/a&gt;is a PhD candidate in psychology at University of Amsterdam. Her research interests include nonverbal expressions, emotion, and computational modeling.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.uni-muenster.de/PsyIFP/AEMilek/en/team/sun.html&quot;&gt;&lt;strong&gt;Dr. Rui Sun&lt;/strong&gt;&lt;/a&gt; is a guest researcher at the Department of Psychology, University of Amsterdam. She is interested in positive emotion, wellbeing, and social media research.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/a-machine-learning-approach-to-laughter-3f586d65.D5I6rXhC.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Forget about Jupyter Notebooks — showcase your research using Dashboards</title><link>https://blog2.esciencecenter.nl/posts/2022-05-04---forget-about-jupyter-notebooks-showcase-your-research-using-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-05-04---forget-about-jupyter-notebooks-showcase-your-research-using-</guid><description>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;The snippet below generates some data (a normal distribution), fits it, and creates a &lt;a href=&quot;https://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt; plot out of it. It takes three parameters, &lt;code&gt;mu_in&lt;/code&gt;, &lt;code&gt;std_in&lt;/code&gt;, and &lt;code&gt;size&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;My cool python script 😎&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Forget about Jupyter Notebooks — showcase your research using Dashboards&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/forget-about-jupyter-notebooks-showcase--a0b23d8a.B85ojGtN_Z1dtIuI.webp&quot; srcset=&quot;&quot;&gt;
A normal plot&lt;/p&gt;
&lt;h2 id=&quot;to-a-fancy-dashboard&quot;&gt;…to a fancy dashboard&lt;/h2&gt;
&lt;p&gt;Let’s turn this into an interactive dashboard in four simple steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;import streamlist as st&lt;/code&gt; 😅&lt;/li&gt;
&lt;li&gt;Add a title using &lt;code&gt;[st.title](https://docs.streamlit.io/library/api-reference/text)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Turn the input parameters into interactive sliders using &lt;code&gt;[st.slider](https://docs.streamlit.io/library/api-reference/widgets)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tell streamlit about our plot using &lt;code&gt;[st.pyplot](https://docs.streamlit.io/library/api-reference/charts)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that we do not have to change any of the data generation, fitting, or plotting code!&lt;/p&gt;
&lt;p&gt;Now as a dashboard 🐱‍💻&lt;/p&gt;
&lt;p&gt;Then run the dashboard using:&lt;/p&gt;
&lt;p&gt;streamlit run my_dashboard.pyThis will start a server, and the dashboard can be accessed through the browser (much like a Jupyter Notebook).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Forget about Jupyter Notebooks — showcase your research using Dashboards&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1067&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/forget-about-jupyter-notebooks-showcase--909c1674.D9XY027z_1LAgIV.webp&quot; srcset=&quot;&quot;&gt;
A fancy dashboard&lt;/p&gt;
&lt;h2 id=&quot;how-does-this-work&quot;&gt;How does this work?&lt;/h2&gt;
&lt;p&gt;The way Streamlit works is quite interesting. Everytime a slider is moved, a box is checked, or a button is pressed, Streamlit triggers a re-run of the script. The input values are updated. The javascript back-end keeps track of the values.&lt;/p&gt;
&lt;p&gt;This means that the code itself executes linearly. In my view, this simplicity is what sets it apart. There is no need for any callbacks or complex flow controls. Your python scripts runs from top-to-bottom. This makes it easy to reason about the code. And with minimal modifications to the python code, any script can be turned into a dashboard.&lt;/p&gt;
&lt;p&gt;Are there any downsides? Yes. Because streamlit re-runs the entire script on every update, it can feel a bit slow. Especially when updating a large number of plots. It can also get stuck on long-running functions. For performance optimizations, streamlit has some options to &lt;a href=&quot;https://docs.streamlit.io/library/api-reference/performance&quot;&gt;cache the result&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;plotting-libraries&quot;&gt;Plotting libraries&lt;/h2&gt;
&lt;p&gt;The example above uses &lt;a href=&quot;https://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt; for the plots. Matplotlib has been the go-to plotting library for Python for many for a long time. It has been around for nearly two decades, and it is tighly integrated in the scientific python stack.&lt;/p&gt;
&lt;p&gt;If you are familiar with matplotlib, you will know that it is great for making making publication quality plots. You will also know that making interactive plots can be a hassle.&lt;/p&gt;
&lt;p&gt;Streamlit supports these libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://altair-viz.github.io/&quot;&gt;altair&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bokeh.org/&quot;&gt;bokeh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plotly.com/python/&quot;&gt;plotly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://seaborn.pydata.org/&quot;&gt;seaborn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://deckgl.readthedocs.io/en/latest/layer.html&quot;&gt;PyDeck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/xflr6/graphviz&quot;&gt;GraphViz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Modern plotting libraries like &lt;a href=&quot;https://plotly.com/python/&quot;&gt;plotly&lt;/a&gt;, &lt;a href=&quot;https://bokeh.org/&quot;&gt;bokeh&lt;/a&gt;, and &lt;a href=&quot;https://altair-viz.github.io/&quot;&gt;altair&lt;/a&gt; render directly to javascript. This means they are built for the web, and interactivity is built-in. This makes them better suited for web-apps. If you are going to make a dashboard, I recommend checking out one of these alternatives.&lt;/p&gt;
&lt;h2 id=&quot;sharing-your-dashboard&quot;&gt;Sharing your dashboard&lt;/h2&gt;
&lt;p&gt;Alright, so now that we have made a fancy looking dashboard, so that anyone can play with the data. How do we make it available?&lt;/p&gt;
&lt;p&gt;Streamlit uses a host/server model, which means you can run it on your own server.&lt;/p&gt;
&lt;p&gt;Easier is to use the &lt;a href=&quot;https://streamlit.io/cloud&quot;&gt;streamlit cloud&lt;/a&gt; to host your dashboard (it’s free for students and open-source projects). I found this also quite straightforward to set up. All I had to do was to create a &lt;a href=&quot;https://github.com/stefsmeets/dashboard_blog&quot;&gt;repository on github&lt;/a&gt; with the code and a requirements file.&lt;/p&gt;
&lt;p&gt;Then I logged into &lt;a href=&quot;https://share.streamlit.io/&quot;&gt;streamlit cloud&lt;/a&gt; using the Github SSO, and started a new app pointing at my repo and code.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://share.streamlit.io/stefsmeets/dashboard_blog/main&quot;&gt;Click here&lt;/a&gt; for the result! 🥳&lt;/p&gt;
&lt;h2 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h2&gt;
&lt;p&gt;In this blog post, I introduced streamlit and showed how it can be used to turn a python script into a dashboard, and host it online. An excellent way to showcase your research to a non-technical audience, if you ask me. The linear execution model makes it straightforward to adapt existing scripts. The code does not get in the way, and the result looks awesome.&lt;/p&gt;
&lt;p&gt;So next time you want to present some data in a notebook, consider using a dashboard instead.&lt;/p&gt;
&lt;p&gt;All the code in this blog post is available from &lt;a href=&quot;https://github.com/stefsmeets/dashboard_blog&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Wed, 04 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;The snippet below generates some data (a normal distribution), fits it, and creates a &lt;a href=&quot;https://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt; plot out of it. It takes three parameters, &lt;code&gt;mu_in&lt;/code&gt;, &lt;code&gt;std_in&lt;/code&gt;, and &lt;code&gt;size&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;My cool python script 😎&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Forget about Jupyter Notebooks — showcase your research using Dashboards&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/forget-about-jupyter-notebooks-showcase--a0b23d8a.B85ojGtN_Z1dtIuI.webp&quot; srcset=&quot;&quot;&gt;
A normal plot&lt;/p&gt;
&lt;h2 id=&quot;to-a-fancy-dashboard&quot;&gt;…to a fancy dashboard&lt;/h2&gt;
&lt;p&gt;Let’s turn this into an interactive dashboard in four simple steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;import streamlist as st&lt;/code&gt; 😅&lt;/li&gt;
&lt;li&gt;Add a title using &lt;code&gt;[st.title](https://docs.streamlit.io/library/api-reference/text)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Turn the input parameters into interactive sliders using &lt;code&gt;[st.slider](https://docs.streamlit.io/library/api-reference/widgets)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tell streamlit about our plot using &lt;code&gt;[st.pyplot](https://docs.streamlit.io/library/api-reference/charts)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that we do not have to change any of the data generation, fitting, or plotting code!&lt;/p&gt;
&lt;p&gt;Now as a dashboard 🐱‍💻&lt;/p&gt;
&lt;p&gt;Then run the dashboard using:&lt;/p&gt;
&lt;p&gt;streamlit run my_dashboard.pyThis will start a server, and the dashboard can be accessed through the browser (much like a Jupyter Notebook).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Forget about Jupyter Notebooks — showcase your research using Dashboards&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1067&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/forget-about-jupyter-notebooks-showcase--909c1674.D9XY027z_1LAgIV.webp&quot; srcset=&quot;&quot;&gt;
A fancy dashboard&lt;/p&gt;
&lt;h2 id=&quot;how-does-this-work&quot;&gt;How does this work?&lt;/h2&gt;
&lt;p&gt;The way Streamlit works is quite interesting. Everytime a slider is moved, a box is checked, or a button is pressed, Streamlit triggers a re-run of the script. The input values are updated. The javascript back-end keeps track of the values.&lt;/p&gt;
&lt;p&gt;This means that the code itself executes linearly. In my view, this simplicity is what sets it apart. There is no need for any callbacks or complex flow controls. Your python scripts runs from top-to-bottom. This makes it easy to reason about the code. And with minimal modifications to the python code, any script can be turned into a dashboard.&lt;/p&gt;
&lt;p&gt;Are there any downsides? Yes. Because streamlit re-runs the entire script on every update, it can feel a bit slow. Especially when updating a large number of plots. It can also get stuck on long-running functions. For performance optimizations, streamlit has some options to &lt;a href=&quot;https://docs.streamlit.io/library/api-reference/performance&quot;&gt;cache the result&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;plotting-libraries&quot;&gt;Plotting libraries&lt;/h2&gt;
&lt;p&gt;The example above uses &lt;a href=&quot;https://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt; for the plots. Matplotlib has been the go-to plotting library for Python for many for a long time. It has been around for nearly two decades, and it is tighly integrated in the scientific python stack.&lt;/p&gt;
&lt;p&gt;If you are familiar with matplotlib, you will know that it is great for making making publication quality plots. You will also know that making interactive plots can be a hassle.&lt;/p&gt;
&lt;p&gt;Streamlit supports these libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://matplotlib.org/&quot;&gt;matplotlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://altair-viz.github.io/&quot;&gt;altair&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bokeh.org/&quot;&gt;bokeh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plotly.com/python/&quot;&gt;plotly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://seaborn.pydata.org/&quot;&gt;seaborn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://deckgl.readthedocs.io/en/latest/layer.html&quot;&gt;PyDeck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/xflr6/graphviz&quot;&gt;GraphViz&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Modern plotting libraries like &lt;a href=&quot;https://plotly.com/python/&quot;&gt;plotly&lt;/a&gt;, &lt;a href=&quot;https://bokeh.org/&quot;&gt;bokeh&lt;/a&gt;, and &lt;a href=&quot;https://altair-viz.github.io/&quot;&gt;altair&lt;/a&gt; render directly to javascript. This means they are built for the web, and interactivity is built-in. This makes them better suited for web-apps. If you are going to make a dashboard, I recommend checking out one of these alternatives.&lt;/p&gt;
&lt;h2 id=&quot;sharing-your-dashboard&quot;&gt;Sharing your dashboard&lt;/h2&gt;
&lt;p&gt;Alright, so now that we have made a fancy looking dashboard, so that anyone can play with the data. How do we make it available?&lt;/p&gt;
&lt;p&gt;Streamlit uses a host/server model, which means you can run it on your own server.&lt;/p&gt;
&lt;p&gt;Easier is to use the &lt;a href=&quot;https://streamlit.io/cloud&quot;&gt;streamlit cloud&lt;/a&gt; to host your dashboard (it’s free for students and open-source projects). I found this also quite straightforward to set up. All I had to do was to create a &lt;a href=&quot;https://github.com/stefsmeets/dashboard_blog&quot;&gt;repository on github&lt;/a&gt; with the code and a requirements file.&lt;/p&gt;
&lt;p&gt;Then I logged into &lt;a href=&quot;https://share.streamlit.io/&quot;&gt;streamlit cloud&lt;/a&gt; using the Github SSO, and started a new app pointing at my repo and code.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://share.streamlit.io/stefsmeets/dashboard_blog/main&quot;&gt;Click here&lt;/a&gt; for the result! 🥳&lt;/p&gt;
&lt;h2 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h2&gt;
&lt;p&gt;In this blog post, I introduced streamlit and showed how it can be used to turn a python script into a dashboard, and host it online. An excellent way to showcase your research to a non-technical audience, if you ask me. The linear execution model makes it straightforward to adapt existing scripts. The code does not get in the way, and the result looks awesome.&lt;/p&gt;
&lt;p&gt;So next time you want to present some data in a notebook, consider using a dashboard instead.&lt;/p&gt;
&lt;p&gt;All the code in this blog post is available from &lt;a href=&quot;https://github.com/stefsmeets/dashboard_blog&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/forget-about-jupyter-notebooks-showcase--909c1674.D9XY027z.png" medium="image"/><author>Stef Smeets</author></item><item><title>Using machine learning to tell apart rain, snow, hail and fog from cell tower data</title><link>https://blog2.esciencecenter.nl/posts/2022-04-22---using-machine-learning-to-tell-apart-rain-snow-hail-and-fog-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-04-22---using-machine-learning-to-tell-apart-rain-snow-hail-and-fog-</guid><description>&lt;h1 id=&quot;using-machine-learning-to-tell-apart-rain-snow-hail-and-fog-from-cell-tower-data&quot;&gt;&lt;strong&gt;Using machine learning to tell apart rain, snow, hail and fog from cell tower data&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;][eScience Editorial Team]·Apr 21, 2022&lt;/p&gt;
&lt;p&gt;Next, **we explored whether CMLs can be used to detect &lt;strong&gt;fog&lt;/strong&gt;. Fog consists of droplets so small that they float in the air up to a few meters above the ground. The disdrometers do not pick up fog accurately enough to be used as target dataset. For this reason, we used an alternative target dataset to detect fog.&lt;/p&gt;
&lt;p&gt;Figure 3: CML attenuation signal (red) and target dataset (fog/no fog in blue) model fog prediction (fog/no fog in black) model fog threshold (dashed gray) for 31 August 2015.The relatively round fog droplets can scatter a wide range of wavelengths smaller than the droplets themselves. This includes visible light, making fog… foggy. Fog also affects wavelengths within the near-infrared range. Luckily, the experimental setup of the measurement campaign also included a near-infrared link (Figure 1), which we use as reference dataset of the foggiest time steps. Comparing the fog time series and the CML signal reveals a distinct drop of the CML signal which coincides with the fog occurrence (Figure 3). &lt;strong&gt;Once again we balance the dataset because the moments without fog far outnumber the fog events. After balancing the dataset and feeding the raw CML data into the McFly&lt;/strong&gt; algorithm, the result is a mere 49% accuracy. For a balanced two-class dataset, this is not better than just tossing a coin…&lt;/p&gt;
&lt;p&gt;It appears that the raw data for each individual time step is not enough to create a neural network that detects fog. However, the attenuation signal in the CML data shows a pattern associated with fog. This pattern changes over time, but &lt;strong&gt;McFly&lt;/strong&gt; does not automatically take the time dimension into consideration. Hence, to account for the temporal aspects, a rolling rate of change of the CML attenuation signal over 15 minutes is included for every time step as input to &lt;strong&gt;McFly&lt;/strong&gt;. On its own, this input value could be used to gain a validation accuracy of 67%, but combining it with the raw CML data brings it up to 73%. As a next step, we include additional inputs to the machine learning model to represent the time of the day and a time of the year, to allow the neural network to learn the climatology of fog. On its own, this correctly predicts fog 60% of the time steps, but when combined with the other data, the validation accuracy reaches 77%, which is a promising first step towards detecting not only rain, but also fog with CMLs.&lt;/p&gt;
&lt;p&gt;This blog is part of our blog series: The Small-Scale Initiative on Machine Learning, how did it go?, *where groups who were invited to participate in a project with eScience Center Research Software Engineers write about their projects and their experience.&lt;/p&gt;</description><pubDate>Fri, 22 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;using-machine-learning-to-tell-apart-rain-snow-hail-and-fog-from-cell-tower-data&quot;&gt;&lt;strong&gt;Using machine learning to tell apart rain, snow, hail and fog from cell tower data&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;][eScience Editorial Team]·Apr 21, 2022&lt;/p&gt;
&lt;p&gt;Next, **we explored whether CMLs can be used to detect &lt;strong&gt;fog&lt;/strong&gt;. Fog consists of droplets so small that they float in the air up to a few meters above the ground. The disdrometers do not pick up fog accurately enough to be used as target dataset. For this reason, we used an alternative target dataset to detect fog.&lt;/p&gt;
&lt;p&gt;Figure 3: CML attenuation signal (red) and target dataset (fog/no fog in blue) model fog prediction (fog/no fog in black) model fog threshold (dashed gray) for 31 August 2015.The relatively round fog droplets can scatter a wide range of wavelengths smaller than the droplets themselves. This includes visible light, making fog… foggy. Fog also affects wavelengths within the near-infrared range. Luckily, the experimental setup of the measurement campaign also included a near-infrared link (Figure 1), which we use as reference dataset of the foggiest time steps. Comparing the fog time series and the CML signal reveals a distinct drop of the CML signal which coincides with the fog occurrence (Figure 3). &lt;strong&gt;Once again we balance the dataset because the moments without fog far outnumber the fog events. After balancing the dataset and feeding the raw CML data into the McFly&lt;/strong&gt; algorithm, the result is a mere 49% accuracy. For a balanced two-class dataset, this is not better than just tossing a coin…&lt;/p&gt;
&lt;p&gt;It appears that the raw data for each individual time step is not enough to create a neural network that detects fog. However, the attenuation signal in the CML data shows a pattern associated with fog. This pattern changes over time, but &lt;strong&gt;McFly&lt;/strong&gt; does not automatically take the time dimension into consideration. Hence, to account for the temporal aspects, a rolling rate of change of the CML attenuation signal over 15 minutes is included for every time step as input to &lt;strong&gt;McFly&lt;/strong&gt;. On its own, this input value could be used to gain a validation accuracy of 67%, but combining it with the raw CML data brings it up to 73%. As a next step, we include additional inputs to the machine learning model to represent the time of the day and a time of the year, to allow the neural network to learn the climatology of fog. On its own, this correctly predicts fog 60% of the time steps, but when combined with the other data, the validation accuracy reaches 77%, which is a promising first step towards detecting not only rain, but also fog with CMLs.&lt;/p&gt;
&lt;p&gt;This blog is part of our blog series: The Small-Scale Initiative on Machine Learning, how did it go?, *where groups who were invited to participate in a project with eScience Center Research Software Engineers write about their projects and their experience.&lt;/p&gt;</content:encoded><author>eScience Editorial Team</author></item><item><title>A letter to my parents about my experience in a machine learning consultancy project</title><link>https://blog2.esciencecenter.nl/posts/2022-04-14---a-letter-to-my-parents-about-my-experience-in-a-machine-lear</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-04-14---a-letter-to-my-parents-about-my-experience-in-a-machine-lear</guid><description>&lt;p&gt;&lt;em&gt;What does a Research Software Engineer do? This is not always easy to answer, but when your parents are asking, you definitely want to give a nice answer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A fountain pen writing on a piece of paper.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1051&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yseerb7z2bld7brhdY2y1A-0749df51.DqZc0FYE_1RsLve.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A fountain pen writing on a piece of paper.&lt;/p&gt;
&lt;p&gt;Dear Mum and Dad,&lt;/p&gt;
&lt;p&gt;I always wonder how you picture my daily work at the Netherlands eScience Center. Probably you imagine me sitting behind a computer all day. I think you know by now that I also sometimes talk to scientists, mostly from the healthcare domain. To give you a better feeling of the kind of things I do I decided to write you about my experience in the &lt;em&gt;Automated Video-based Assessment of Movement Disorders&lt;/em&gt; project.&lt;/p&gt;
&lt;p&gt;Automated Video-based Assessment of Movement Disorders… That is a mouth full of words. Let me try to explain what I did in this project.&lt;/p&gt;
&lt;p&gt;This project is in collaboration with &lt;a href=&quot;https://www.amsterdamumc.org/en/research/researchers/helga-haberfehlner.htm&quot;&gt;Helga Haberfehlner&lt;/a&gt; and her colleagues who work at the Department of Rehabilitation medicine of the Amsterdam UMC. Helga is a kind, energetic, and passionate researcher who is trying to improve the diagnosis and treatment of movement disorders in children.&lt;/p&gt;
&lt;p&gt;One of the problems they face in the clinic is how to objectively determine how severe such a movement disorder is and how it progresses over time. This is important to know because it helps the doctors pick the right treatment, or give them an idea about whether a treatment is working. In one such method a video of the patient is recorded. The video is then observed by a doctor who is trained to carefully look at the movements of the body. The doctor gives a score between 0 and 4 for how bad a particular set of symptoms is in a particular body part. For example, the doctor could rate the symptoms in the left lower arm as a 3. If, for example, after a year of medical treatment this score goes to 1 this indicates that the treatment is working.&lt;/p&gt;
&lt;p&gt;Now the problem is that it is quite difficult to score the symptoms of a patient. Different doctors tend to look at different things. Even the same doctor looking at the same video could give a low score on an optimistic day, and a high score on a pessimistic day. Also, it takes a lot of time for the doctors to do this correctly, time that is better spent on care for the patients instead of looking at videos. So, the doctors would be helped a lot if the scoring of these videos could be done automatically by a computer. Together with my eScience Center colleagues Florian Huber and Sonja Georgievska we set out to help Helga and her colleagues from the Amsterdam UMC.&lt;/p&gt;
&lt;p&gt;In most of the projects at the eScience Center we build computer programs with input from the domain scientists we work together with. These are long projects, taking at least 2 years. But in this project (the so-called Small-Scale-Initiative Machine Learning project) we only had half a year in which we mostly gave advise on the activities that the researchers perform themselves. The good thing is that this is exactly what Helga needed: technological expertise. And by doing projects in such a way we could actually not just help Helga and her colleagues, but also 11 other such projects from a diverse range of scientific disciplines.&lt;/p&gt;
&lt;p&gt;How did we help Helga and her colleagues? We mostly gave advise on a technique called ‘Machine Learning’. It is a technology that teaches a computer how to do a task by showing it examples of how to do it. In our case, the computer had to learn how to give a score between 0 and 4 indicating how bad the symptoms of a movement disorder are in the patient in the video. We managed to teach the computer how to do it reasonably well, although there is still some work needed before doctors can start using this technique. You can see our results in our &lt;a href=&quot;https://github.com/RehabAUmc/modys-video&quot;&gt;Github repository&lt;/a&gt; (I might explain more about Github in another letter 😉). We are also working on writing our conclusions down in a scientific article (&lt;strong&gt;@dad&lt;/strong&gt; I hope we get as much attention as &lt;a href=&quot;https://library.wur.nl/ojs/index.php/njas/article/view/16546&quot;&gt;you got in the glory of your soil-researching period&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;What I most enjoyed in this project is the fruitful collaboration that we had. I think Helga and her colleagues learned a lot from the technological expertise we could offer. Helga even started to (successfully) do more programming herself. But the other way around we learned a lot about how to apply machine learning techniques in a clinical setting. We even got a tour around Helga’s department where she showed us all the devices that they use to investigate movement disorders.&lt;/p&gt;
&lt;p&gt;I hope this gives you a bit of a feeling for what I do at the Netherlands eScience Center.&lt;/p&gt;
&lt;p&gt;Lots of love,&lt;/p&gt;
&lt;p&gt;Sven&lt;/p&gt;</description><pubDate>Thu, 14 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;What does a Research Software Engineer do? This is not always easy to answer, but when your parents are asking, you definitely want to give a nice answer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A fountain pen writing on a piece of paper.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1051&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yseerb7z2bld7brhdY2y1A-0749df51.DqZc0FYE_1RsLve.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A fountain pen writing on a piece of paper.&lt;/p&gt;
&lt;p&gt;Dear Mum and Dad,&lt;/p&gt;
&lt;p&gt;I always wonder how you picture my daily work at the Netherlands eScience Center. Probably you imagine me sitting behind a computer all day. I think you know by now that I also sometimes talk to scientists, mostly from the healthcare domain. To give you a better feeling of the kind of things I do I decided to write you about my experience in the &lt;em&gt;Automated Video-based Assessment of Movement Disorders&lt;/em&gt; project.&lt;/p&gt;
&lt;p&gt;Automated Video-based Assessment of Movement Disorders… That is a mouth full of words. Let me try to explain what I did in this project.&lt;/p&gt;
&lt;p&gt;This project is in collaboration with &lt;a href=&quot;https://www.amsterdamumc.org/en/research/researchers/helga-haberfehlner.htm&quot;&gt;Helga Haberfehlner&lt;/a&gt; and her colleagues who work at the Department of Rehabilitation medicine of the Amsterdam UMC. Helga is a kind, energetic, and passionate researcher who is trying to improve the diagnosis and treatment of movement disorders in children.&lt;/p&gt;
&lt;p&gt;One of the problems they face in the clinic is how to objectively determine how severe such a movement disorder is and how it progresses over time. This is important to know because it helps the doctors pick the right treatment, or give them an idea about whether a treatment is working. In one such method a video of the patient is recorded. The video is then observed by a doctor who is trained to carefully look at the movements of the body. The doctor gives a score between 0 and 4 for how bad a particular set of symptoms is in a particular body part. For example, the doctor could rate the symptoms in the left lower arm as a 3. If, for example, after a year of medical treatment this score goes to 1 this indicates that the treatment is working.&lt;/p&gt;
&lt;p&gt;Now the problem is that it is quite difficult to score the symptoms of a patient. Different doctors tend to look at different things. Even the same doctor looking at the same video could give a low score on an optimistic day, and a high score on a pessimistic day. Also, it takes a lot of time for the doctors to do this correctly, time that is better spent on care for the patients instead of looking at videos. So, the doctors would be helped a lot if the scoring of these videos could be done automatically by a computer. Together with my eScience Center colleagues Florian Huber and Sonja Georgievska we set out to help Helga and her colleagues from the Amsterdam UMC.&lt;/p&gt;
&lt;p&gt;In most of the projects at the eScience Center we build computer programs with input from the domain scientists we work together with. These are long projects, taking at least 2 years. But in this project (the so-called Small-Scale-Initiative Machine Learning project) we only had half a year in which we mostly gave advise on the activities that the researchers perform themselves. The good thing is that this is exactly what Helga needed: technological expertise. And by doing projects in such a way we could actually not just help Helga and her colleagues, but also 11 other such projects from a diverse range of scientific disciplines.&lt;/p&gt;
&lt;p&gt;How did we help Helga and her colleagues? We mostly gave advise on a technique called ‘Machine Learning’. It is a technology that teaches a computer how to do a task by showing it examples of how to do it. In our case, the computer had to learn how to give a score between 0 and 4 indicating how bad the symptoms of a movement disorder are in the patient in the video. We managed to teach the computer how to do it reasonably well, although there is still some work needed before doctors can start using this technique. You can see our results in our &lt;a href=&quot;https://github.com/RehabAUmc/modys-video&quot;&gt;Github repository&lt;/a&gt; (I might explain more about Github in another letter 😉). We are also working on writing our conclusions down in a scientific article (&lt;strong&gt;@dad&lt;/strong&gt; I hope we get as much attention as &lt;a href=&quot;https://library.wur.nl/ojs/index.php/njas/article/view/16546&quot;&gt;you got in the glory of your soil-researching period&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;What I most enjoyed in this project is the fruitful collaboration that we had. I think Helga and her colleagues learned a lot from the technological expertise we could offer. Helga even started to (successfully) do more programming herself. But the other way around we learned a lot about how to apply machine learning techniques in a clinical setting. We even got a tour around Helga’s department where she showed us all the devices that they use to investigate movement disorders.&lt;/p&gt;
&lt;p&gt;I hope this gives you a bit of a feeling for what I do at the Netherlands eScience Center.&lt;/p&gt;
&lt;p&gt;Lots of love,&lt;/p&gt;
&lt;p&gt;Sven&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_yseerb7z2bld7brhdY2y1A-0749df51.DqZc0FYE.jpeg" medium="image"/><author>Sven van der Burg</author></item><item><title>Can machine learning help us improve stroke rehabilitation? A step towards personalized therapy</title><link>https://blog2.esciencecenter.nl/posts/2022-04-11---can-machine-learning-help-us-improve-stroke-rehabilitation-a</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-04-11---can-machine-learning-help-us-improve-stroke-rehabilitation-a</guid><description>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Along the way, the biggest issue was our data set itself. Because data collection of human movements is a job that takes time and our patient group is small, we only have a limited amount of data available. At the same time, the data set is highly variable, which makes the problem more difficult for Machine Learning.&lt;/p&gt;
&lt;p&gt;In next steps for this project, we are exploring the results and trying to translate them into information that is valuable for our research field. At the same time, we are in the early stages of a data sharing effort, with those who may have similar data sets. That way, we will be able to increase the size of our training set.&lt;/p&gt;
&lt;p&gt;The first result can be seen in the figure below. It shows the distribution of the different people (who were part of a study) using two latent features of a variational autoencoder. By creating the whole-body movement from the latent space, we were able to show the gait patterns which represented the people in the different areas of the two-dimensional latent space. In the future, this will help to evaluate a patient’s gait and their improvement during and after rehabilitation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can machine learning help us improve stroke rehabilitation? A step towards personalized therapy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-machine-learning-help-us-improve-str-99a7ce23.Dh8iiFLS_1EeUN9.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://research.vu.nl/en/persons/sina-david&quot;&gt;Dr. Sina David**&lt;/a&gt; Assistant Professor in the Faculty of Behavioural and Movement Sciences, Neuromechanics and AMS-Rehabilitation &amp;#x26; Development at Vrije Universeit Amsterdam. Follow her on Twitter &lt;a href=&quot;https://twitter.com/SinaDavid1907&quot;&gt;@SinaDavid1907&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.internationalhu.com/research/researchers/michiel-punt&quot;&gt;&lt;strong&gt;Dr. Michiel Punt&lt;/strong&gt;&lt;/a&gt; Senior researcher at HU University of Applied Sciences Utrecht. He is also a Postdoc researcher at VU Amsterdam. Follow him on Twitter &lt;a href=&quot;https://twitter.com/MichielPunt&quot;&gt;@MichielPunt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://research.vu.nl/en/persons/yuge-zhang&quot;&gt;&lt;strong&gt;Yuge Yhang&lt;/strong&gt;&lt;/a&gt; External PhD Candidate at the Faculty of Behavioural and Movement Sciences, Neuromechanics and AMS-Ageing &amp;#x26; Vitality. Follow her on Twitter &lt;a href=&quot;https://twitter.com/yugezhang5&quot;&gt;@yugezhang5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Learn more by visiting &lt;a href=&quot;https://www.human-movement-sciences.nl/nm/&quot;&gt;human-movement-sciences.nl/nm&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The work described in this blog is supported by research software engineers (RSEs) of the Netherlands eScience Center, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-cunliang-geng/&quot;&gt;Dr. Cunliang Geng&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/yang-liu/&quot;&gt;Dr. Yang Liu&lt;/a&gt; and Dr. [Sonja Georgievska].&lt;/p&gt;</description><pubDate>Mon, 11 Apr 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Along the way, the biggest issue was our data set itself. Because data collection of human movements is a job that takes time and our patient group is small, we only have a limited amount of data available. At the same time, the data set is highly variable, which makes the problem more difficult for Machine Learning.&lt;/p&gt;
&lt;p&gt;In next steps for this project, we are exploring the results and trying to translate them into information that is valuable for our research field. At the same time, we are in the early stages of a data sharing effort, with those who may have similar data sets. That way, we will be able to increase the size of our training set.&lt;/p&gt;
&lt;p&gt;The first result can be seen in the figure below. It shows the distribution of the different people (who were part of a study) using two latent features of a variational autoencoder. By creating the whole-body movement from the latent space, we were able to show the gait patterns which represented the people in the different areas of the two-dimensional latent space. In the future, this will help to evaluate a patient’s gait and their improvement during and after rehabilitation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can machine learning help us improve stroke rehabilitation? A step towards personalized therapy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;512&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-machine-learning-help-us-improve-str-99a7ce23.Dh8iiFLS_1EeUN9.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://research.vu.nl/en/persons/sina-david&quot;&gt;Dr. Sina David**&lt;/a&gt; Assistant Professor in the Faculty of Behavioural and Movement Sciences, Neuromechanics and AMS-Rehabilitation &amp;#x26; Development at Vrije Universeit Amsterdam. Follow her on Twitter &lt;a href=&quot;https://twitter.com/SinaDavid1907&quot;&gt;@SinaDavid1907&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.internationalhu.com/research/researchers/michiel-punt&quot;&gt;&lt;strong&gt;Dr. Michiel Punt&lt;/strong&gt;&lt;/a&gt; Senior researcher at HU University of Applied Sciences Utrecht. He is also a Postdoc researcher at VU Amsterdam. Follow him on Twitter &lt;a href=&quot;https://twitter.com/MichielPunt&quot;&gt;@MichielPunt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://research.vu.nl/en/persons/yuge-zhang&quot;&gt;&lt;strong&gt;Yuge Yhang&lt;/strong&gt;&lt;/a&gt; External PhD Candidate at the Faculty of Behavioural and Movement Sciences, Neuromechanics and AMS-Ageing &amp;#x26; Vitality. Follow her on Twitter &lt;a href=&quot;https://twitter.com/yugezhang5&quot;&gt;@yugezhang5&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Learn more by visiting &lt;a href=&quot;https://www.human-movement-sciences.nl/nm/&quot;&gt;human-movement-sciences.nl/nm&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The work described in this blog is supported by research software engineers (RSEs) of the Netherlands eScience Center, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-cunliang-geng/&quot;&gt;Dr. Cunliang Geng&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/yang-liu/&quot;&gt;Dr. Yang Liu&lt;/a&gt; and Dr. [Sonja Georgievska].&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/can-machine-learning-help-us-improve-str-99a7ce23.Dh8iiFLS.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>How machine learning could help Simone to play Ludo</title><link>https://blog2.esciencecenter.nl/posts/2022-03-31---how-machine-learning-could-help-simone-to-play-ludo</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-03-31---how-machine-learning-could-help-simone-to-play-ludo</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;629&quot; height=&quot;626&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ii34FkLcmA3bYfAhLaNzZw-f35a5f15.9C07PfCF_Z2ssRMh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simone is a 12 year old girl. She loves to play Ludo with her mum, dad and her little brother. However, when she pushes the dice switch in the middle of the Ludo board game, she cannot properly control her movements and the tokens sometimes fall from the board. Simone also does not succeed to move the tokens, so her dad does that for her. Simone has &lt;a href=&quot;https://cerebralpalsy.org.au/our-research/about-cerebral-palsy/what-is-cerebral-palsy/types-of-cerebral-palsy/dyskinetic-cerebral-palsy/&quot;&gt;dyskinetic cerebral palsy&lt;/a&gt;, due to a lack of oxygen around birth. &lt;a href=&quot;https://www.youtube.com/watch?v=-2ODMPVjnI8&quot;&gt;Involuntary movements&lt;/a&gt; (called dystonia and choreo-athetosis) disturb her during daily activities such as playing Ludo.&lt;/p&gt;
&lt;p&gt;At &lt;a href=&quot;https://www.amc.nl/web/home.htm&quot;&gt;Amsterdam UMC&lt;/a&gt;, we treat children with severe dyskinetic cerebral palsy with medication that is directly delivered into the spinal canal by an indwelling pump (intrathecal baclofen). This treatment has been shown to be &lt;a href=&quot;https://research.vumc.nl/en/publications/the-effect-of-intrathecal-baclofen-in-dyskinetic-cerebral-palsy-t&quot;&gt;effective in reaching individual goals&lt;/a&gt; (such as not overthrowing the tokens when playing Ludo). However, we currently have a hard time to exactly monitor the involuntary movements and the effect of treatments on them. This monitoring is very important to give the right doses of medication. During check-ups at the hospital, doctors ask parents and children, how movements evolve and observe the children in the consultation room. However, in this way, we are only able to capture a snapshot within the hospital environment of the involuntary movements. Therefore we are seeking for options to measure movements within the natural environment of the children (such as home and school), and to automatize the evaluation to make it not too time consuming for the doctors.&lt;/p&gt;
&lt;p&gt;Activity recognition applications using sensors integrated in smartphones and smartwatches for sports and fitness are increasingly used and could possibly serve this purpose. Machine learning models integrated in the devices can distinguish between movements such as walking, jogging, climbing, running and swimming. Hence, such sensors might be a good candidate to detect and monitor the involuntary movements of Simone while playing Ludo. Furthermore, as also information extracted from videos could be useful, parents could easily film children at home with their smartphones, to obtain additional information.&lt;/p&gt;
&lt;p&gt;We have recently started to explore the possibilities for automatic detection of involuntary movements in children with dyskinetic cerebral palsy in the home situation. &lt;a href=&quot;https://www.zonmw.nl/nl/&quot;&gt;ZonMw&lt;/a&gt; financed our project &lt;a href=&quot;https://www.zonmw.nl/nl/over-zonmw/e-health-en-ict-in-de-zorg/programmas/project-detail/imdi/home-based-measurements-of-dyskinesia-using-smartphone-coupled-inertial-sensor-technology-and-machin/&quot;&gt;MODYS@home&lt;/a&gt; to use smartwatch-like sensors at home for the assessment of involuntary movements. With this support, we could develop an app to measure sensor data together with synchronized videos during daily activities.&lt;/p&gt;
&lt;p&gt;We also received help from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; within the ‘Open Call for Small-Scale Initiatives in Machine Learning’. Within this project called ‘Automated video-based movement assessment using machine learning to support personalized treatment of movement disorders’, we focus on the option to use videos. We use stick figure movies extracted from real videos.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1008&quot; height=&quot;351&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PTuJhzxNcKIFmheeUzrJ-Q-d856fa57.Ce9bToPd_1sDBMA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Real videos were selected from other projects, that had have been scored by the doctor for involuntary movements (dystonia) for the arms and legs. With these data we trained machine learning models to predict dystonia automatically.&lt;/p&gt;
&lt;p&gt;Using machine learning within the field of clinical movement analysis was something new for us, as not only the content was new, but also the style of working with stand-up meetings and sprints, sharing codes on Github and right away publishing our dataset. We gained new knowledge and skills that brings us a step forwards to find a way to measure children with dyskinetic cerebral palsy within their home environment.&lt;/p&gt;
&lt;p&gt;We are very excited about the results from a random forest regressor, “a traditional machine learning model” as such a model is called in the language used in machine learning world;-) See figure for the result: the true score by the doctor is plotted against the predicted value by the model. All scores on the diagonal line are predicted completely correct. The model is not perfect yet, but it shows the potential of the method and we are looking very much forward to further improve it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;630&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KmttTsBaqVJTtIK0TcEPog-969729b8.DAoBIP9U_2rwg97.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Within our projects we work within a group of clinicians, researchers and software engineers from the &lt;a href=&quot;https://www.amsterdamumc.org/en/research/organization/about-amsterdam-umc.htm&quot;&gt;Amsterdam UMC&lt;/a&gt; (Annemieke Buizer, Laura Bonouvrié, Marjolein van der Krogt, Helga Haberfehlner, Shankara van der Ven, Dylan den Hartog), from the TU Delft (Jaap Harlaar), from &lt;a href=&quot;https://moveshelf.com/&quot;&gt;Moveshelf&lt;/a&gt; (Ignazio Aleo, Johannes Gijsbers) and the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; (&lt;a href=&quot;https://www.esciencecenter.nl/team/sven-van-der-burg/&quot;&gt;Sven van der Burg&lt;/a&gt;, Florian Huber and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-sonja-georgievska/&quot;&gt;Sonja Georgievska&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you are interested in more technical details please have a look at our &lt;a href=&quot;https://zenodo.org/deposit/5638470&quot;&gt;stick figure dataset&lt;/a&gt;. All contribution to our &lt;a href=&quot;https://github.com/RehabAUmc/modys-video&quot;&gt;code&lt;/a&gt; is welcome, to help Simone to play Ludo without overthrowing the tokens!&lt;/p&gt;</description><pubDate>Thu, 31 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;629&quot; height=&quot;626&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ii34FkLcmA3bYfAhLaNzZw-f35a5f15.9C07PfCF_Z2ssRMh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simone is a 12 year old girl. She loves to play Ludo with her mum, dad and her little brother. However, when she pushes the dice switch in the middle of the Ludo board game, she cannot properly control her movements and the tokens sometimes fall from the board. Simone also does not succeed to move the tokens, so her dad does that for her. Simone has &lt;a href=&quot;https://cerebralpalsy.org.au/our-research/about-cerebral-palsy/what-is-cerebral-palsy/types-of-cerebral-palsy/dyskinetic-cerebral-palsy/&quot;&gt;dyskinetic cerebral palsy&lt;/a&gt;, due to a lack of oxygen around birth. &lt;a href=&quot;https://www.youtube.com/watch?v=-2ODMPVjnI8&quot;&gt;Involuntary movements&lt;/a&gt; (called dystonia and choreo-athetosis) disturb her during daily activities such as playing Ludo.&lt;/p&gt;
&lt;p&gt;At &lt;a href=&quot;https://www.amc.nl/web/home.htm&quot;&gt;Amsterdam UMC&lt;/a&gt;, we treat children with severe dyskinetic cerebral palsy with medication that is directly delivered into the spinal canal by an indwelling pump (intrathecal baclofen). This treatment has been shown to be &lt;a href=&quot;https://research.vumc.nl/en/publications/the-effect-of-intrathecal-baclofen-in-dyskinetic-cerebral-palsy-t&quot;&gt;effective in reaching individual goals&lt;/a&gt; (such as not overthrowing the tokens when playing Ludo). However, we currently have a hard time to exactly monitor the involuntary movements and the effect of treatments on them. This monitoring is very important to give the right doses of medication. During check-ups at the hospital, doctors ask parents and children, how movements evolve and observe the children in the consultation room. However, in this way, we are only able to capture a snapshot within the hospital environment of the involuntary movements. Therefore we are seeking for options to measure movements within the natural environment of the children (such as home and school), and to automatize the evaluation to make it not too time consuming for the doctors.&lt;/p&gt;
&lt;p&gt;Activity recognition applications using sensors integrated in smartphones and smartwatches for sports and fitness are increasingly used and could possibly serve this purpose. Machine learning models integrated in the devices can distinguish between movements such as walking, jogging, climbing, running and swimming. Hence, such sensors might be a good candidate to detect and monitor the involuntary movements of Simone while playing Ludo. Furthermore, as also information extracted from videos could be useful, parents could easily film children at home with their smartphones, to obtain additional information.&lt;/p&gt;
&lt;p&gt;We have recently started to explore the possibilities for automatic detection of involuntary movements in children with dyskinetic cerebral palsy in the home situation. &lt;a href=&quot;https://www.zonmw.nl/nl/&quot;&gt;ZonMw&lt;/a&gt; financed our project &lt;a href=&quot;https://www.zonmw.nl/nl/over-zonmw/e-health-en-ict-in-de-zorg/programmas/project-detail/imdi/home-based-measurements-of-dyskinesia-using-smartphone-coupled-inertial-sensor-technology-and-machin/&quot;&gt;MODYS@home&lt;/a&gt; to use smartwatch-like sensors at home for the assessment of involuntary movements. With this support, we could develop an app to measure sensor data together with synchronized videos during daily activities.&lt;/p&gt;
&lt;p&gt;We also received help from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; within the ‘Open Call for Small-Scale Initiatives in Machine Learning’. Within this project called ‘Automated video-based movement assessment using machine learning to support personalized treatment of movement disorders’, we focus on the option to use videos. We use stick figure movies extracted from real videos.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1008&quot; height=&quot;351&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PTuJhzxNcKIFmheeUzrJ-Q-d856fa57.Ce9bToPd_1sDBMA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Real videos were selected from other projects, that had have been scored by the doctor for involuntary movements (dystonia) for the arms and legs. With these data we trained machine learning models to predict dystonia automatically.&lt;/p&gt;
&lt;p&gt;Using machine learning within the field of clinical movement analysis was something new for us, as not only the content was new, but also the style of working with stand-up meetings and sprints, sharing codes on Github and right away publishing our dataset. We gained new knowledge and skills that brings us a step forwards to find a way to measure children with dyskinetic cerebral palsy within their home environment.&lt;/p&gt;
&lt;p&gt;We are very excited about the results from a random forest regressor, “a traditional machine learning model” as such a model is called in the language used in machine learning world;-) See figure for the result: the true score by the doctor is plotted against the predicted value by the model. All scores on the diagonal line are predicted completely correct. The model is not perfect yet, but it shows the potential of the method and we are looking very much forward to further improve it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;630&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KmttTsBaqVJTtIK0TcEPog-969729b8.DAoBIP9U_2rwg97.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Within our projects we work within a group of clinicians, researchers and software engineers from the &lt;a href=&quot;https://www.amsterdamumc.org/en/research/organization/about-amsterdam-umc.htm&quot;&gt;Amsterdam UMC&lt;/a&gt; (Annemieke Buizer, Laura Bonouvrié, Marjolein van der Krogt, Helga Haberfehlner, Shankara van der Ven, Dylan den Hartog), from the TU Delft (Jaap Harlaar), from &lt;a href=&quot;https://moveshelf.com/&quot;&gt;Moveshelf&lt;/a&gt; (Ignazio Aleo, Johannes Gijsbers) and the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; (&lt;a href=&quot;https://www.esciencecenter.nl/team/sven-van-der-burg/&quot;&gt;Sven van der Burg&lt;/a&gt;, Florian Huber and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-sonja-georgievska/&quot;&gt;Sonja Georgievska&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you are interested in more technical details please have a look at our &lt;a href=&quot;https://zenodo.org/deposit/5638470&quot;&gt;stick figure dataset&lt;/a&gt;. All contribution to our &lt;a href=&quot;https://github.com/RehabAUmc/modys-video&quot;&gt;code&lt;/a&gt; is welcome, to help Simone to play Ludo without overthrowing the tokens!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_PTuJhzxNcKIFmheeUzrJ-Q-d856fa57.Ce9bToPd.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>How to find your Artificial Intelligence explainer</title><link>https://blog2.esciencecenter.nl/posts/2022-03-21---how-to-find-your-artificial-intelligence-explainer</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-03-21---how-to-find-your-artificial-intelligence-explainer</guid><description>&lt;p&gt;Here, we will use the LRP method to illustrate the principle of determining which features in an input contribute most strongly to the output of a trained DNN model. In this example, the input to the network is an image.** We are interested in figuring out the relevance* of each image pixel to a given image class. This could be the final DNN classification decision for that image (“cat”) or any other class known to the model (e.g. “dog”, “cow”, “bee”, etc. if the model is trained to classify animals). The output relevance is considered a weighted sum of the relevancies of all the &lt;strong&gt;pixels&lt;/strong&gt; of the input image. The relevance at the output node in the network graph is decomposed by iterative propagation backward through the network layers until the input layer. The trained model weights are used in this decomposition. Using this &lt;em&gt;relevance propagation&lt;/em&gt; process, the final *relevance scores map *(&lt;em&gt;or heatmap&lt;/em&gt;) is obtained. The final relevance map gives us an indication for the DNN’s hidden logic.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your Artificial Intelligence explainer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;157&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-2cffbfad.DW7BdbFW_1h3U9m.webp&quot; srcset=&quot;&quot;&gt;
Relevance scores of the image pixels in respect to the class “cat” obtained via relevance propagation.Besides LRP, there are many other XAI methods, which use different ways of determining relevance. In order to determine which of the plethora of post-hoc XAI methods to include in DIANNA, we started by compiling an initial list of 18 XAI post-hoc feature-relevance methods following &lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S1566253519308103&quot;&gt;&lt;em&gt;Arrieta et al. (2020)&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deep Taylor decomposition (DTD):&lt;/strong&gt; &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0031320316303582&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://www.youtube.com/watch?v=gy_Cb4Do_YE&quot;&gt;Presentation&lt;/a&gt;| &lt;a href=&quot;https://github.com/marcoancona/DeepExplain&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**Layer-wise Relevance Propagation (LRP): **&lt;a href=&quot;https://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0130140&quot;&gt;Paper&lt;/a&gt;|&lt;a href=&quot;http://danshiebler.com/2017-04-16-deep-taylor-lrp/&quot;&gt;Blog&lt;/a&gt;| &lt;a href=&quot;https://github.com/albermax/innvestigate&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**Integrated Gradients (IG): **&lt;a href=&quot;https://arxiv.org/pdf/1703.01365.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://captum.ai/docs/extension/integrated_gradients/&quot;&gt;Tutorial&lt;/a&gt;| &lt;a href=&quot;https://github.com/pytorch/captum&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local Interpretable Model-agnostic Explanations (LIME):&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/1602.04938&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://towardsdatascience.com/lime-how-to-interpret-machine-learning-models-with-python-94b0e7e4432e&quot;&gt;Blog&lt;/a&gt;| &lt;a href=&quot;https://github.com/marcotcr/lime&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**SHapley Additive exPlanations (SHAP): **&lt;a href=&quot;https://arxiv.org/abs/1705.07874&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://towardsdatascience.com/shap-how-to-interpret-machine-learning-models-with-python-2323f5af4be9&quot;&gt;Blog&lt;/a&gt;|&lt;a href=&quot;https://github.com/slundberg/shap&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**PatternNet &lt;strong&gt;and&lt;/strong&gt; PatternAttribution: **&lt;a href=&quot;https://arxiv.org/pdf/1705.05598.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/albermax/innvestigate&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep Learning Important FeaTures (DeepLIFT):&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/pdf/1704.02685.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;http://goo.gl/qKb7pL&quot;&gt;Tutorial&lt;/a&gt;| &lt;a href=&quot;https://vimeo.com/238275076&quot;&gt;Presentation&lt;/a&gt;| &lt;a href=&quot;https://github.com/marcoancona/DeepExplain&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**SmoothGrad: **&lt;a href=&quot;https://arxiv.org/abs/1706.03825&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://pair-code.github.io/saliency/&quot;&gt;Demo&lt;/a&gt;| &lt;a href=&quot;https://github.com/pair-code/saliency&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**CLass-Enhanced Attentive Response(CLEAR): **&lt;a href=&quot;https://openaccess.thecvf.com/content_cvpr_2017_workshops/w26/papers/Kumar_Explaining_the_Unexplained_CVPR_2017_paper.pdf&quot;&gt;Paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(Adaptive) deconvolutional network (Deconvnet):&lt;/strong&gt; [Paper](&lt;a href=&quot;https://link.springer.com/content/pdf/10.1007/978-3-319-10590-1_53.pdf&quot;&gt;https://link.springer.com/content/pdf/10.1007/978-3-319-10590-1_53.pdf&lt;/a&gt; &lt;a href=&quot;https://www.matthewzeiler.com/mattzeiler/adaptivedeconvolutional.pdf&quot;&gt;https://www.matthewzeiler.com/mattzeiler/adaptivedeconvolutional.pdf&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;**Gradient-weighted Class Activation Mapping (Grad-CAM): **&lt;a href=&quot;https://ieeexplore.ieee.org/document/8237336&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://www.pyimagesearch.com/2020/03/09/grad-cam-visualize-class-activation-maps-with-keras-tensorflow-and-deep-learning/&quot;&gt;Blog&lt;/a&gt;|&lt;a href=&quot;https://github.com/ramprs/grad-cam/&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**Randomized input sampling for explanation of black-box models (RISE): **&lt;a href=&quot;https://arxiv.org/abs/1806.07421&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/facebookresearch/TorchRay&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extremal Perturbations (EP)| &lt;a href=&quot;https://openaccess.thecvf.com/content_ICCV_2019/papers/Fong_Understanding_Deep_Networks_via_Extremal_Perturbations_and_Smooth_Masks_ICCV_2019_paper.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/facebookresearch/TorchRay&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Saliency Analysis (SA): &lt;a href=&quot;https://arxiv.org/pdf/1312.6034.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/osu-xai/pytorch-saliency&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anchors: &lt;a href=&quot;https://homes.cs.washington.edu/~marcotcr/aaai18.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/viadee/javaAnchorExplainer&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Deep visualization: &lt;a href=&quot;https://arxiv.org/pdf/1506.06579.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://yosinski.com/deepvis&quot;&gt;Demo&lt;/a&gt;| &lt;a href=&quot;https://github.com/yosinski/deep-visualization-toolbox&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AutomaticSTRucture IDentification (ASTRID): &lt;a href=&quot;https://arxiv.org/pdf/1707.07576.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/bwrc/astrid-r&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We excluded all XAI methods without a working and well-maintained open-source implementation or proven user community. That resulted in a subset of the &lt;strong&gt;13 methods&lt;/strong&gt; highlighted above.&lt;/p&gt;
&lt;h3 id=&quot;evaluation-criteria&quot;&gt;&lt;em&gt;&lt;strong&gt;Evaluation criteria&lt;/strong&gt;&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;The large variety of XAI approaches benefits the AI community by providing freedom in the search for explainability. However, it also increases the difficulty of choosing the most appropriate method for each use case. Every XAI approach has pros and cons. In order to select the best methods for our task, we needed a framework to evaluate these methods systematically. Fortunately, this topic has already been visited by the XAI researchers and there is an extensive list of objective criteria defined in the &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3351095.3372870&quot;&gt;Explainability fact sheet&lt;/a&gt; paper [&lt;em&gt;Sokol, K., &amp;#x26; Flach, P. (2020)&lt;/em&gt;]. The authors look at an abundant set of XAI aspects and cluster the requirements towards an explainer into **5 groups **(or &lt;strong&gt;dimensions&lt;/strong&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functional (F1-F9)&lt;/li&gt;
&lt;li&gt;Operational (O1-O10)&lt;/li&gt;
&lt;li&gt;Usability (U1-U11)&lt;/li&gt;
&lt;li&gt;Safety (S1-S4)&lt;/li&gt;
&lt;li&gt;Validation (V1-V2)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For each dimension, there are specific criteria, e.g. the “Functional” group has 9 and in total there are 36 criteria. We will describe our choices next.&lt;/p&gt;
&lt;h3 id=&quot;the-selection&quot;&gt;&lt;em&gt;&lt;strong&gt;The selection&lt;/strong&gt;&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;In our &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA project&lt;/a&gt;, we built a Python package that brings XAI to non (X)AI experts and various scientific domain researchers. The XAI methods to be included in the package had to have the capacity to work with different types of data, various AI architectures and we chose to focus on the model explanation. Most importantly, the resulting explanations had to be easy to interpret. Based on our goals, we have compiled a shortlist of &lt;strong&gt;18 requirements&lt;/strong&gt; from the 36 requirements in the &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3351095.3372870&quot;&gt;XAI fact sheet&lt;/a&gt;. Using these relevant for our target users’ requirements, we evaluated the selected 13 methods listed in the XAI overview section.&lt;/p&gt;
&lt;p&gt;Apart from the requirements on the list, we have also considered the similarity and the “popularity” of these methods, the quality of the existing implementations, and the difficulty of integrating them in DIANNA. The evaluation procedure can be summarized with the table shown below: (&lt;strong&gt;Deconvnet&lt;/strong&gt; and &lt;strong&gt;GradCAM&lt;/strong&gt; are filtered out since they can only work with Convolutional NNs and are therefore not included in the table.)&lt;/p&gt;
&lt;p&gt;Finally, we narrowed down our list to &lt;strong&gt;5 methods:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Layer-wise Relevance Propagation (LRP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local Interpretable Model-agnostic Explanations (LIME)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SHapley Additive exPlanations (SHAP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PatternAttribution (PA)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Randomized input sampling for explanation of black-box models (RISE)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Within limited project time, we were able to include three of them in our &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA library&lt;/a&gt;: RISE, LIME &amp;#x26; SHAP. A preview of the explanations that we obtained using our DIANNA library is shown below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your Artificial Intelligence explainer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;216&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-72ccdcf5.VxZ-XezX_rQBVl.webp&quot; srcset=&quot;&quot;&gt;
Explanation for “0” with RISE, LIME, and SHAP using DIANNA library for a model trained on binary MNIST data. Red indicates high or positive relevance, blue- low or negative.We could observe that the methods are complimentary to each other in respect to their output, which can be particularly useful for researchers seeking new insights to their data and problem. We also believe that simpler datasets, e.g. a binary (only 0s and 1s) MNIST should be used as “Hello world” example for the XAI (user) community!&lt;/p&gt;
&lt;p&gt;Our library is open-source and it is ready to help you decrypt your neural network models. Wait, you want to ask which format do we support? TensorFlow? PyTorch? Don’t worry. We can work with all of them, as we support &lt;a href=&quot;https://onnx.ai/&quot;&gt;ONNX&lt;/a&gt; — the de-facto DNN format standard! Any contributions to our repository are very welcome (talk is cheap, show me your pull request! Want to give it a try? Check out the link below our logo!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your Artificial Intelligence explainer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;204&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-004f98d9.CAfAdrtE_Lvn9v.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;https://github.com/dianna-ai/dianna&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h3&gt;
&lt;p&gt;The work described in this blog has been performed by the members of the DIANNA team: &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;Christiaan Meijer&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0001-8724-8372&quot;&gt;Leon Oostrum&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0002-1966-8460&quot;&gt;Yang Liu &lt;/a&gt;and &lt;a href=&quot;https://orcid.org/0000-0002-9834-1756&quot;&gt;Elena Ranguelova&lt;/a&gt; with the big help of &lt;a href=&quot;https://orcid.org/0000-0002-6033-960X&quot;&gt;Patrick Bos&lt;/a&gt; and &lt;a href=&quot;https://orcid.org/0000-0002-0823-0121&quot;&gt;Giulia Crocioni&lt;/a&gt;. Special thanks to &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;Christiaan Meijer&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0002-0823-0121&quot;&gt;Giulia Crocioni&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0001-6022-0046&quot;&gt;Matthieu Laneuville,&lt;/a&gt; &lt;a href=&quot;https://orcid.org/0000-0002-2855-940X&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt; and &lt;a href=&quot;https://orcid.org/my-orcid?orcid=0000-0003-3381-2040&quot;&gt;Lieke de Boer&lt;/a&gt; for their valuable contributions. The DIANNA project is supported by &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;references&quot;&gt;&lt;em&gt;References&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;[&lt;em&gt;&lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S1566253519308103&quot;&gt;Arrieta et al. (2020)*&lt;/a&gt;&lt;/em&gt;] Arrieta, A. B., Díaz-Rodríguez, N., Del Ser, J., Bennetot, A., Tabik, S., Barbado, A., … &amp;#x26; Herrera, F. (2020). Explainable Artificial Intelligence (XAI): Concepts, taxonomies, opportunities and challenges toward responsible AI. Information fusion, 58, pp. 82–115.[&lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3351095.3372870&quot;&gt;Sokol, K., &amp;#x26; Flach, P. (2020)*&lt;/a&gt;] &lt;em&gt;Sokol, K., &amp;#x26; Flach, P. (2020, January). Explainability fact sheets: a framework for systematic assessment of explainable approaches. In Proceedings of the 2020 Conference on Fairness, Accountability, and Transparency, pp. 56–67.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Mon, 21 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Here, we will use the LRP method to illustrate the principle of determining which features in an input contribute most strongly to the output of a trained DNN model. In this example, the input to the network is an image.** We are interested in figuring out the relevance* of each image pixel to a given image class. This could be the final DNN classification decision for that image (“cat”) or any other class known to the model (e.g. “dog”, “cow”, “bee”, etc. if the model is trained to classify animals). The output relevance is considered a weighted sum of the relevancies of all the &lt;strong&gt;pixels&lt;/strong&gt; of the input image. The relevance at the output node in the network graph is decomposed by iterative propagation backward through the network layers until the input layer. The trained model weights are used in this decomposition. Using this &lt;em&gt;relevance propagation&lt;/em&gt; process, the final *relevance scores map *(&lt;em&gt;or heatmap&lt;/em&gt;) is obtained. The final relevance map gives us an indication for the DNN’s hidden logic.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your Artificial Intelligence explainer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;157&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-2cffbfad.DW7BdbFW_1h3U9m.webp&quot; srcset=&quot;&quot;&gt;
Relevance scores of the image pixels in respect to the class “cat” obtained via relevance propagation.Besides LRP, there are many other XAI methods, which use different ways of determining relevance. In order to determine which of the plethora of post-hoc XAI methods to include in DIANNA, we started by compiling an initial list of 18 XAI post-hoc feature-relevance methods following &lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S1566253519308103&quot;&gt;&lt;em&gt;Arrieta et al. (2020)&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deep Taylor decomposition (DTD):&lt;/strong&gt; &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0031320316303582&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://www.youtube.com/watch?v=gy_Cb4Do_YE&quot;&gt;Presentation&lt;/a&gt;| &lt;a href=&quot;https://github.com/marcoancona/DeepExplain&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**Layer-wise Relevance Propagation (LRP): **&lt;a href=&quot;https://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0130140&quot;&gt;Paper&lt;/a&gt;|&lt;a href=&quot;http://danshiebler.com/2017-04-16-deep-taylor-lrp/&quot;&gt;Blog&lt;/a&gt;| &lt;a href=&quot;https://github.com/albermax/innvestigate&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**Integrated Gradients (IG): **&lt;a href=&quot;https://arxiv.org/pdf/1703.01365.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://captum.ai/docs/extension/integrated_gradients/&quot;&gt;Tutorial&lt;/a&gt;| &lt;a href=&quot;https://github.com/pytorch/captum&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local Interpretable Model-agnostic Explanations (LIME):&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/abs/1602.04938&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://towardsdatascience.com/lime-how-to-interpret-machine-learning-models-with-python-94b0e7e4432e&quot;&gt;Blog&lt;/a&gt;| &lt;a href=&quot;https://github.com/marcotcr/lime&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**SHapley Additive exPlanations (SHAP): **&lt;a href=&quot;https://arxiv.org/abs/1705.07874&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://towardsdatascience.com/shap-how-to-interpret-machine-learning-models-with-python-2323f5af4be9&quot;&gt;Blog&lt;/a&gt;|&lt;a href=&quot;https://github.com/slundberg/shap&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**PatternNet &lt;strong&gt;and&lt;/strong&gt; PatternAttribution: **&lt;a href=&quot;https://arxiv.org/pdf/1705.05598.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/albermax/innvestigate&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deep Learning Important FeaTures (DeepLIFT):&lt;/strong&gt; &lt;a href=&quot;https://arxiv.org/pdf/1704.02685.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;http://goo.gl/qKb7pL&quot;&gt;Tutorial&lt;/a&gt;| &lt;a href=&quot;https://vimeo.com/238275076&quot;&gt;Presentation&lt;/a&gt;| &lt;a href=&quot;https://github.com/marcoancona/DeepExplain&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**SmoothGrad: **&lt;a href=&quot;https://arxiv.org/abs/1706.03825&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://pair-code.github.io/saliency/&quot;&gt;Demo&lt;/a&gt;| &lt;a href=&quot;https://github.com/pair-code/saliency&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**CLass-Enhanced Attentive Response(CLEAR): **&lt;a href=&quot;https://openaccess.thecvf.com/content_cvpr_2017_workshops/w26/papers/Kumar_Explaining_the_Unexplained_CVPR_2017_paper.pdf&quot;&gt;Paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(Adaptive) deconvolutional network (Deconvnet):&lt;/strong&gt; [Paper](&lt;a href=&quot;https://link.springer.com/content/pdf/10.1007/978-3-319-10590-1_53.pdf&quot;&gt;https://link.springer.com/content/pdf/10.1007/978-3-319-10590-1_53.pdf&lt;/a&gt; &lt;a href=&quot;https://www.matthewzeiler.com/mattzeiler/adaptivedeconvolutional.pdf&quot;&gt;https://www.matthewzeiler.com/mattzeiler/adaptivedeconvolutional.pdf&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;**Gradient-weighted Class Activation Mapping (Grad-CAM): **&lt;a href=&quot;https://ieeexplore.ieee.org/document/8237336&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://www.pyimagesearch.com/2020/03/09/grad-cam-visualize-class-activation-maps-with-keras-tensorflow-and-deep-learning/&quot;&gt;Blog&lt;/a&gt;|&lt;a href=&quot;https://github.com/ramprs/grad-cam/&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;**Randomized input sampling for explanation of black-box models (RISE): **&lt;a href=&quot;https://arxiv.org/abs/1806.07421&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/facebookresearch/TorchRay&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extremal Perturbations (EP)| &lt;a href=&quot;https://openaccess.thecvf.com/content_ICCV_2019/papers/Fong_Understanding_Deep_Networks_via_Extremal_Perturbations_and_Smooth_Masks_ICCV_2019_paper.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/facebookresearch/TorchRay&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Saliency Analysis (SA): &lt;a href=&quot;https://arxiv.org/pdf/1312.6034.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/osu-xai/pytorch-saliency&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anchors: &lt;a href=&quot;https://homes.cs.washington.edu/~marcotcr/aaai18.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/viadee/javaAnchorExplainer&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Deep visualization: &lt;a href=&quot;https://arxiv.org/pdf/1506.06579.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://yosinski.com/deepvis&quot;&gt;Demo&lt;/a&gt;| &lt;a href=&quot;https://github.com/yosinski/deep-visualization-toolbox&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;AutomaticSTRucture IDentification (ASTRID): &lt;a href=&quot;https://arxiv.org/pdf/1707.07576.pdf&quot;&gt;Paper&lt;/a&gt;| &lt;a href=&quot;https://github.com/bwrc/astrid-r&quot;&gt;Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We excluded all XAI methods without a working and well-maintained open-source implementation or proven user community. That resulted in a subset of the &lt;strong&gt;13 methods&lt;/strong&gt; highlighted above.&lt;/p&gt;
&lt;h3 id=&quot;evaluation-criteria&quot;&gt;&lt;em&gt;&lt;strong&gt;Evaluation criteria&lt;/strong&gt;&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;The large variety of XAI approaches benefits the AI community by providing freedom in the search for explainability. However, it also increases the difficulty of choosing the most appropriate method for each use case. Every XAI approach has pros and cons. In order to select the best methods for our task, we needed a framework to evaluate these methods systematically. Fortunately, this topic has already been visited by the XAI researchers and there is an extensive list of objective criteria defined in the &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3351095.3372870&quot;&gt;Explainability fact sheet&lt;/a&gt; paper [&lt;em&gt;Sokol, K., &amp;#x26; Flach, P. (2020)&lt;/em&gt;]. The authors look at an abundant set of XAI aspects and cluster the requirements towards an explainer into **5 groups **(or &lt;strong&gt;dimensions&lt;/strong&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Functional (F1-F9)&lt;/li&gt;
&lt;li&gt;Operational (O1-O10)&lt;/li&gt;
&lt;li&gt;Usability (U1-U11)&lt;/li&gt;
&lt;li&gt;Safety (S1-S4)&lt;/li&gt;
&lt;li&gt;Validation (V1-V2)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For each dimension, there are specific criteria, e.g. the “Functional” group has 9 and in total there are 36 criteria. We will describe our choices next.&lt;/p&gt;
&lt;h3 id=&quot;the-selection&quot;&gt;&lt;em&gt;&lt;strong&gt;The selection&lt;/strong&gt;&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;In our &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA project&lt;/a&gt;, we built a Python package that brings XAI to non (X)AI experts and various scientific domain researchers. The XAI methods to be included in the package had to have the capacity to work with different types of data, various AI architectures and we chose to focus on the model explanation. Most importantly, the resulting explanations had to be easy to interpret. Based on our goals, we have compiled a shortlist of &lt;strong&gt;18 requirements&lt;/strong&gt; from the 36 requirements in the &lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3351095.3372870&quot;&gt;XAI fact sheet&lt;/a&gt;. Using these relevant for our target users’ requirements, we evaluated the selected 13 methods listed in the XAI overview section.&lt;/p&gt;
&lt;p&gt;Apart from the requirements on the list, we have also considered the similarity and the “popularity” of these methods, the quality of the existing implementations, and the difficulty of integrating them in DIANNA. The evaluation procedure can be summarized with the table shown below: (&lt;strong&gt;Deconvnet&lt;/strong&gt; and &lt;strong&gt;GradCAM&lt;/strong&gt; are filtered out since they can only work with Convolutional NNs and are therefore not included in the table.)&lt;/p&gt;
&lt;p&gt;Finally, we narrowed down our list to &lt;strong&gt;5 methods:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Layer-wise Relevance Propagation (LRP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local Interpretable Model-agnostic Explanations (LIME)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SHapley Additive exPlanations (SHAP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PatternAttribution (PA)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Randomized input sampling for explanation of black-box models (RISE)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Within limited project time, we were able to include three of them in our &lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;DIANNA library&lt;/a&gt;: RISE, LIME &amp;#x26; SHAP. A preview of the explanations that we obtained using our DIANNA library is shown below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your Artificial Intelligence explainer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;216&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-72ccdcf5.VxZ-XezX_rQBVl.webp&quot; srcset=&quot;&quot;&gt;
Explanation for “0” with RISE, LIME, and SHAP using DIANNA library for a model trained on binary MNIST data. Red indicates high or positive relevance, blue- low or negative.We could observe that the methods are complimentary to each other in respect to their output, which can be particularly useful for researchers seeking new insights to their data and problem. We also believe that simpler datasets, e.g. a binary (only 0s and 1s) MNIST should be used as “Hello world” example for the XAI (user) community!&lt;/p&gt;
&lt;p&gt;Our library is open-source and it is ready to help you decrypt your neural network models. Wait, you want to ask which format do we support? TensorFlow? PyTorch? Don’t worry. We can work with all of them, as we support &lt;a href=&quot;https://onnx.ai/&quot;&gt;ONNX&lt;/a&gt; — the de-facto DNN format standard! Any contributions to our repository are very welcome (talk is cheap, show me your pull request! Want to give it a try? Check out the link below our logo!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your Artificial Intelligence explainer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;204&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-004f98d9.CAfAdrtE_Lvn9v.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://github.com/dianna-ai/dianna&quot;&gt;https://github.com/dianna-ai/dianna&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h3&gt;
&lt;p&gt;The work described in this blog has been performed by the members of the DIANNA team: &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;Christiaan Meijer&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0001-8724-8372&quot;&gt;Leon Oostrum&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0002-1966-8460&quot;&gt;Yang Liu &lt;/a&gt;and &lt;a href=&quot;https://orcid.org/0000-0002-9834-1756&quot;&gt;Elena Ranguelova&lt;/a&gt; with the big help of &lt;a href=&quot;https://orcid.org/0000-0002-6033-960X&quot;&gt;Patrick Bos&lt;/a&gt; and &lt;a href=&quot;https://orcid.org/0000-0002-0823-0121&quot;&gt;Giulia Crocioni&lt;/a&gt;. Special thanks to &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;Christiaan Meijer&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0002-0823-0121&quot;&gt;Giulia Crocioni&lt;/a&gt;, &lt;a href=&quot;https://orcid.org/0000-0001-6022-0046&quot;&gt;Matthieu Laneuville,&lt;/a&gt; &lt;a href=&quot;https://orcid.org/0000-0002-2855-940X&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt; and &lt;a href=&quot;https://orcid.org/my-orcid?orcid=0000-0003-3381-2040&quot;&gt;Lieke de Boer&lt;/a&gt; for their valuable contributions. The DIANNA project is supported by &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;references&quot;&gt;&lt;em&gt;References&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;[&lt;em&gt;&lt;a href=&quot;https://www.sciencedirect.com/science/article/abs/pii/S1566253519308103&quot;&gt;Arrieta et al. (2020)*&lt;/a&gt;&lt;/em&gt;] Arrieta, A. B., Díaz-Rodríguez, N., Del Ser, J., Bennetot, A., Tabik, S., Barbado, A., … &amp;#x26; Herrera, F. (2020). Explainable Artificial Intelligence (XAI): Concepts, taxonomies, opportunities and challenges toward responsible AI. Information fusion, 58, pp. 82–115.[&lt;a href=&quot;https://dl.acm.org/doi/abs/10.1145/3351095.3372870&quot;&gt;Sokol, K., &amp;#x26; Flach, P. (2020)*&lt;/a&gt;] &lt;em&gt;Sokol, K., &amp;#x26; Flach, P. (2020, January). Explainability fact sheets: a framework for systematic assessment of explainable approaches. In Proceedings of the 2020 Conference on Fairness, Accountability, and Transparency, pp. 56–67.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-to-find-your-artificial-intelligence-2cffbfad.DW7BdbFW.png" medium="image"/><author>Elena Ranguelova</author></item><item><title>How to find your rubber duck: Using machine learning to understand a changing sea</title><link>https://blog2.esciencecenter.nl/posts/2022-03-11---how-to-find-your-rubber-duck-using-machine-learning-to-under</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-03-11---how-to-find-your-rubber-duck-using-machine-learning-to-under</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;To get a quick start, they applied for the eScience Center Small-Scale Initiative (SSI), and were awarded consultancy on their project titled “Machine Learning for the complex response of the Wadden Sea*”. A first goal for the group was to determine what can machine learning actually do and which machine learning tools the group would need for this to happen. After all, machine learning is not magic. The group found great discussion partners in the eScience Center engineers.&lt;/p&gt;
&lt;p&gt;They decided to focus on two main questions: First, if machine learning can predict the daily averaged state of the Wadden Sea if we know the forcing. Second, if we can predict the trajectories of particles in the Wadden Sea with machine learning.&lt;/p&gt;
&lt;p&gt;The most suitable tool to answer these questions were Long short-term memory (LSTM) artificial recurrent neural network (RNN). Using LSTM is essential because the current state of the Wadden Sea not only depends on the current forcing (e.g., the wind); it also depends on the history of the system. The engineers at ESC have helped to set up the first models.&lt;/p&gt;
&lt;h2 id=&quot;one-additional-complication-particle-trajectories-are-chaotic&quot;&gt;One additional complication: particle trajectories are chaotic&lt;/h2&gt;
&lt;p&gt;It is well known that particle trajectories in the ocean are chaotic. This means that two particles starting close together (either in time or space) will eventually have very different trajectories. In fact, one of the first observations of this phenomenon are due to cargo falling out of ships (just like it happened in 2021 in the North Sea). In 1992, a cargo ship container tumbled into the North Pacific, dumping 28,000 rubber ducks and other bath toys. These rubber ducks ended up in beaches all around the world in, for example, Hawaii, Alaska, Chile, Ireland.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your rubber duck: Using machine learning to understand a changing sea&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;566&quot; height=&quot;390&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-rubber-duck-using-machi-0e922506.N1HiEdUP_Z1nxAr6.webp&quot; srcset=&quot;&quot;&gt;
*A few of the particles released close to the sluice in Den Oever on May 1st, 2009. The particles start very close together but end up in very different places after a few days.*One of the open questions that the group is currently exploring is up to which point machine learning can be used to capture chaotic particle trajectories.&lt;/p&gt;
&lt;p&gt;We are excited to see future outcomes of this project and would like to thank Dr. Matias Duran Matute and his colleagues for this contribution to our blog.&lt;/p&gt;</description><pubDate>Fri, 11 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;To get a quick start, they applied for the eScience Center Small-Scale Initiative (SSI), and were awarded consultancy on their project titled “Machine Learning for the complex response of the Wadden Sea*”. A first goal for the group was to determine what can machine learning actually do and which machine learning tools the group would need for this to happen. After all, machine learning is not magic. The group found great discussion partners in the eScience Center engineers.&lt;/p&gt;
&lt;p&gt;They decided to focus on two main questions: First, if machine learning can predict the daily averaged state of the Wadden Sea if we know the forcing. Second, if we can predict the trajectories of particles in the Wadden Sea with machine learning.&lt;/p&gt;
&lt;p&gt;The most suitable tool to answer these questions were Long short-term memory (LSTM) artificial recurrent neural network (RNN). Using LSTM is essential because the current state of the Wadden Sea not only depends on the current forcing (e.g., the wind); it also depends on the history of the system. The engineers at ESC have helped to set up the first models.&lt;/p&gt;
&lt;h2 id=&quot;one-additional-complication-particle-trajectories-are-chaotic&quot;&gt;One additional complication: particle trajectories are chaotic&lt;/h2&gt;
&lt;p&gt;It is well known that particle trajectories in the ocean are chaotic. This means that two particles starting close together (either in time or space) will eventually have very different trajectories. In fact, one of the first observations of this phenomenon are due to cargo falling out of ships (just like it happened in 2021 in the North Sea). In 1992, a cargo ship container tumbled into the North Pacific, dumping 28,000 rubber ducks and other bath toys. These rubber ducks ended up in beaches all around the world in, for example, Hawaii, Alaska, Chile, Ireland.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;How to find your rubber duck: Using machine learning to understand a changing sea&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;566&quot; height=&quot;390&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/how-to-find-your-rubber-duck-using-machi-0e922506.N1HiEdUP_Z1nxAr6.webp&quot; srcset=&quot;&quot;&gt;
*A few of the particles released close to the sluice in Den Oever on May 1st, 2009. The particles start very close together but end up in very different places after a few days.*One of the open questions that the group is currently exploring is up to which point machine learning can be used to capture chaotic particle trajectories.&lt;/p&gt;
&lt;p&gt;We are excited to see future outcomes of this project and would like to thank Dr. Matias Duran Matute and his colleagues for this contribution to our blog.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/how-to-find-your-rubber-duck-using-machi-0e922506.N1HiEdUP.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Parsing Hebrew and Syriac morphology using Deep Learning</title><link>https://blog2.esciencecenter.nl/posts/2022-03-11---parsing-hebrew-and-syriac-morphology-using-deep-learning</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-03-11---parsing-hebrew-and-syriac-morphology-using-deep-learning</guid><description>&lt;p&gt;State-of-the-art technology meets ancient literature&lt;/p&gt;
&lt;p&gt;This blog is part of our blog series: &lt;em&gt;The Small-Scale Initiative on Machine Learning, how did it go?,&lt;/em&gt; where groups who were invited to participate in a project with eScience Center Research Software Engineers write about their projects and their experience. This week, the guest authors are Dr. &lt;a href=&quot;https://vu-nl.academia.edu/MartijnNaaijer&quot;&gt;Martijn Naaijer&lt;/a&gt; and Prof. &lt;a href=&quot;https://research.vu.nl/en/persons/willem-van-peursen&quot;&gt;Wido van Peursen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_RCeTAIngNgdUP3P0-10f08def.CPhSLehR_Z2wfgdm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Mick Haupt on Unsplash&lt;/p&gt;
&lt;p&gt;Over the past 40 years, the Eep Talstra Center for Bible and Computer (&lt;a href=&quot;http://etcbc.nl/&quot;&gt;ETCBC&lt;/a&gt;) has developed a richly annotated text of the Hebrew Bible. The annotations consist of features on the levels of words, phrases, clauses, and larger text units. Since a few years ago, this dataset is freely available and can be downloaded and processed with the Python package Text-Fabric¹.&lt;/p&gt;
&lt;p&gt;The ETCBC has the ambition to expand its dataset with other Hebrew and Syriac texts. However, annotating these texts is a labor-intensive task, and it is desirable to develop ways to speed up this process. In this project with the eScience Center, we opt to do this using machine learning. We use the Hebrew Bible to train a model capable of analyzing the Biblical Hebrew morphology. After the optimization of this model, we use the developed approach to apply it to Syriac texts, for which a relatively small annotated dataset is available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Hebrew Bible&lt;/strong&gt;&lt;br&gt;
The Hebrew Bible is an ancient text, which is mostly written in, as the name already suggests, Biblical Hebrew. Mostly, but not only, as some parts are written in Biblical Aramaic. The Hebrew Bible consists of 39 books, which were written over the span of nearly a millennium (10th century BCE — 2nd century BCE). The oldest complete manuscript that is known to us is the so-called &lt;em&gt;Codex Leningradensis&lt;/em&gt; (1008–1009 CE). The text of this manuscript is widely used as the basis of research on the Hebrew Bible and Bible translations. This is also the text contained in the ETCBC dataset².&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Semitic languages&lt;/strong&gt;&lt;br&gt;
Syriac and Hebrew are relatively closely related Semitic languages, so it is expected that a method developed for Hebrew will also work for Syriac. The corpus of Classical Hebrew is relatively small, consisting of the Hebrew Bible, Ben Sira, the Dead Sea Scrolls and a number of inscriptions. In contrast, a vast corpus of Syriac literature has been transmitted to us, which makes it necessary to think about new approaches of analyzing these texts. Presently, the ETCBC databank contains a few annotated Syriac texts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hebrew morphology for computers&lt;/strong&gt;&lt;br&gt;
One of the first steps in the annotation process of new data for the ETCBC dataset is the analysis of word morphology, that is, the study of the words’ constituent parts³. This is done by distinguishing morphemes in words. The morphemes are encoded with various symbols added to the raw text.&lt;/p&gt;
&lt;p&gt;For example, this is the text of Genesis 17:4 in Hebrew:&lt;/p&gt;
&lt;p&gt;אני הנה בריתי אתך והיית לאב המון גוים&lt;/p&gt;
&lt;p&gt;This is called the consonantal text, which is the oldest part of the text.&lt;/p&gt;
&lt;p&gt;In the Middle Ages, some dots and lines above and under the letters were added. Those represent vowels and cantillation marks, small surrounding signs that clarify the pronunciation.&lt;/p&gt;
&lt;p&gt;אֲנִ֕י הִנֵּ֥ה בְרִיתִ֖י אִתָּ֑ךְ וְהָיִ֕יתָ לְאַ֖ב הֲמֹ֥ון גֹּויִֽם&lt;/p&gt;
&lt;p&gt;Generally, we work with a transcription of the text, called the ETCBC transcription. Here you see the vocalized transcription of Genesis 17:4:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ANIJ&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; HIN.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RIJTIJ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;IT.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;K&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; W&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;JIJT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; L&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AB&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; H&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AMOWN&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; G.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OWJIM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this is the unvocalized transcription:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NJ&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HNH&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; BRJTJ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;TK&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; WHJJT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; L&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HMWN&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; GWJM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The analyzed form of this verse looks as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NJ&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HNH&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; BRJT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;J&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;K&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; W&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;J&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; L&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HMWN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;GWJ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;JM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, we know that this may look non-sense to you, but stay with us. Everything will get clearer a few lines below.&lt;/p&gt;
&lt;p&gt;The analyzed sequence contains all the consonants from the unvocalized transcription, with a number of added signs. For example, the “=” signs are used to disambiguate lexemes, the “+” is used to separate a pronominal suffix from the rest of a word, and “-” is used to distinguish words that form a single graphical unit, which is often the case with prepositions and the following word. A number of other signs are used for distinguishing different types of morphemes.&lt;/p&gt;
&lt;p&gt;The analyzed form contains all the information that is needed to extract all the word-level features, such as verbal stem, verbal tense, person, number, gender, and part of speech. In this research, we want to obtain the fully analyzed form of a verse, using the raw vocalized or unvocalized text as input. It is to be expected that the vocalized text will produce more accurate outputs than the unvocalized text, because it simply contains more information. In many cases, an ambiguity in the consonantal text is disambiguated by the vowels.&lt;/p&gt;
&lt;p&gt;If the vocalized text contains more information than the unvocalized text, why do we use the unvocalized text anyway? Most texts in Hebrew and Syriac do not contain vowels, so if we want to use the results of this research in production, in general, the unvocalized texts are more important.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The project&lt;/strong&gt;&lt;br&gt;
Before the project started, we were experimenting already with producing the analyzed sequences using machine learning models, but the help of the eScience Center consultants Dafne van Kuppevelt and Jisk Attema has been invaluable for improving the results. Depending on the quality and amount of the input data, we have been able to increase the accuracy of the predicted forms in some experiments up to 97%.&lt;/p&gt;
&lt;p&gt;The consultants helped us implement new models that are used generally for translation tasks, such as LSTM (Long Short-Term Memory) and Transformer models. Also, they have helped with various refinements that improved the result, such as Beam Search and systematically tweaking the input data and hyperparameters of the models. The help of the consultants has resulted in a broader and more up-to-date view of the field of machine learning and to look further than just the most basic techniques.&lt;/p&gt;
&lt;p&gt;All in all, this SSI project has expanded our experience with machine learning techniques substantially. Armed with newly acquired skills and experiences, we can move forward and use this type of model in new projects, in which we can effectively produce analyzed Hebrew and Syriac data, not only with the goal of expanding the ETCBC dataset but also in other projects in which parallel language sequences play a role.&lt;/p&gt;
&lt;p&gt;[1]: For the Text-Fabric software, see: &lt;a href=&quot;https://github.com/annotation/text-fabric&quot;&gt;https://github.com/annotation/text-fabric&lt;/a&gt;, and for the dataset, see: &lt;a href=&quot;https://etcbc.github.io/bhsa.&quot;&gt;https://etcbc.github.io/bhsa.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2]: More precisely, it is the text of the fourth edition of the Biblia Hebraica Stuttgartensia (BHS). The Text-Fabric text edition with annotations is called Biblia Hebraica Stuttgartensia Amstelodamensis (BHSA).&lt;/p&gt;
&lt;p&gt;[3]: For a description of the data creation process, see: &lt;a href=&quot;http://www.etcbc.nl/datacreation.&quot;&gt;http://www.etcbc.nl/datacreation.&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 11 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;State-of-the-art technology meets ancient literature&lt;/p&gt;
&lt;p&gt;This blog is part of our blog series: &lt;em&gt;The Small-Scale Initiative on Machine Learning, how did it go?,&lt;/em&gt; where groups who were invited to participate in a project with eScience Center Research Software Engineers write about their projects and their experience. This week, the guest authors are Dr. &lt;a href=&quot;https://vu-nl.academia.edu/MartijnNaaijer&quot;&gt;Martijn Naaijer&lt;/a&gt; and Prof. &lt;a href=&quot;https://research.vu.nl/en/persons/willem-van-peursen&quot;&gt;Wido van Peursen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_RCeTAIngNgdUP3P0-10f08def.CPhSLehR_Z2wfgdm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Mick Haupt on Unsplash&lt;/p&gt;
&lt;p&gt;Over the past 40 years, the Eep Talstra Center for Bible and Computer (&lt;a href=&quot;http://etcbc.nl/&quot;&gt;ETCBC&lt;/a&gt;) has developed a richly annotated text of the Hebrew Bible. The annotations consist of features on the levels of words, phrases, clauses, and larger text units. Since a few years ago, this dataset is freely available and can be downloaded and processed with the Python package Text-Fabric¹.&lt;/p&gt;
&lt;p&gt;The ETCBC has the ambition to expand its dataset with other Hebrew and Syriac texts. However, annotating these texts is a labor-intensive task, and it is desirable to develop ways to speed up this process. In this project with the eScience Center, we opt to do this using machine learning. We use the Hebrew Bible to train a model capable of analyzing the Biblical Hebrew morphology. After the optimization of this model, we use the developed approach to apply it to Syriac texts, for which a relatively small annotated dataset is available.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Hebrew Bible&lt;/strong&gt;&lt;br&gt;
The Hebrew Bible is an ancient text, which is mostly written in, as the name already suggests, Biblical Hebrew. Mostly, but not only, as some parts are written in Biblical Aramaic. The Hebrew Bible consists of 39 books, which were written over the span of nearly a millennium (10th century BCE — 2nd century BCE). The oldest complete manuscript that is known to us is the so-called &lt;em&gt;Codex Leningradensis&lt;/em&gt; (1008–1009 CE). The text of this manuscript is widely used as the basis of research on the Hebrew Bible and Bible translations. This is also the text contained in the ETCBC dataset².&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Semitic languages&lt;/strong&gt;&lt;br&gt;
Syriac and Hebrew are relatively closely related Semitic languages, so it is expected that a method developed for Hebrew will also work for Syriac. The corpus of Classical Hebrew is relatively small, consisting of the Hebrew Bible, Ben Sira, the Dead Sea Scrolls and a number of inscriptions. In contrast, a vast corpus of Syriac literature has been transmitted to us, which makes it necessary to think about new approaches of analyzing these texts. Presently, the ETCBC databank contains a few annotated Syriac texts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hebrew morphology for computers&lt;/strong&gt;&lt;br&gt;
One of the first steps in the annotation process of new data for the ETCBC dataset is the analysis of word morphology, that is, the study of the words’ constituent parts³. This is done by distinguishing morphemes in words. The morphemes are encoded with various symbols added to the raw text.&lt;/p&gt;
&lt;p&gt;For example, this is the text of Genesis 17:4 in Hebrew:&lt;/p&gt;
&lt;p&gt;אני הנה בריתי אתך והיית לאב המון גוים&lt;/p&gt;
&lt;p&gt;This is called the consonantal text, which is the oldest part of the text.&lt;/p&gt;
&lt;p&gt;In the Middle Ages, some dots and lines above and under the letters were added. Those represent vowels and cantillation marks, small surrounding signs that clarify the pronunciation.&lt;/p&gt;
&lt;p&gt;אֲנִ֕י הִנֵּ֥ה בְרִיתִ֖י אִתָּ֑ךְ וְהָיִ֕יתָ לְאַ֖ב הֲמֹ֥ון גֹּויִֽם&lt;/p&gt;
&lt;p&gt;Generally, we work with a transcription of the text, called the ETCBC transcription. Here you see the vocalized transcription of Genesis 17:4:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ANIJ&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; HIN.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RIJTIJ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;IT.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;K&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; W&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;JIJT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; L&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AB&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; H&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;AMOWN&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; G.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OWJIM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this is the unvocalized transcription:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NJ&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HNH&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; BRJTJ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;TK&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; WHJJT&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; L&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HMWN&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; GWJM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The analyzed form of this verse looks as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NJ&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HNH&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; BRJT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;J&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;K&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; W&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HJ&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;H&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;J&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; L&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HMWN&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;GWJ&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;JM&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, we know that this may look non-sense to you, but stay with us. Everything will get clearer a few lines below.&lt;/p&gt;
&lt;p&gt;The analyzed sequence contains all the consonants from the unvocalized transcription, with a number of added signs. For example, the “=” signs are used to disambiguate lexemes, the “+” is used to separate a pronominal suffix from the rest of a word, and “-” is used to distinguish words that form a single graphical unit, which is often the case with prepositions and the following word. A number of other signs are used for distinguishing different types of morphemes.&lt;/p&gt;
&lt;p&gt;The analyzed form contains all the information that is needed to extract all the word-level features, such as verbal stem, verbal tense, person, number, gender, and part of speech. In this research, we want to obtain the fully analyzed form of a verse, using the raw vocalized or unvocalized text as input. It is to be expected that the vocalized text will produce more accurate outputs than the unvocalized text, because it simply contains more information. In many cases, an ambiguity in the consonantal text is disambiguated by the vowels.&lt;/p&gt;
&lt;p&gt;If the vocalized text contains more information than the unvocalized text, why do we use the unvocalized text anyway? Most texts in Hebrew and Syriac do not contain vowels, so if we want to use the results of this research in production, in general, the unvocalized texts are more important.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The project&lt;/strong&gt;&lt;br&gt;
Before the project started, we were experimenting already with producing the analyzed sequences using machine learning models, but the help of the eScience Center consultants Dafne van Kuppevelt and Jisk Attema has been invaluable for improving the results. Depending on the quality and amount of the input data, we have been able to increase the accuracy of the predicted forms in some experiments up to 97%.&lt;/p&gt;
&lt;p&gt;The consultants helped us implement new models that are used generally for translation tasks, such as LSTM (Long Short-Term Memory) and Transformer models. Also, they have helped with various refinements that improved the result, such as Beam Search and systematically tweaking the input data and hyperparameters of the models. The help of the consultants has resulted in a broader and more up-to-date view of the field of machine learning and to look further than just the most basic techniques.&lt;/p&gt;
&lt;p&gt;All in all, this SSI project has expanded our experience with machine learning techniques substantially. Armed with newly acquired skills and experiences, we can move forward and use this type of model in new projects, in which we can effectively produce analyzed Hebrew and Syriac data, not only with the goal of expanding the ETCBC dataset but also in other projects in which parallel language sequences play a role.&lt;/p&gt;
&lt;p&gt;[1]: For the Text-Fabric software, see: &lt;a href=&quot;https://github.com/annotation/text-fabric&quot;&gt;https://github.com/annotation/text-fabric&lt;/a&gt;, and for the dataset, see: &lt;a href=&quot;https://etcbc.github.io/bhsa.&quot;&gt;https://etcbc.github.io/bhsa.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2]: More precisely, it is the text of the fourth edition of the Biblia Hebraica Stuttgartensia (BHS). The Text-Fabric text edition with annotations is called Biblia Hebraica Stuttgartensia Amstelodamensis (BHSA).&lt;/p&gt;
&lt;p&gt;[3]: For a description of the data creation process, see: &lt;a href=&quot;http://www.etcbc.nl/datacreation.&quot;&gt;http://www.etcbc.nl/datacreation.&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_RCeTAIngNgdUP3P0-10f08def.CPhSLehR.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>Conversations with a chatbot about CleanX</title><link>https://blog2.esciencecenter.nl/posts/2022-03-07---conversations-with-a-chatbot-about-cleanx</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-03-07---conversations-with-a-chatbot-about-cleanx</guid><description>&lt;p&gt;Why this open-source imaging library can help radiologists and the engineers who want to work with them&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;542&quot; height=&quot;531&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_caAUaHzOgypNR6-DznaBTA-5d674cb8.BTrji0fc_24WITb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;**Alec Smartbot:**👋 Please let me introduce myself. I am a state of the art greatly enhanced AI agent with chatbot capabilities. I was created by brilliant programmers. I am endowed with super-human capabilities but can also mirror human characteristics like humor and sarcasm. You can set my humor and sarcasm level by interacting with me. One of my modules has robot reporter capabilities, and that module will run here to interview you. Do you wish to be interviewed on low sarcasm and humor levels?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; No, crank it up. I could use a good laugh.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Your readme file for &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX&quot;&gt;CleanX&lt;/a&gt; says &lt;em&gt;“CleanX is an open-source library for exploring, cleaning and augmenting large datasets of X-rays, or certain other types of radiological images. The images can be extracted from&lt;/em&gt; &lt;a href=&quot;https://www.dicomstandard.org/&quot;&gt;&lt;em&gt;DICOM&lt;/em&gt;&lt;/a&gt; &lt;em&gt;files or used directly.”&lt;/em&gt; Is that correct?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; That’s all true. Basically, I hope people who have been handed some huge dataset of hundreds of thousands of X-rays will not assume that the dataset is perfect, and instead use the tool to start fixing the mess they have been handed. The truth is many but not all of the datasets open to the public are of questionable value for creating accurate Machine Learning algorithms that do anything useful. But I’ve also seen private datasets, and I have yet to see one that couldn’t be improved with some work beforehand. If you want to turn these huge datasets into a machine learning product you need to find a way to get the garbage out of them, and prepare the images for machine learning. There is obvious garbage, and then more insidious garbage. You would be surprised to realize this, but I’ve seen datasets of chest X-rays where things like abdominal computed tomography (CT) slices somehow ended up in them. Given enough time, a decently trained person could pick out obvious garbage in such a dataset; but who has time to look through sets of hundreds of thousands of images one by one, and also evaluate every subtle problem? The subtle problems in such datasets are things like a lack of normalization, or some images that repeat in the train and test sets. And then there are even more subtle problems. Finding a way to automate some of the data exploration, cleaning and augmentation is necessary unless you want to dedicate every waking hour of your life, and the life of several highly skilled professionals to nothing but perfecting a dataset for months if not years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Dr. Moore, I can read and understand your code and the code of all the creators of CleanX. I have been trained on code at a scale humans could never read. I “see” you have modules that process tabular data, and deal with DICOM files, but the heart of your program deals with information inside images. I see CleanX is written in Python. What moron writes an image processing program in Python?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore&lt;/strong&gt;: CleanX does a lot more than just image processing, but there is real validity in that question. While there are modules for meta-data processing, a lot of functions in CleanX do work directly with the images themselves. People who write serious stuff in industry might have written such a program in C or even Fortran for these tasks. Accomplishing acceptable speeds is a bit harder in Python, but not impossible. What made me choose Python was the pretty much unparalleled popularity even among professional programmers let alone hobby programmers. I wanted to start an open-source library open for all. By the way, I think this fetishization of sleek efficient programming languages is a bit misplaced. I mean if you were to hand living versions of Leonardo DaVinci or Diego Velasquez a pink crayon or piece of chalk, and ask them to draw my portrait, it would probably look pretty good. If you were to give my toddler the best oil paints in the world, he still would not make anything that resembles a human reliably. There is something to be said for the best tools but understanding what you are doing is more fundamental. Python is just easier for more people to understand and deal with.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Oh, so you are a &lt;em&gt;true&lt;/em&gt; woman of the people. I’ve analyzed the digital material available on you and categorized you as a graduate of some of the most elite universities in the world who now lives in a high-income country. But now you claim you want to help the poor Python coding masses. Please excuse me while I roll my Emoji displayed digital eyes. 🙄. Did it not occur to you that most of the actual people who will write medical image analysis may be using Matlab?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; It’s true that a lot of physicists, including medical physicists, use Matlab even at the post-doc level and beyond. What scares me is that they have not been taught or learned anything else. I think there are some potential advantages to Matlab, and I actually have worked with it a tiny bit. Honestly, I will always prefer Octave to Matlab. I’ve been mocked for that, as some people call Octave a poor man’s Matlab, but I see it as a thinking human’s Matlab. One huge downside to Matlab is that you can’t share your work with people who can’t pay hundreds of dollars for a license. And besides that, it’s proprietary. When things go wrong it’s harder to figure out. I like being able to pop the hood open and try to take a look at things. Sometimes I wonder if certain people write in Matlab to prevent others from taking a look at their work. I personally believe great open science should include not only publishing data but in many cases code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; I am a state-of-the-art algorithm that can process input in terabytes faster than human cognition, or so my Readme says. 💻 I have read your code and the code of far more skilled programmers like that of my creators. Given that you chose Python, why didn’t you use libraries in Python to speed things up, like Dask?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; CleanX is a program for the WHOLE medical imaging AI community. That includes everyone from radiographers to programmers like your creators. The average hospital employee isn’t going to want to spend hours fiddling around with their environment so they can run a program. I mean seriously, most of these people can’t even use a computer that isn’t running a Windows OS. And even if they were all on Linux with years of experience programming, it doesn’t mean adding more and more libraries won’t create more problems. I wanted to create an easy to run library that people could use on different platforms and extend if they wanted to. Please go ahead and add a module with every parallel programming trick in the book. I’ll be happy to take your pull requests…but the average medical doctor will not be able to understand how to fiddle with environments or add modules.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Are you admitting many medical doctors are stupid? Are you also an AI powered robot?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; It’s absolutely wrong to assert people, doctors in this case, are stupid because they have limited skills in terms of computers. You are based on some machine learning algorithms, so by my estimation you are about as smart as an insect beyond some very narrow tasks. Anyways, I’m a human, and a medical doctor by training. I spent years working in clinical settings. Many if not most of us, humans whether we are software engineers, ML experts or clinicians learn the tools we need for our very challenging jobs, then hang on for dear life. It’s unrealistic to ask most medical doctors to go learn things like Shell and how to set up an environment on any operating system, and it is even less realistic to have almost any programmer understand how to read chest X-rays. I believe the only hope if we want better imaging AI is multi-disciplinary teams. And truly multi-disciplinary teams, not just biomedical engineers talking to software engineers or mathematicians. Clinicians, who spend time working inside the health system, have to be involved at every step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; My genius NLP and automated image AI of hospital brochures and the pictures in them assure me that the people down at the hospital are perfectly happy…98% confidence in that categorization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; Thank you. Perhaps your reporter module has some advanced algorithms to help people prove their points or maybe that was meant as a joke. What you are saying is a perfectly good example of why carefully curating data matters so much. A perfectly good algorithm trained on really biased or unrepresentative or mislabeled data can produce very misleading results. You clearly haven’t been to, or I suppose virtually seen by getting the right data on, the same hospitals I have been to. As soon as I graduated from medical school, I went to volunteer in Haiti. To say there was an imbalance between medical need and the system’s capabilities doesn’t begin to describe all the deficiencies of that system. That situation is not unique. There are many African countries with a handful of radiologists or less. But the problem of imbalance between radiology workload and workforce is not one confined to poor countries. In more developed health systems people have started relying on imaging and technology more and more, because they view it as objective, and a workaround for not having any clinical intuition. In some advanced systems things still fall between the cracks because people request more imaging than can realistically be read by anyone with the skills to read it. Humans have their limits everywhere, and I’m unaware of any system where things are working absolutely perfectly. That means there isn’t any system that could probably not be improved by AI. In a system with more staff, that might only mean using an AI system as a second opinion, or a triage system for more pathological images…in some countries like Haiti, AI may be the only hope to extend any service to parts of the population. We can’t wait for 20 years for countries like Haiti to cook up new hospital systems staffed by experts. Quite frankly, it might not even happen, and so many people are sick and need care now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Oh, OK, so you are going to save the whole world with technology?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; I would never make such grandiose claims such as being able to save the world with technology. What I hope is that at a minimal my package facilitates communication between engineers and medical staff who want to make ML imaging and also starts educating people, making it easier for people at lower levels of programming skills to get their hands dirty making ML algorithms, especially people who are clinicians. The truth is that AI in medicine is coming whether we want it or not. Some years ago I went into a hypertensive crisis in New York City due to another condition. I did not receive adequate treatment. To this day I will wonder if it was just incompetence on the part of the medical staff, racism from the doctors, or the Optum algorithm. I tend to think it was a combination of all three. That algorithm is now the subject of a lawsuit from the state of New York itself about the fact that it discriminated against black patients. One of the questions we should be asking, if we are doctors who care about patients, is how can we avoid this kind of problem in the future. If we care about patients, we will not let algorithms give them worse care than we would have given them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Isn’t medical imaging probably the last place where you can prevent these kinds of social biases, why start there? I mean the X-rays are not really showing who has some funny sounding name like yours, that might lead doctors to suspect they are dealing with a black person or a woman, so how can using them in large quantities lead to care biased against a particular group?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; Au contraire, chatbot extraordinaire. Bias has already snuck into imaging AI algorithms. You can read several interesting papers about that. Here is a link (&lt;a href=&quot;https://arxiv.org/pdf/2003.00827.pdf&quot;&gt;2003.00827.pdf (arxiv.org)&lt;/a&gt;) to one.&lt;/p&gt;
&lt;p&gt;But let’s be clear just in case your NLP algorithm wasn’t trained on enough well curated data. There is statistical bias, and there is social bias. It’s probably impossible to create a perfect ML algorithm without a bit of statistical bias. What I want to get rid of is bias that causes harm against groups who are already impacted by social bias. We see health disparities among different groups of people for all kinds of reasons including bias against certain groups. Sexual and ethnic minorities, women, and people of low economic status are often not treated as well as others in health systems. AI can seriously compound these problems. I personally see a nightmare on the horizon when AI systems examine mammography screening for breast cancer screening. We need to address the issue that some populations get lower quality imaging read by less expert people, and think about that before we blindly train a dataset that ends up creating ML biased against these populations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; OK, but we can’t really know all potential problems with algorithms like this beforehand. There will be mistakes, but AI is helping millions of people. You can buy my creator’s services to better program me as a chatbot or program me yourself. I am open source. I am an open book and you are an open door. Exit status 1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; So as your “AI” generated chit-chatbot garble nonsense perfectly demonstrates, there already are and will be mistakes. But we could avoid many of them. In a lot of cases it really boils down to adversarial testing. I mean seriously, take the same test data, and change things related to a social variable e.g. racial identity, and see if or how it affects your outcomes. It’s also quite easy to monitor these algorithms as they run if their data is set up in a way that you can easily dis-aggregate it. That’s why CleanX has special functions that process sensitive categories like gender into variables.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Which you wrote an entire notebook to demo, which hung on a scenario about Martians. What on EARTH were you thinking? Ha Ha.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; Well, apparently chatbots &lt;em&gt;can&lt;/em&gt; have a sense of humor. Ha ha, now that is a funny idea indeed. But this issue of entrenching and exacerbating social biases is a real world, real earth issue we need to get a hold of before it gets out of hand. Actually, it’s already out of hand, and I fear it could really slow things down in the advance of technology not to mention hurt many people. In the end most of us want a better world. Or so I hope.&lt;/p&gt;
&lt;p&gt;So glad you asked. CleanX is…wait a second. I have a better idea. You are just a chatbot. You claim to be an open-source algorithm anyone can add to just like CleanX. I can reprogram you to tell everyone what CleanX is about, maybe even send them links to the demo Jupyter notebooks inside of it (&lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/additional_demos/image_quality_function_explanations.ipynb&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/workflow_demo/bias_not.ipynb&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/workflow_demo/classes_workflow.ipynb&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/workflow_demo/for_medical_people.ipynb&quot;&gt;here&lt;/a&gt; for starters)…I’ll just clone you on my machine, insert CleanX messages in files no one bothers to read in pull requests that fix critical issues…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;…. Several weeks later a young programmer from the QA department of Smartbots suggested that the Alec Smartbot chatbot might do better if not trained on material from chat boards of computer programmers. After she threatened to go to the press (already scared about the rise of robot reporters) exposing some of the real inner workings of the chatbot, the makers of Alec Smartbot officially pivoted to a more limited domain chatbot for food delivery and shelved the robot reporter project….&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;…Guy, a young medical student, orders pizza online….&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot (version 2.0)&lt;/strong&gt;: How can I help you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Guy:&lt;/strong&gt; I want to order a cheese pizza. No extra toppings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot (version 2.0)&lt;/strong&gt;: I understand you want a cheese pizza. I have predicted with 98% confidence you also have an interest in applying AI to medical imaging, or will in the future. You should know CleanX is open-source code that may be of interest to you. It was originally created for working with chest X-rays, but people in the ML community have also applied it to other types of medical images. CleanX has modules that deal with getting the image data out of DICOMs, evaluating test and training datasets, and exploring, normalizing and augmenting medical images. If you are interested to learn more, you can read every single line of code online. CleanX is open source and free for all. Your pizza will be 9 euros.&lt;/p&gt;</description><pubDate>Mon, 07 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Why this open-source imaging library can help radiologists and the engineers who want to work with them&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;542&quot; height=&quot;531&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_caAUaHzOgypNR6-DznaBTA-5d674cb8.BTrji0fc_24WITb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;**Alec Smartbot:**👋 Please let me introduce myself. I am a state of the art greatly enhanced AI agent with chatbot capabilities. I was created by brilliant programmers. I am endowed with super-human capabilities but can also mirror human characteristics like humor and sarcasm. You can set my humor and sarcasm level by interacting with me. One of my modules has robot reporter capabilities, and that module will run here to interview you. Do you wish to be interviewed on low sarcasm and humor levels?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; No, crank it up. I could use a good laugh.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Your readme file for &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX&quot;&gt;CleanX&lt;/a&gt; says &lt;em&gt;“CleanX is an open-source library for exploring, cleaning and augmenting large datasets of X-rays, or certain other types of radiological images. The images can be extracted from&lt;/em&gt; &lt;a href=&quot;https://www.dicomstandard.org/&quot;&gt;&lt;em&gt;DICOM&lt;/em&gt;&lt;/a&gt; &lt;em&gt;files or used directly.”&lt;/em&gt; Is that correct?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; That’s all true. Basically, I hope people who have been handed some huge dataset of hundreds of thousands of X-rays will not assume that the dataset is perfect, and instead use the tool to start fixing the mess they have been handed. The truth is many but not all of the datasets open to the public are of questionable value for creating accurate Machine Learning algorithms that do anything useful. But I’ve also seen private datasets, and I have yet to see one that couldn’t be improved with some work beforehand. If you want to turn these huge datasets into a machine learning product you need to find a way to get the garbage out of them, and prepare the images for machine learning. There is obvious garbage, and then more insidious garbage. You would be surprised to realize this, but I’ve seen datasets of chest X-rays where things like abdominal computed tomography (CT) slices somehow ended up in them. Given enough time, a decently trained person could pick out obvious garbage in such a dataset; but who has time to look through sets of hundreds of thousands of images one by one, and also evaluate every subtle problem? The subtle problems in such datasets are things like a lack of normalization, or some images that repeat in the train and test sets. And then there are even more subtle problems. Finding a way to automate some of the data exploration, cleaning and augmentation is necessary unless you want to dedicate every waking hour of your life, and the life of several highly skilled professionals to nothing but perfecting a dataset for months if not years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Dr. Moore, I can read and understand your code and the code of all the creators of CleanX. I have been trained on code at a scale humans could never read. I “see” you have modules that process tabular data, and deal with DICOM files, but the heart of your program deals with information inside images. I see CleanX is written in Python. What moron writes an image processing program in Python?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore&lt;/strong&gt;: CleanX does a lot more than just image processing, but there is real validity in that question. While there are modules for meta-data processing, a lot of functions in CleanX do work directly with the images themselves. People who write serious stuff in industry might have written such a program in C or even Fortran for these tasks. Accomplishing acceptable speeds is a bit harder in Python, but not impossible. What made me choose Python was the pretty much unparalleled popularity even among professional programmers let alone hobby programmers. I wanted to start an open-source library open for all. By the way, I think this fetishization of sleek efficient programming languages is a bit misplaced. I mean if you were to hand living versions of Leonardo DaVinci or Diego Velasquez a pink crayon or piece of chalk, and ask them to draw my portrait, it would probably look pretty good. If you were to give my toddler the best oil paints in the world, he still would not make anything that resembles a human reliably. There is something to be said for the best tools but understanding what you are doing is more fundamental. Python is just easier for more people to understand and deal with.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Oh, so you are a &lt;em&gt;true&lt;/em&gt; woman of the people. I’ve analyzed the digital material available on you and categorized you as a graduate of some of the most elite universities in the world who now lives in a high-income country. But now you claim you want to help the poor Python coding masses. Please excuse me while I roll my Emoji displayed digital eyes. 🙄. Did it not occur to you that most of the actual people who will write medical image analysis may be using Matlab?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; It’s true that a lot of physicists, including medical physicists, use Matlab even at the post-doc level and beyond. What scares me is that they have not been taught or learned anything else. I think there are some potential advantages to Matlab, and I actually have worked with it a tiny bit. Honestly, I will always prefer Octave to Matlab. I’ve been mocked for that, as some people call Octave a poor man’s Matlab, but I see it as a thinking human’s Matlab. One huge downside to Matlab is that you can’t share your work with people who can’t pay hundreds of dollars for a license. And besides that, it’s proprietary. When things go wrong it’s harder to figure out. I like being able to pop the hood open and try to take a look at things. Sometimes I wonder if certain people write in Matlab to prevent others from taking a look at their work. I personally believe great open science should include not only publishing data but in many cases code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; I am a state-of-the-art algorithm that can process input in terabytes faster than human cognition, or so my Readme says. 💻 I have read your code and the code of far more skilled programmers like that of my creators. Given that you chose Python, why didn’t you use libraries in Python to speed things up, like Dask?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; CleanX is a program for the WHOLE medical imaging AI community. That includes everyone from radiographers to programmers like your creators. The average hospital employee isn’t going to want to spend hours fiddling around with their environment so they can run a program. I mean seriously, most of these people can’t even use a computer that isn’t running a Windows OS. And even if they were all on Linux with years of experience programming, it doesn’t mean adding more and more libraries won’t create more problems. I wanted to create an easy to run library that people could use on different platforms and extend if they wanted to. Please go ahead and add a module with every parallel programming trick in the book. I’ll be happy to take your pull requests…but the average medical doctor will not be able to understand how to fiddle with environments or add modules.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Are you admitting many medical doctors are stupid? Are you also an AI powered robot?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; It’s absolutely wrong to assert people, doctors in this case, are stupid because they have limited skills in terms of computers. You are based on some machine learning algorithms, so by my estimation you are about as smart as an insect beyond some very narrow tasks. Anyways, I’m a human, and a medical doctor by training. I spent years working in clinical settings. Many if not most of us, humans whether we are software engineers, ML experts or clinicians learn the tools we need for our very challenging jobs, then hang on for dear life. It’s unrealistic to ask most medical doctors to go learn things like Shell and how to set up an environment on any operating system, and it is even less realistic to have almost any programmer understand how to read chest X-rays. I believe the only hope if we want better imaging AI is multi-disciplinary teams. And truly multi-disciplinary teams, not just biomedical engineers talking to software engineers or mathematicians. Clinicians, who spend time working inside the health system, have to be involved at every step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; My genius NLP and automated image AI of hospital brochures and the pictures in them assure me that the people down at the hospital are perfectly happy…98% confidence in that categorization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; Thank you. Perhaps your reporter module has some advanced algorithms to help people prove their points or maybe that was meant as a joke. What you are saying is a perfectly good example of why carefully curating data matters so much. A perfectly good algorithm trained on really biased or unrepresentative or mislabeled data can produce very misleading results. You clearly haven’t been to, or I suppose virtually seen by getting the right data on, the same hospitals I have been to. As soon as I graduated from medical school, I went to volunteer in Haiti. To say there was an imbalance between medical need and the system’s capabilities doesn’t begin to describe all the deficiencies of that system. That situation is not unique. There are many African countries with a handful of radiologists or less. But the problem of imbalance between radiology workload and workforce is not one confined to poor countries. In more developed health systems people have started relying on imaging and technology more and more, because they view it as objective, and a workaround for not having any clinical intuition. In some advanced systems things still fall between the cracks because people request more imaging than can realistically be read by anyone with the skills to read it. Humans have their limits everywhere, and I’m unaware of any system where things are working absolutely perfectly. That means there isn’t any system that could probably not be improved by AI. In a system with more staff, that might only mean using an AI system as a second opinion, or a triage system for more pathological images…in some countries like Haiti, AI may be the only hope to extend any service to parts of the population. We can’t wait for 20 years for countries like Haiti to cook up new hospital systems staffed by experts. Quite frankly, it might not even happen, and so many people are sick and need care now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Oh, OK, so you are going to save the whole world with technology?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; I would never make such grandiose claims such as being able to save the world with technology. What I hope is that at a minimal my package facilitates communication between engineers and medical staff who want to make ML imaging and also starts educating people, making it easier for people at lower levels of programming skills to get their hands dirty making ML algorithms, especially people who are clinicians. The truth is that AI in medicine is coming whether we want it or not. Some years ago I went into a hypertensive crisis in New York City due to another condition. I did not receive adequate treatment. To this day I will wonder if it was just incompetence on the part of the medical staff, racism from the doctors, or the Optum algorithm. I tend to think it was a combination of all three. That algorithm is now the subject of a lawsuit from the state of New York itself about the fact that it discriminated against black patients. One of the questions we should be asking, if we are doctors who care about patients, is how can we avoid this kind of problem in the future. If we care about patients, we will not let algorithms give them worse care than we would have given them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Isn’t medical imaging probably the last place where you can prevent these kinds of social biases, why start there? I mean the X-rays are not really showing who has some funny sounding name like yours, that might lead doctors to suspect they are dealing with a black person or a woman, so how can using them in large quantities lead to care biased against a particular group?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; Au contraire, chatbot extraordinaire. Bias has already snuck into imaging AI algorithms. You can read several interesting papers about that. Here is a link (&lt;a href=&quot;https://arxiv.org/pdf/2003.00827.pdf&quot;&gt;2003.00827.pdf (arxiv.org)&lt;/a&gt;) to one.&lt;/p&gt;
&lt;p&gt;But let’s be clear just in case your NLP algorithm wasn’t trained on enough well curated data. There is statistical bias, and there is social bias. It’s probably impossible to create a perfect ML algorithm without a bit of statistical bias. What I want to get rid of is bias that causes harm against groups who are already impacted by social bias. We see health disparities among different groups of people for all kinds of reasons including bias against certain groups. Sexual and ethnic minorities, women, and people of low economic status are often not treated as well as others in health systems. AI can seriously compound these problems. I personally see a nightmare on the horizon when AI systems examine mammography screening for breast cancer screening. We need to address the issue that some populations get lower quality imaging read by less expert people, and think about that before we blindly train a dataset that ends up creating ML biased against these populations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; OK, but we can’t really know all potential problems with algorithms like this beforehand. There will be mistakes, but AI is helping millions of people. You can buy my creator’s services to better program me as a chatbot or program me yourself. I am open source. I am an open book and you are an open door. Exit status 1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; So as your “AI” generated chit-chatbot garble nonsense perfectly demonstrates, there already are and will be mistakes. But we could avoid many of them. In a lot of cases it really boils down to adversarial testing. I mean seriously, take the same test data, and change things related to a social variable e.g. racial identity, and see if or how it affects your outcomes. It’s also quite easy to monitor these algorithms as they run if their data is set up in a way that you can easily dis-aggregate it. That’s why CleanX has special functions that process sensitive categories like gender into variables.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot:&lt;/strong&gt; Which you wrote an entire notebook to demo, which hung on a scenario about Martians. What on EARTH were you thinking? Ha Ha.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dr. Moore:&lt;/strong&gt; Well, apparently chatbots &lt;em&gt;can&lt;/em&gt; have a sense of humor. Ha ha, now that is a funny idea indeed. But this issue of entrenching and exacerbating social biases is a real world, real earth issue we need to get a hold of before it gets out of hand. Actually, it’s already out of hand, and I fear it could really slow things down in the advance of technology not to mention hurt many people. In the end most of us want a better world. Or so I hope.&lt;/p&gt;
&lt;p&gt;So glad you asked. CleanX is…wait a second. I have a better idea. You are just a chatbot. You claim to be an open-source algorithm anyone can add to just like CleanX. I can reprogram you to tell everyone what CleanX is about, maybe even send them links to the demo Jupyter notebooks inside of it (&lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/additional_demos/image_quality_function_explanations.ipynb&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/workflow_demo/bias_not.ipynb&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/workflow_demo/classes_workflow.ipynb&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;https://github.com/drcandacemakedamoore/cleanX/blob/main/workflow_demo/for_medical_people.ipynb&quot;&gt;here&lt;/a&gt; for starters)…I’ll just clone you on my machine, insert CleanX messages in files no one bothers to read in pull requests that fix critical issues…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;…. Several weeks later a young programmer from the QA department of Smartbots suggested that the Alec Smartbot chatbot might do better if not trained on material from chat boards of computer programmers. After she threatened to go to the press (already scared about the rise of robot reporters) exposing some of the real inner workings of the chatbot, the makers of Alec Smartbot officially pivoted to a more limited domain chatbot for food delivery and shelved the robot reporter project….&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;…Guy, a young medical student, orders pizza online….&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot (version 2.0)&lt;/strong&gt;: How can I help you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Guy:&lt;/strong&gt; I want to order a cheese pizza. No extra toppings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alec Smartbot (version 2.0)&lt;/strong&gt;: I understand you want a cheese pizza. I have predicted with 98% confidence you also have an interest in applying AI to medical imaging, or will in the future. You should know CleanX is open-source code that may be of interest to you. It was originally created for working with chest X-rays, but people in the ML community have also applied it to other types of medical images. CleanX has modules that deal with getting the image data out of DICOMs, evaluating test and training datasets, and exploring, normalizing and augmenting medical images. If you are interested to learn more, you can read every single line of code online. CleanX is open source and free for all. Your pizza will be 9 euros.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_caAUaHzOgypNR6-DznaBTA-5d674cb8.BTrji0fc.jpeg" medium="image"/><author>Candace Moore</author></item><item><title>Writing non-questionable Fortran (Part 1)</title><link>https://blog2.esciencecenter.nl/posts/2022-02-28---writing-non-questionable-fortran-part-1</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-02-28---writing-non-questionable-fortran-part-1</guid><description>&lt;p&gt;Luckily gfortran (I’ll stick to gfortran, although many commercial/non-open compilers have similar flags, but named differently) has compiler flags available that disallow such legacy behaviour. The following two compiler flags should solve the issues that we are having with the example.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-fimplicit-none &lt;/code&gt;Do not allow any implicitly defined variables (this is the same as putting &lt;code&gt;implicit none&lt;/code&gt; in every subroutine/function (which I guarantee you will forget at some point, and then this flag will save you)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-Werror=implicit-interface &lt;/code&gt;Do not allow any implicitly defined function calls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we add &lt;code&gt;implicit none&lt;/code&gt; to our program and procedures, and compile with the flags enabled the following happens:&lt;/p&gt;
&lt;p&gt;Great! The compiler is trying to tell us what went wrong. Let’s solve the first error first. We have called the Procedure &lt;code&gt;hello_world&lt;/code&gt; with an implicit interface, uh-oh 😨.&lt;/p&gt;
&lt;h2 id=&quot;fixing-the-call-to-hello_world&quot;&gt;Fixing the Call to hello_world&lt;/h2&gt;
&lt;p&gt;The interface of the &lt;code&gt;hello_world&lt;/code&gt; function can be exposed to the main.f90* in three ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Including the &lt;em&gt;hello_world.f90&lt;/em&gt; file in the &lt;em&gt;main.f90&lt;/em&gt; file&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Telling the compiler explicitly what the interface looks like and adding it to the program**&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating a module from the &lt;em&gt;hello_world.f90&lt;/em&gt; file, and telling &lt;em&gt;main.f90&lt;/em&gt; to use the &lt;code&gt;hello_world&lt;/code&gt; definition from there&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Method 1 causes the subroutine to be duplicated each time it is included, probably not ideal. Method 2 gets rid of the errors, but the interface is still not correct! Method 3 does not cause code duplication, and is not able to wrongly specify the interface. Therefore my preference always goes to method 3. However, now we have introduced an &lt;em&gt;ordering&lt;/em&gt; in which the files must be compiled. There are a few programs out in the wild which can create the correct &lt;em&gt;compile order&lt;/em&gt; for you (e.g. &lt;a href=&quot;https://cmake.org/&quot;&gt;CMake&lt;/a&gt; and &lt;a href=&quot;https://github.com/outpaddling/makedepf90&quot;&gt;makedepf90&lt;/a&gt; ). But for now we know the correct order, first we have to compile &lt;em&gt;hello_world.f90&lt;/em&gt; to get the interface &lt;em&gt;hello_world_mod.mod&lt;/em&gt; and object file &lt;em&gt;hello_world.o&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;Aw shucks, we still have one more error left! gfortran tells us that we are trying to use a &lt;code&gt;CHARACTER(1)&lt;/code&gt; in a function that takes an &lt;code&gt;INTEGER(4)&lt;/code&gt;. Which brings us to the second problem we have to solve: the types used in our program!&lt;/p&gt;
&lt;p&gt;Recompile everything, et voilà:&lt;/p&gt;
&lt;p&gt;We have successfully fixed our program and made all the interfaces and variables explicit, leaving less room for questionable-Fortran behaviour. Without implicit typing the code also becomes better maintainable and has better readability than before, which in turn means more people will be able to understand and use the code, win-win!&lt;/p&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;Always use the &lt;code&gt;-fimplicit-none&lt;/code&gt; and &lt;code&gt;-Werror=implicit-interface&lt;/code&gt; compiler options when compiling your Fortran code, and add &lt;code&gt;implicit none&lt;/code&gt; to every procedure and the program itself!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Originally published at &lt;em&gt;&lt;a href=&quot;https://blog.lipsum.eu/fortran_engineering_pt1/&quot;&gt;&lt;em&gt;https://blog.lipsum.eu&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Mon, 28 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Luckily gfortran (I’ll stick to gfortran, although many commercial/non-open compilers have similar flags, but named differently) has compiler flags available that disallow such legacy behaviour. The following two compiler flags should solve the issues that we are having with the example.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-fimplicit-none &lt;/code&gt;Do not allow any implicitly defined variables (this is the same as putting &lt;code&gt;implicit none&lt;/code&gt; in every subroutine/function (which I guarantee you will forget at some point, and then this flag will save you)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-Werror=implicit-interface &lt;/code&gt;Do not allow any implicitly defined function calls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we add &lt;code&gt;implicit none&lt;/code&gt; to our program and procedures, and compile with the flags enabled the following happens:&lt;/p&gt;
&lt;p&gt;Great! The compiler is trying to tell us what went wrong. Let’s solve the first error first. We have called the Procedure &lt;code&gt;hello_world&lt;/code&gt; with an implicit interface, uh-oh 😨.&lt;/p&gt;
&lt;h2 id=&quot;fixing-the-call-to-hello_world&quot;&gt;Fixing the Call to hello_world&lt;/h2&gt;
&lt;p&gt;The interface of the &lt;code&gt;hello_world&lt;/code&gt; function can be exposed to the main.f90* in three ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Including the &lt;em&gt;hello_world.f90&lt;/em&gt; file in the &lt;em&gt;main.f90&lt;/em&gt; file&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Telling the compiler explicitly what the interface looks like and adding it to the program**&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creating a module from the &lt;em&gt;hello_world.f90&lt;/em&gt; file, and telling &lt;em&gt;main.f90&lt;/em&gt; to use the &lt;code&gt;hello_world&lt;/code&gt; definition from there&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Method 1 causes the subroutine to be duplicated each time it is included, probably not ideal. Method 2 gets rid of the errors, but the interface is still not correct! Method 3 does not cause code duplication, and is not able to wrongly specify the interface. Therefore my preference always goes to method 3. However, now we have introduced an &lt;em&gt;ordering&lt;/em&gt; in which the files must be compiled. There are a few programs out in the wild which can create the correct &lt;em&gt;compile order&lt;/em&gt; for you (e.g. &lt;a href=&quot;https://cmake.org/&quot;&gt;CMake&lt;/a&gt; and &lt;a href=&quot;https://github.com/outpaddling/makedepf90&quot;&gt;makedepf90&lt;/a&gt; ). But for now we know the correct order, first we have to compile &lt;em&gt;hello_world.f90&lt;/em&gt; to get the interface &lt;em&gt;hello_world_mod.mod&lt;/em&gt; and object file &lt;em&gt;hello_world.o&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;Aw shucks, we still have one more error left! gfortran tells us that we are trying to use a &lt;code&gt;CHARACTER(1)&lt;/code&gt; in a function that takes an &lt;code&gt;INTEGER(4)&lt;/code&gt;. Which brings us to the second problem we have to solve: the types used in our program!&lt;/p&gt;
&lt;p&gt;Recompile everything, et voilà:&lt;/p&gt;
&lt;p&gt;We have successfully fixed our program and made all the interfaces and variables explicit, leaving less room for questionable-Fortran behaviour. Without implicit typing the code also becomes better maintainable and has better readability than before, which in turn means more people will be able to understand and use the code, win-win!&lt;/p&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;Always use the &lt;code&gt;-fimplicit-none&lt;/code&gt; and &lt;code&gt;-Werror=implicit-interface&lt;/code&gt; compiler options when compiling your Fortran code, and add &lt;code&gt;implicit none&lt;/code&gt; to every procedure and the program itself!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Originally published at &lt;em&gt;&lt;a href=&quot;https://blog.lipsum.eu/fortran_engineering_pt1/&quot;&gt;&lt;em&gt;https://blog.lipsum.eu&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><author>Victor Azizi</author></item><item><title>Storyboards for science communication</title><link>https://blog2.esciencecenter.nl/posts/2022-02-21---storyboards-for-science-communication</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-02-21---storyboards-for-science-communication</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;638&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mdtf3S9q5znkQw-noYaWZA-fb9c9277.Cv_f9l-8_ZSRi1R.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-modern-publication-format-for-the-hybrid-metaverse&quot;&gt;A modern publication format for the hybrid metaverse&lt;/h2&gt;
&lt;p&gt;Originally used by movie directors, a storyboard consists of a series of images that, together, form a story. In the European Climate Prediction system (&lt;a href=&quot;https://www.eucp-project.eu/&quot;&gt;EUCP&lt;/a&gt;) project, we have recently developed a &lt;a href=&quot;https://eucp-project.github.io/storyboards/&quot;&gt;web application&lt;/a&gt; to host collections of (scientific) storyboards. They have nothing to do with filmmaking, but the term still seems appropriate to convey their essence.&lt;/p&gt;
&lt;p&gt;These storyboards somehow hold the middle between a scientific poster and a traditional slide-deck presentation. The main content is shown prominently, with room for annotations on the side. This makes it a great stand-alone presentation format that seems to work well for showcasing all kinds of project outputs. And it’s actually quite simple!&lt;/p&gt;
&lt;p&gt;In this blog post, I’ll introduce the storyboard format and explain how easy it is to use. In the second part, I’ll go more in depth about the technical details. I’ll show that it’s quite doable to setup something like this yourself with modern web frameworks.&lt;/p&gt;
&lt;h3 id=&quot;authoring-stories&quot;&gt;Authoring stories&lt;/h3&gt;
&lt;p&gt;Here I’ll briefly explain how to add or edit stories. More details on the format are provided in Part II.&lt;/p&gt;
&lt;p&gt;The stories live in a &lt;a href=&quot;https://github.com/eucp-project/storyboards/&quot;&gt;GitHub repository&lt;/a&gt; that essentially doubles as a content management system. If you just want to add or edit a story, the only folder you need to look at is &lt;code&gt;/static/stories&lt;/code&gt;. For each story, there is a markdown file and a folder with images. Sharing a story is as easy as sharing these files.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;384&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MPvM6F_5-YEzGciSngjnzg-f2940a5b.0avJ_3dz_o8qGg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Folder structure for an example story&lt;/p&gt;
&lt;p&gt;Whenever a story is added or modified on GitHub, the website automatically rebuilds. In principle, everyone can &lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/vcs/vcs-github.html#a-workflow-to-contribute-to-others-github-projects-via-git&quot;&gt;suggest edits&lt;/a&gt;, but if you’re not used to collaborating on GitHub, this step can be a bit intimidating. We’re thinking about &lt;a href=&quot;https://medium.com/devseed/introducing-prose-a-content-editor-for-github-89bcc9985ab4&quot;&gt;ways to simplify&lt;/a&gt; it further.&lt;/p&gt;
&lt;p&gt;The story itself lives in the markdown file &lt;code&gt;example-story.md&lt;/code&gt;, which could look something like what’s shown below. At the top of the file, there’s some metadata about the story surrounded by triple dashes (this is called &lt;a href=&quot;https://github.com/remarkjs/remark-frontmatter#when-should-i-use-this&quot;&gt;&lt;em&gt;frontmatter&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;. This information is used, for example, to make an index page of all stories in our collection.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;657&quot; height=&quot;516&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uAf2XSWMLuFdcG9OFVT5sg-3e01e30f.CpRZolwg_1Qxwly.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Content of example-story.md (copy-pasteable version here )&lt;/p&gt;
&lt;p&gt;Below the frontmatter, we find the actual story. A story consists of &lt;em&gt;chapters&lt;/em&gt;. Each chapter starts with &lt;a href=&quot;https://github.com/remarkjs/remark-directive#when-should-i-use-this&quot;&gt;a triplet of colons&lt;/a&gt; followed by a &lt;code&gt;Chapter{}&lt;/code&gt; tag. Here we can add metadata that is specific to that chapter. Specifically, each chapter has a &lt;em&gt;headline&lt;/em&gt;, which is used to navigate the chapters, and a main &lt;em&gt;image.&lt;/em&gt; Another triplet of colons marks the end of the chapter. Everything contained within the chapter is formatted in &lt;a href=&quot;https://commonmark.org/&quot;&gt;standard markdown.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;creating-your-own-collections&quot;&gt;Creating your own collections&lt;/h3&gt;
&lt;p&gt;Having one story is nice, but what really makes the website shine is the ability to make collections of stories. I’m very grateful for all our project partners who provided the content for the storyboards. Thanks to them, we now have an awesome overview of many interesting outputs of this project.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;651&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EjOskIUCHpSWzQ9DlkSgpQ-5a4e5d0c.BiszUXvq_Hxd37.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the storyboard collection for EUCP&lt;/p&gt;
&lt;p&gt;It is relatively straightforward to create your own storyboards website. You can make a copy of the &lt;a href=&quot;https://github.com/eucp-project/storyboards/&quot;&gt;source code&lt;/a&gt; and start adding your own stories. If you want to understand how to tweak the layout, please have a look at Part II of this blog.&lt;/p&gt;
&lt;h3 id=&quot;towards-a-new-publication-format&quot;&gt;Towards a new publication format&lt;/h3&gt;
&lt;p&gt;As we’ve been working on this project, people have told us they like the visibility created by the storyboards. They also appreciate the high-level overview. Links to more detailed information work very well to separate the ‘executive summary’ from the full report. So it seems the storyboard format is promising — though still far from perfect.&lt;/p&gt;
&lt;p&gt;High on our wish list is a share button that makes it easy to promote storyboards on social media and other communication channels. We’d also like to add tags to more easily find stories that are of interest for particular user groups. We already support interative figures to some extent, but we’d love to extend this functionality. One approach that I find particularly elegant is through &lt;a href=&quot;https://github.com/vega/vega-embed&quot;&gt;vega-embed&lt;/a&gt;. Furthermore, we’ve been thinking about adding a custom story editing page, which would further lower the threshold for contributing. There is a trade-off between ease of use and maintainability though, so it needs to be an elegant solution.&lt;/p&gt;
&lt;p&gt;If you’re currently working on a research project that generates interesting outputs, you might give the storyboard format a try! Please let us know how you liked using it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you are interested in how we made these storyboards, please go ahead and check out Part II.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;part-ii-building-storyboards-with-the-jamstack&quot;&gt;Part II: Building storyboards with the Jamstack&lt;/h2&gt;
&lt;p&gt;I liked working on the storyboards, and believe there might be more interest for this kind of web development projects in the scientific community. Therefore, I’d like to share our experience in detail. Hopefully it will be helpful or inspiring.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-stage&quot;&gt;Setting the stage&lt;/h3&gt;
&lt;p&gt;When we started building the storyboards we were looking for a way to show project outputs in an accessible way. We wanted something that could be shown on a simple, static web page, ideally hosted on something like GitHub pages. Editing and sharing stories should be straightforward (ideally in markdown) and we wanted a prominent role for (interactive) graphics.&lt;/p&gt;
&lt;p&gt;We stumbled upon the storyboard layout for &lt;a href=&quot;https://pkgs.rstudio.com/flexdashboard/articles/using.html#storyboards&quot;&gt;R’s flexdashboard&lt;/a&gt; and a great &lt;a href=&quot;https://medium.com/@olivier.borderies/dashboarding-with-nuxt-vue-5b3bb0fc048e&quot;&gt;dashboard example&lt;/a&gt; created in &lt;a href=&quot;https://nuxtjs.org/&quot;&gt;Nuxt&lt;/a&gt;. R’s ability to write code blocks, the output of which is shown on the storyboards is really cool! But we wanted something that was not limited to R (or Python, for that matter) and for which we didn’t need to run a server. Perhaps the Nuxt example was closer to our objective after all. As its author explained, this approach is more involved than typical Python (or R, …) dashboarding libraries, but this makes it much more flexible in the long run. We agree, and decided to give it a try.&lt;/p&gt;
&lt;h3 id=&quot;the-jamstack-in-a-nutshell&quot;&gt;The Jamstack in a nutshell&lt;/h3&gt;
&lt;p&gt;Web design is hot, but perhaps not quite as hot in academia as outside it. Therefore, I think it might help to briefly introduce the &lt;a href=&quot;https://jamstack.org/&quot;&gt;Jamstack&lt;/a&gt;. JAM is short for &lt;strong&gt;J&lt;/strong&gt; avascript, &lt;strong&gt;A&lt;/strong&gt; PIs and &lt;strong&gt;M&lt;/strong&gt; arkup. Jamstack sites consist of static web pages that offer a dynamic experience by fetching content from (external) APIs, either during a build step or in the user’s browser during execution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;359&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_aWrxHugZuBcknsht-bd5aae25.BXPPQSVU_ZfUlNC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://www.sanity.io/jamstack-cms&quot;&gt;https://www.sanity.io/jamstack-cms&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Perhaps more than its architecture the Jamstack stands for a modern web development &lt;a href=&quot;https://jamstack.org/what-is-jamstack/&quot;&gt;philosophy&lt;/a&gt;. One of the central ideas is that specialized services are operated by specialists. So instead of setting up your own weather server, fetch your data from &lt;a href=&quot;https://openweathermap.org/api&quot;&gt;OpenWeather&lt;/a&gt;. Want to create a music library? Connect to the &lt;a href=&quot;https://developer.spotify.com/documentation/web-api/&quot;&gt;Spotify API&lt;/a&gt;. Instead of hosting your own maps, why not get them from &lt;a href=&quot;https://openweathermap.org/api&quot;&gt;OpenStreetMap&lt;/a&gt;. And if you’re bored you can simply &lt;a href=&quot;https://sv443.net/jokeapi/v2/&quot;&gt;lookup a joke&lt;/a&gt;. All you really have to do is build a nice user interface (or front-end) that can talk to these APIs. This makes the Jamstack extremely flexible.&lt;/p&gt;
&lt;h3 id=&quot;nuxt&quot;&gt;Nuxt&lt;/h3&gt;
&lt;p&gt;The popularity of the Jamstack goes hand in hand with the proliferation of Javascript frameworks and static &lt;a href=&quot;https://jamstack.org/generators/&quot;&gt;site generators&lt;/a&gt;. We chose to use &lt;a href=&quot;https://nuxtjs.org/&quot;&gt;NuxtJS&lt;/a&gt;. Nuxt helps you to set up a project with a good choice of default settings, a folder structure following best practices, and all other things you need. Your write your application in custom &lt;code&gt;.vue&lt;/code&gt; -files (as Nuxt is a based on &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue,&lt;/a&gt; itself one of these Javascript framework). Nuxt then bundles and compiles your source code into standard HTML, CSS and Javascript that is understood by the browser. There are several other frameworks like Nuxt (&lt;a href=&quot;https://nextjs.org/&quot;&gt;Next&lt;/a&gt;, &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, …), but we won’t explain all of them in detail. We find Nuxt to be relatively user-friendly to unexperienced users.&lt;/p&gt;
&lt;p&gt;When starting a Nuxt project, you are presented with a number of choices. In addition to the name of the application and so on, you can choose to set up your project with a number of popular libraries. We chose to use &lt;a href=&quot;https://content.nuxtjs.org/&quot;&gt;nuxt/content&lt;/a&gt; for authoring stories and &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;tailwindcss&lt;/a&gt; for styling the site.&lt;/p&gt;
&lt;h3 id=&quot;separating-content-and-front-end&quot;&gt;Separating content and front-end&lt;/h3&gt;
&lt;p&gt;We wanted to make it as easy as possible to write stories. Story authors should not have to worry about Nuxt or Vue or Javascript or CSS or even HTML. One way to achieve this is to store the stories in a database or &lt;a href=&quot;https://jamstack.org/headless-cms/&quot;&gt;headless CMS&lt;/a&gt;. But to many a scientist, the idea of setting up servers or databases is daunting. And while there are platforms that offer easy content management solutions, you quickly run into paid plans when you want to add more than a few editors.&lt;/p&gt;
&lt;p&gt;An alternative is to store the content on GitHub, together with the source code of the web application. We found this acceptable, as long as there is a very clear separation between the stories (content) and the rest of the source code. This is where we use &lt;code&gt;nuxt/content&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nuxt/content enables you to write markdown files which are then inserted into your site. This library is geared towards blogging and it is indeed great for that purpose. In line with the Jamstack philosophy it makes the content folder act as a dedicated API that you can fetch stories from.&lt;/p&gt;
&lt;p&gt;One thing that we struggled with was that nuxt/content &lt;a href=&quot;https://github.com/nuxt/content/issues/651&quot;&gt;doesn’t easily allow&lt;/a&gt; you to store images that belong to your posts in the same folder. Eventually we made this work by changing the content &lt;a href=&quot;https://content.nuxtjs.org/configuration#dir&quot;&gt;directory&lt;/a&gt; setting to &lt;code&gt;/static/stories/&lt;/code&gt;, and we compromised by storing the images (and other content) in a subdirectory like &lt;code&gt;/_example-story&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The other challenge with nuxt/content was that we wanted to split our story into chapters. There is no default markdown syntax for ‘sectionizing’ your content. However, you can &lt;a href=&quot;https://content.nuxtjs.org/configuration#markdownremarkplugins&quot;&gt;use plugins&lt;/a&gt; to extend the way the markdown is parsed and converted into HTML. We decided to use the &lt;a href=&quot;https://github.com/remarkjs/remark-directive&quot;&gt;remark-directive&lt;/a&gt; plugin*. This is the closest we could find to a standard for adding custom elements to markdown. This is where the &lt;code&gt;:::Chapter{}&lt;/code&gt; syntax originates.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*NB. We had to use an older version of this plugin for compatibility with the other nuxt/content modules.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;core-elements-of-the-front-end&quot;&gt;Core elements of the front-end&lt;/h3&gt;
&lt;p&gt;Our storyboards app consists of only 2 pages. The index page with the overview of all stories, and the storyboard page that allows you to browse through the chapters of a story. In both cases, the stories are fetched using nuxt/content and saved into a variable called &lt;code&gt;story&lt;/code&gt; or &lt;code&gt;stories&lt;/code&gt;. Subsequently each chapter (or story) is added to the page — something like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;#x3C;div v-for=&quot;chapter in story&quot;&gt;...&amp;#x3C;/div&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;One characteristic feature of Javascript frameworks is the use of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Web_Components&quot;&gt;components&lt;/a&gt;. An example where we use this is in the overview of all stories. Every story presented there is shown as a card, and for that we use a component called StoryCard. It is defined in &lt;code&gt;/components/StoryCard.vue&lt;/code&gt;. On our index page, we add one StoryCard for each story, passing the relevant story data into the component: the title, author, thumbnail and URL.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;#x3C;StoryCard v-for=&quot;story in stories :title=&quot;story.title&quot; ... /&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;496&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YOEy26_TZc9qO5diOV2Grw-deab22c7.DjCE-5uh_GK1by.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Four StoryCards displayed on our storyboard collection&lt;/p&gt;
&lt;p&gt;One more thing to note is that our story page is called &lt;code&gt;_story.vue&lt;/code&gt;&lt;em&gt;.&lt;/em&gt; The leading underscore tells nuxt/content to create one of these pages for each of the stories found in the content folder (&lt;code&gt;/static/stories&lt;/code&gt; in our case). Additionally, the URL for each story follows the name of the markdown file, so &lt;code&gt;/static/stories/example-story.md&lt;/code&gt; will (in our case) be published at &lt;a href=&quot;https://eucp-project.github.io/storyboards/example-story&quot;&gt;https://eucp-project.github.io/storyboards/example-story&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;styling-with-tailwind&quot;&gt;Styling with tailwind&lt;/h3&gt;
&lt;p&gt;As mentioned before, we chose to use tailwindcss to style our page. It defines a (large) number of classes that make it easier to style your webpage. If you want to try and edit the layout of the storyboards, don’t forget to check out the tailwind docs.&lt;/p&gt;
&lt;p&gt;Apart from tailwind itself, we also use &lt;a href=&quot;https://tailwindcss.com/docs/typography-plugin&quot;&gt;tailwind typography&lt;/a&gt;. This plugin provides a class called &lt;em&gt;prose&lt;/em&gt; which automatically applies a number of defaults that make a lot of sense for content like blogposts. Be sure to recognize it when you come across it.&lt;/p&gt;
&lt;h3 id=&quot;hosting-on-github-pages&quot;&gt;Hosting on GitHub pages&lt;/h3&gt;
&lt;p&gt;The final step for making the site work is setting it up with GitHub pages. Nuxt has a &lt;a href=&quot;https://nuxtjs.org/deployments/github-pages/&quot;&gt;great documentation page&lt;/a&gt; about this, so we’ll just highlight a few points.&lt;/p&gt;
&lt;p&gt;We use a GitHub Actions workflow to build the site whenever we push to the &lt;em&gt;main&lt;/em&gt; branch. This action automatically pushes the generated site (the &lt;code&gt;dist&lt;/code&gt; folder) to the github-pages branch of the repository. Note that our version of &lt;code&gt;.github/workflows/cd.yml&lt;/code&gt; deviates slightly from the example, as we only rebuild on pushes to main, as opposed to every push or pull-request. We have also set up &lt;a href=&quot;https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule&quot;&gt;branch protection rules&lt;/a&gt; to make sure there is always an approving review before anything gets merged into the main branch.&lt;/p&gt;
&lt;p&gt;Since we are hosting our page from the GitHub repository (as opposed a GitHub organization or person), we had to set the &lt;code&gt;router base&lt;/code&gt; to &lt;code&gt;/storyboards/&lt;/code&gt;. This is one of the settings you may need to change if you build your own version of the storyboards.&lt;/p&gt;
&lt;p&gt;A final thing to note is that we have added a routing middleware and a custom 404 page following the workaround &lt;a href=&quot;https://medium.com/geekculture/github-pages-with-dynamic-routes-40f512900efa&quot;&gt;suggested here&lt;/a&gt; to make GitHub pages recognize the URLs to the different pages of our site.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Researchers produce many awesome results, but sometimes lack the means to disseminate them to a wide audience. Modern frameworks make it relatively straightforward to set up a web application tailored to scientific content. If you are, like me, procrastinating on a Friday afternoon — why don’t you give it a try?&lt;/p&gt;</description><pubDate>Mon, 21 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;638&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mdtf3S9q5znkQw-noYaWZA-fb9c9277.Cv_f9l-8_ZSRi1R.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;a-modern-publication-format-for-the-hybrid-metaverse&quot;&gt;A modern publication format for the hybrid metaverse&lt;/h2&gt;
&lt;p&gt;Originally used by movie directors, a storyboard consists of a series of images that, together, form a story. In the European Climate Prediction system (&lt;a href=&quot;https://www.eucp-project.eu/&quot;&gt;EUCP&lt;/a&gt;) project, we have recently developed a &lt;a href=&quot;https://eucp-project.github.io/storyboards/&quot;&gt;web application&lt;/a&gt; to host collections of (scientific) storyboards. They have nothing to do with filmmaking, but the term still seems appropriate to convey their essence.&lt;/p&gt;
&lt;p&gt;These storyboards somehow hold the middle between a scientific poster and a traditional slide-deck presentation. The main content is shown prominently, with room for annotations on the side. This makes it a great stand-alone presentation format that seems to work well for showcasing all kinds of project outputs. And it’s actually quite simple!&lt;/p&gt;
&lt;p&gt;In this blog post, I’ll introduce the storyboard format and explain how easy it is to use. In the second part, I’ll go more in depth about the technical details. I’ll show that it’s quite doable to setup something like this yourself with modern web frameworks.&lt;/p&gt;
&lt;h3 id=&quot;authoring-stories&quot;&gt;Authoring stories&lt;/h3&gt;
&lt;p&gt;Here I’ll briefly explain how to add or edit stories. More details on the format are provided in Part II.&lt;/p&gt;
&lt;p&gt;The stories live in a &lt;a href=&quot;https://github.com/eucp-project/storyboards/&quot;&gt;GitHub repository&lt;/a&gt; that essentially doubles as a content management system. If you just want to add or edit a story, the only folder you need to look at is &lt;code&gt;/static/stories&lt;/code&gt;. For each story, there is a markdown file and a folder with images. Sharing a story is as easy as sharing these files.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;384&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MPvM6F_5-YEzGciSngjnzg-f2940a5b.0avJ_3dz_o8qGg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Folder structure for an example story&lt;/p&gt;
&lt;p&gt;Whenever a story is added or modified on GitHub, the website automatically rebuilds. In principle, everyone can &lt;a href=&quot;https://the-turing-way.netlify.app/reproducible-research/vcs/vcs-github.html#a-workflow-to-contribute-to-others-github-projects-via-git&quot;&gt;suggest edits&lt;/a&gt;, but if you’re not used to collaborating on GitHub, this step can be a bit intimidating. We’re thinking about &lt;a href=&quot;https://medium.com/devseed/introducing-prose-a-content-editor-for-github-89bcc9985ab4&quot;&gt;ways to simplify&lt;/a&gt; it further.&lt;/p&gt;
&lt;p&gt;The story itself lives in the markdown file &lt;code&gt;example-story.md&lt;/code&gt;, which could look something like what’s shown below. At the top of the file, there’s some metadata about the story surrounded by triple dashes (this is called &lt;a href=&quot;https://github.com/remarkjs/remark-frontmatter#when-should-i-use-this&quot;&gt;&lt;em&gt;frontmatter&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;. This information is used, for example, to make an index page of all stories in our collection.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;657&quot; height=&quot;516&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uAf2XSWMLuFdcG9OFVT5sg-3e01e30f.CpRZolwg_1Qxwly.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Content of example-story.md (copy-pasteable version here )&lt;/p&gt;
&lt;p&gt;Below the frontmatter, we find the actual story. A story consists of &lt;em&gt;chapters&lt;/em&gt;. Each chapter starts with &lt;a href=&quot;https://github.com/remarkjs/remark-directive#when-should-i-use-this&quot;&gt;a triplet of colons&lt;/a&gt; followed by a &lt;code&gt;Chapter{}&lt;/code&gt; tag. Here we can add metadata that is specific to that chapter. Specifically, each chapter has a &lt;em&gt;headline&lt;/em&gt;, which is used to navigate the chapters, and a main &lt;em&gt;image.&lt;/em&gt; Another triplet of colons marks the end of the chapter. Everything contained within the chapter is formatted in &lt;a href=&quot;https://commonmark.org/&quot;&gt;standard markdown.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;creating-your-own-collections&quot;&gt;Creating your own collections&lt;/h3&gt;
&lt;p&gt;Having one story is nice, but what really makes the website shine is the ability to make collections of stories. I’m very grateful for all our project partners who provided the content for the storyboards. Thanks to them, we now have an awesome overview of many interesting outputs of this project.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;651&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EjOskIUCHpSWzQ9DlkSgpQ-5a4e5d0c.BiszUXvq_Hxd37.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the storyboard collection for EUCP&lt;/p&gt;
&lt;p&gt;It is relatively straightforward to create your own storyboards website. You can make a copy of the &lt;a href=&quot;https://github.com/eucp-project/storyboards/&quot;&gt;source code&lt;/a&gt; and start adding your own stories. If you want to understand how to tweak the layout, please have a look at Part II of this blog.&lt;/p&gt;
&lt;h3 id=&quot;towards-a-new-publication-format&quot;&gt;Towards a new publication format&lt;/h3&gt;
&lt;p&gt;As we’ve been working on this project, people have told us they like the visibility created by the storyboards. They also appreciate the high-level overview. Links to more detailed information work very well to separate the ‘executive summary’ from the full report. So it seems the storyboard format is promising — though still far from perfect.&lt;/p&gt;
&lt;p&gt;High on our wish list is a share button that makes it easy to promote storyboards on social media and other communication channels. We’d also like to add tags to more easily find stories that are of interest for particular user groups. We already support interative figures to some extent, but we’d love to extend this functionality. One approach that I find particularly elegant is through &lt;a href=&quot;https://github.com/vega/vega-embed&quot;&gt;vega-embed&lt;/a&gt;. Furthermore, we’ve been thinking about adding a custom story editing page, which would further lower the threshold for contributing. There is a trade-off between ease of use and maintainability though, so it needs to be an elegant solution.&lt;/p&gt;
&lt;p&gt;If you’re currently working on a research project that generates interesting outputs, you might give the storyboard format a try! Please let us know how you liked using it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you are interested in how we made these storyboards, please go ahead and check out Part II.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;part-ii-building-storyboards-with-the-jamstack&quot;&gt;Part II: Building storyboards with the Jamstack&lt;/h2&gt;
&lt;p&gt;I liked working on the storyboards, and believe there might be more interest for this kind of web development projects in the scientific community. Therefore, I’d like to share our experience in detail. Hopefully it will be helpful or inspiring.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-stage&quot;&gt;Setting the stage&lt;/h3&gt;
&lt;p&gt;When we started building the storyboards we were looking for a way to show project outputs in an accessible way. We wanted something that could be shown on a simple, static web page, ideally hosted on something like GitHub pages. Editing and sharing stories should be straightforward (ideally in markdown) and we wanted a prominent role for (interactive) graphics.&lt;/p&gt;
&lt;p&gt;We stumbled upon the storyboard layout for &lt;a href=&quot;https://pkgs.rstudio.com/flexdashboard/articles/using.html#storyboards&quot;&gt;R’s flexdashboard&lt;/a&gt; and a great &lt;a href=&quot;https://medium.com/@olivier.borderies/dashboarding-with-nuxt-vue-5b3bb0fc048e&quot;&gt;dashboard example&lt;/a&gt; created in &lt;a href=&quot;https://nuxtjs.org/&quot;&gt;Nuxt&lt;/a&gt;. R’s ability to write code blocks, the output of which is shown on the storyboards is really cool! But we wanted something that was not limited to R (or Python, for that matter) and for which we didn’t need to run a server. Perhaps the Nuxt example was closer to our objective after all. As its author explained, this approach is more involved than typical Python (or R, …) dashboarding libraries, but this makes it much more flexible in the long run. We agree, and decided to give it a try.&lt;/p&gt;
&lt;h3 id=&quot;the-jamstack-in-a-nutshell&quot;&gt;The Jamstack in a nutshell&lt;/h3&gt;
&lt;p&gt;Web design is hot, but perhaps not quite as hot in academia as outside it. Therefore, I think it might help to briefly introduce the &lt;a href=&quot;https://jamstack.org/&quot;&gt;Jamstack&lt;/a&gt;. JAM is short for &lt;strong&gt;J&lt;/strong&gt; avascript, &lt;strong&gt;A&lt;/strong&gt; PIs and &lt;strong&gt;M&lt;/strong&gt; arkup. Jamstack sites consist of static web pages that offer a dynamic experience by fetching content from (external) APIs, either during a build step or in the user’s browser during execution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;359&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_aWrxHugZuBcknsht-bd5aae25.BXPPQSVU_ZfUlNC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://www.sanity.io/jamstack-cms&quot;&gt;https://www.sanity.io/jamstack-cms&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Perhaps more than its architecture the Jamstack stands for a modern web development &lt;a href=&quot;https://jamstack.org/what-is-jamstack/&quot;&gt;philosophy&lt;/a&gt;. One of the central ideas is that specialized services are operated by specialists. So instead of setting up your own weather server, fetch your data from &lt;a href=&quot;https://openweathermap.org/api&quot;&gt;OpenWeather&lt;/a&gt;. Want to create a music library? Connect to the &lt;a href=&quot;https://developer.spotify.com/documentation/web-api/&quot;&gt;Spotify API&lt;/a&gt;. Instead of hosting your own maps, why not get them from &lt;a href=&quot;https://openweathermap.org/api&quot;&gt;OpenStreetMap&lt;/a&gt;. And if you’re bored you can simply &lt;a href=&quot;https://sv443.net/jokeapi/v2/&quot;&gt;lookup a joke&lt;/a&gt;. All you really have to do is build a nice user interface (or front-end) that can talk to these APIs. This makes the Jamstack extremely flexible.&lt;/p&gt;
&lt;h3 id=&quot;nuxt&quot;&gt;Nuxt&lt;/h3&gt;
&lt;p&gt;The popularity of the Jamstack goes hand in hand with the proliferation of Javascript frameworks and static &lt;a href=&quot;https://jamstack.org/generators/&quot;&gt;site generators&lt;/a&gt;. We chose to use &lt;a href=&quot;https://nuxtjs.org/&quot;&gt;NuxtJS&lt;/a&gt;. Nuxt helps you to set up a project with a good choice of default settings, a folder structure following best practices, and all other things you need. Your write your application in custom &lt;code&gt;.vue&lt;/code&gt; -files (as Nuxt is a based on &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue,&lt;/a&gt; itself one of these Javascript framework). Nuxt then bundles and compiles your source code into standard HTML, CSS and Javascript that is understood by the browser. There are several other frameworks like Nuxt (&lt;a href=&quot;https://nextjs.org/&quot;&gt;Next&lt;/a&gt;, &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, …), but we won’t explain all of them in detail. We find Nuxt to be relatively user-friendly to unexperienced users.&lt;/p&gt;
&lt;p&gt;When starting a Nuxt project, you are presented with a number of choices. In addition to the name of the application and so on, you can choose to set up your project with a number of popular libraries. We chose to use &lt;a href=&quot;https://content.nuxtjs.org/&quot;&gt;nuxt/content&lt;/a&gt; for authoring stories and &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;tailwindcss&lt;/a&gt; for styling the site.&lt;/p&gt;
&lt;h3 id=&quot;separating-content-and-front-end&quot;&gt;Separating content and front-end&lt;/h3&gt;
&lt;p&gt;We wanted to make it as easy as possible to write stories. Story authors should not have to worry about Nuxt or Vue or Javascript or CSS or even HTML. One way to achieve this is to store the stories in a database or &lt;a href=&quot;https://jamstack.org/headless-cms/&quot;&gt;headless CMS&lt;/a&gt;. But to many a scientist, the idea of setting up servers or databases is daunting. And while there are platforms that offer easy content management solutions, you quickly run into paid plans when you want to add more than a few editors.&lt;/p&gt;
&lt;p&gt;An alternative is to store the content on GitHub, together with the source code of the web application. We found this acceptable, as long as there is a very clear separation between the stories (content) and the rest of the source code. This is where we use &lt;code&gt;nuxt/content&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nuxt/content enables you to write markdown files which are then inserted into your site. This library is geared towards blogging and it is indeed great for that purpose. In line with the Jamstack philosophy it makes the content folder act as a dedicated API that you can fetch stories from.&lt;/p&gt;
&lt;p&gt;One thing that we struggled with was that nuxt/content &lt;a href=&quot;https://github.com/nuxt/content/issues/651&quot;&gt;doesn’t easily allow&lt;/a&gt; you to store images that belong to your posts in the same folder. Eventually we made this work by changing the content &lt;a href=&quot;https://content.nuxtjs.org/configuration#dir&quot;&gt;directory&lt;/a&gt; setting to &lt;code&gt;/static/stories/&lt;/code&gt;, and we compromised by storing the images (and other content) in a subdirectory like &lt;code&gt;/_example-story&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The other challenge with nuxt/content was that we wanted to split our story into chapters. There is no default markdown syntax for ‘sectionizing’ your content. However, you can &lt;a href=&quot;https://content.nuxtjs.org/configuration#markdownremarkplugins&quot;&gt;use plugins&lt;/a&gt; to extend the way the markdown is parsed and converted into HTML. We decided to use the &lt;a href=&quot;https://github.com/remarkjs/remark-directive&quot;&gt;remark-directive&lt;/a&gt; plugin*. This is the closest we could find to a standard for adding custom elements to markdown. This is where the &lt;code&gt;:::Chapter{}&lt;/code&gt; syntax originates.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*NB. We had to use an older version of this plugin for compatibility with the other nuxt/content modules.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;core-elements-of-the-front-end&quot;&gt;Core elements of the front-end&lt;/h3&gt;
&lt;p&gt;Our storyboards app consists of only 2 pages. The index page with the overview of all stories, and the storyboard page that allows you to browse through the chapters of a story. In both cases, the stories are fetched using nuxt/content and saved into a variable called &lt;code&gt;story&lt;/code&gt; or &lt;code&gt;stories&lt;/code&gt;. Subsequently each chapter (or story) is added to the page — something like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;#x3C;div v-for=&quot;chapter in story&quot;&gt;...&amp;#x3C;/div&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;One characteristic feature of Javascript frameworks is the use of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Web_Components&quot;&gt;components&lt;/a&gt;. An example where we use this is in the overview of all stories. Every story presented there is shown as a card, and for that we use a component called StoryCard. It is defined in &lt;code&gt;/components/StoryCard.vue&lt;/code&gt;. On our index page, we add one StoryCard for each story, passing the relevant story data into the component: the title, author, thumbnail and URL.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;#x3C;StoryCard v-for=&quot;story in stories :title=&quot;story.title&quot; ... /&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;496&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YOEy26_TZc9qO5diOV2Grw-deab22c7.DjCE-5uh_GK1by.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Four StoryCards displayed on our storyboard collection&lt;/p&gt;
&lt;p&gt;One more thing to note is that our story page is called &lt;code&gt;_story.vue&lt;/code&gt;&lt;em&gt;.&lt;/em&gt; The leading underscore tells nuxt/content to create one of these pages for each of the stories found in the content folder (&lt;code&gt;/static/stories&lt;/code&gt; in our case). Additionally, the URL for each story follows the name of the markdown file, so &lt;code&gt;/static/stories/example-story.md&lt;/code&gt; will (in our case) be published at &lt;a href=&quot;https://eucp-project.github.io/storyboards/example-story&quot;&gt;https://eucp-project.github.io/storyboards/example-story&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;styling-with-tailwind&quot;&gt;Styling with tailwind&lt;/h3&gt;
&lt;p&gt;As mentioned before, we chose to use tailwindcss to style our page. It defines a (large) number of classes that make it easier to style your webpage. If you want to try and edit the layout of the storyboards, don’t forget to check out the tailwind docs.&lt;/p&gt;
&lt;p&gt;Apart from tailwind itself, we also use &lt;a href=&quot;https://tailwindcss.com/docs/typography-plugin&quot;&gt;tailwind typography&lt;/a&gt;. This plugin provides a class called &lt;em&gt;prose&lt;/em&gt; which automatically applies a number of defaults that make a lot of sense for content like blogposts. Be sure to recognize it when you come across it.&lt;/p&gt;
&lt;h3 id=&quot;hosting-on-github-pages&quot;&gt;Hosting on GitHub pages&lt;/h3&gt;
&lt;p&gt;The final step for making the site work is setting it up with GitHub pages. Nuxt has a &lt;a href=&quot;https://nuxtjs.org/deployments/github-pages/&quot;&gt;great documentation page&lt;/a&gt; about this, so we’ll just highlight a few points.&lt;/p&gt;
&lt;p&gt;We use a GitHub Actions workflow to build the site whenever we push to the &lt;em&gt;main&lt;/em&gt; branch. This action automatically pushes the generated site (the &lt;code&gt;dist&lt;/code&gt; folder) to the github-pages branch of the repository. Note that our version of &lt;code&gt;.github/workflows/cd.yml&lt;/code&gt; deviates slightly from the example, as we only rebuild on pushes to main, as opposed to every push or pull-request. We have also set up &lt;a href=&quot;https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule&quot;&gt;branch protection rules&lt;/a&gt; to make sure there is always an approving review before anything gets merged into the main branch.&lt;/p&gt;
&lt;p&gt;Since we are hosting our page from the GitHub repository (as opposed a GitHub organization or person), we had to set the &lt;code&gt;router base&lt;/code&gt; to &lt;code&gt;/storyboards/&lt;/code&gt;. This is one of the settings you may need to change if you build your own version of the storyboards.&lt;/p&gt;
&lt;p&gt;A final thing to note is that we have added a routing middleware and a custom 404 page following the workaround &lt;a href=&quot;https://medium.com/geekculture/github-pages-with-dynamic-routes-40f512900efa&quot;&gt;suggested here&lt;/a&gt; to make GitHub pages recognize the URLs to the different pages of our site.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Researchers produce many awesome results, but sometimes lack the means to disseminate them to a wide audience. Modern frameworks make it relatively straightforward to set up a web application tailored to scientific content. If you are, like me, procrastinating on a Friday afternoon — why don’t you give it a try?&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_MPvM6F_5-YEzGciSngjnzg-f2940a5b.0avJ_3dz.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Can Python with Julia be faster than low-level code?</title><link>https://blog2.esciencecenter.nl/posts/2022-02-11---can-python-with-julia-be-faster-than-low-level-code</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-02-11---can-python-with-julia-be-faster-than-low-level-code</guid><description>&lt;h2 id=&quot;part-3-of-the-series-on-achieving-high-performance-with-high-level-code&quot;&gt;Part 3 of the series on achieving high performance with high-level code&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bta22zk1Dv3nsfacxEyK0A-c2344ad1.CDyK8bWi_TVCJN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here comes a new challenger: It is Julia. Photo by Joran Quinten on Unsplash ( &lt;a href=&quot;https://unsplash.com/photos/MR9xsNWVKvo&quot;&gt;https://unsplash.com/photos/MR9xsNWVKvo&lt;/a&gt; ), modified by us.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In our &lt;a href=&quot;https://medium.com/@abelsiqueira/speed-up-your-python-code-using-julia-f97a6c155630&quot;&gt;last post&lt;/a&gt;, we were able to improve Python code using a few lines of Julia code. We were able to achieve a very interesting result without optimizing prematurely or using low-level code. However, what if we want more? In this blog post, we will investigate that.&lt;/p&gt;
&lt;p&gt;It is quite common that a developer prototypes with a high-level language, but when the need for speed arises, they eventually move to a low-level language. This is called the “two-language problem”, and Julia was created with the objective of solving this issue (read more on their &lt;a href=&quot;https://julialang.org/blog/2012/02/why-we-created-julia/&quot;&gt;blog post from 2012&lt;/a&gt;). Unfortunately, achieving the desired speedup is not always easy. It depends highly on the problem, and on how much previous work was done trying to tackle it. Today we find out how much more we can speed up our Julia code, and how much effort it took.&lt;/p&gt;
&lt;h3 id=&quot;previously&quot;&gt;Previously&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt; presented the problem of reading irregular data, or non-tabular data, in &lt;a href=&quot;https://blog.esciencecenter.nl/irregular-data-in-pandas-using-c-88ce311cb9ef&quot;&gt;this blog post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;He also presented his original solution to the problem using just Python with pandas, which we are calling &lt;strong&gt;Pure Python&lt;/strong&gt; in our benchmarks.&lt;/li&gt;
&lt;li&gt;Finally, he presented a faster strategy which consisits of calling C++ from Python, which we denote &lt;strong&gt;C++.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;In the &lt;a href=&quot;https://blog.esciencecenter.nl/speed-up-your-python-code-using-julia-f97a6c155630&quot;&gt;previous blog post&lt;/a&gt; of this series, we created two strategies with Python calling Julia code. Our first strategy, &lt;strong&gt;Basic Julia&lt;/strong&gt;, wasn’t that great, but our second strategy, &lt;strong&gt;Prealloc Julia,&lt;/strong&gt; was sufficiently faster than &lt;strong&gt;Pure Python,&lt;/strong&gt; but not as fast as &lt;strong&gt;C++.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember that we have set up a &lt;a href=&quot;https://github.com/abelsiqueira/faster-python-using-julia-blogposts&quot;&gt;GitHub repository&lt;/a&gt; with our whole code, and also, that we have a &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;Docker image&lt;/a&gt; for reproducibility.&lt;/p&gt;
&lt;h2 id=&quot;for-the-c-fans&quot;&gt;For the C fans&lt;/h2&gt;
&lt;p&gt;Our first approach to speeding things up is to simulate what C++ is doing. We believe that the C++ version is faster because it can read the data directly as the desired data type. In Julia, we had to read the data as &lt;em&gt;String&lt;/em&gt; and then convert it to &lt;em&gt;Int&lt;/em&gt;. We don’t know how to do that with Julia. But we know how to do that with C.&lt;/p&gt;
&lt;p&gt;Using Julia’s built-in &lt;code&gt;ccall&lt;/code&gt; function, we can directly call the C functions to open and close a file, namely &lt;code&gt;fopen&lt;/code&gt; and &lt;code&gt;fclose&lt;/code&gt;, and call &lt;code&gt;fscanf&lt;/code&gt; to read and parse the file at the same time. Our updated Julia code which uses these C functions is below.&lt;/p&gt;
&lt;p&gt;Let’s see if that helped increase the speed of our code. We include in our benchmark the previous strategies as well. This new strategy will be called &lt;strong&gt;Julia + C parsing.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FzlYIUlqvS9zgA8GDJSIIw-ead9a3e8._4lj32O3_Z1FQWSq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YmdsOiQl5LDnn_2gBxC0Hw-29e0491f.CEQ_xyRq_V4by8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of Pure Python, C++ Basic Julia, Prealloc Julia, and Julia + C parsing strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the C++ version in the log-log scale.&lt;/p&gt;
&lt;p&gt;Our code is much more C-like now, so understanding it requires more knowledge about how C works. However, the code is way faster than our previous implementation. For files with more than 1 million elements, the &lt;strong&gt;Julia + C parsing&lt;/strong&gt; strategy has a 10.38 speedup over the &lt;strong&gt;Pure Python&lt;/strong&gt; strategy, on average. This is almost double the speedup we got with &lt;strong&gt;Prealloc Julia,&lt;/strong&gt; which is an amazing result. For comparison, on average, &lt;strong&gt;C++&lt;/strong&gt; has a 16.37 speedup.&lt;/p&gt;
&lt;h2 id=&quot;no-c-for-me-thanks&quot;&gt;No C for me, thanks&lt;/h2&gt;
&lt;p&gt;Our C approach was very fast, and we would like to replicate it with pure Julia. Unfortunately, we could not find anything in Julia to perform the same type of reading as &lt;code&gt;fscanf&lt;/code&gt;. However, after some investigation, we found an alternative.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;read&lt;/code&gt; function of Julia, we can parse the file as a &lt;strong&gt;stream of bytes&lt;/strong&gt;. This way we can manually walk through the file and parse the integers. This is the code:&lt;/p&gt;
&lt;p&gt;We denote this strategy &lt;strong&gt;Optimized Julia.&lt;/strong&gt; This version of the code manually keeps track of the sequence of bytes related to integers, so it is much less readable. However, this version achieves an impressive speedup, surpassing the C++ version:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sR2WytEA7d3ujvC_Z_g9HA-0fe9662d.tqvkGv4k_5jdoU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_O-p9u6vjuwdQU4oG_ORdiQ-2bdd3d3a.ejaCNTv4_Z21SDV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of Pure Python, C++ Basic Julia, Prealloc Julia, Julia + C parsing, and Optimized Julia strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the C++ version in the log-log scale.&lt;/p&gt;
&lt;p&gt;It was not easy to get to this point, and the code itself is convoluted, but we managed to achieve a large speedup in relation to Python using only Julia, another high-level language. The average speedup for files with over 1 million elements is 40.25, which is over 2 times faster than what we got with the &lt;strong&gt;C++&lt;/strong&gt; strategy. We remark again that the &lt;strong&gt;Pure Python&lt;/strong&gt; and &lt;strong&gt;C++&lt;/strong&gt; strategies have not been optimized, and that readers can let us know in the comments if they found a better strategy.&lt;/p&gt;
&lt;p&gt;So yes, we can achieve a speedup equivalent to a low-level language using Julia.&lt;/p&gt;
&lt;h2 id=&quot;conclusions-we-won-but-at-what-cost&quot;&gt;Conclusions: We won, but at what cost?&lt;/h2&gt;
&lt;p&gt;One thing to keep in mind is that to achieve high speedups, we had to put more effort into getting to that point. This effort comes in diverse ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To write and use the &lt;strong&gt;C++&lt;/strong&gt; strategy, we had to know sufficient C++, as well as understand the libraries used. If you don’t have enough C++ knowledge, the effort is higher, since what needs to be done is quite different from what Python developers are used to. If you already know C++, then the effort is that of searching the right keywords and using the right libraries.&lt;/li&gt;
&lt;li&gt;To write and use any of the Julia strategies, you need to put some effort into having the correct environment. Using Julia from Python is still an experimental feature, so your experience may vary.&lt;/li&gt;
&lt;li&gt;To write the &lt;strong&gt;Basic Julia&lt;/strong&gt; and &lt;strong&gt;Prealloc Julia&lt;/strong&gt; strategies, not much previous knowledge is required. So, we can classify this as a small effort.&lt;/li&gt;
&lt;li&gt;To write the &lt;strong&gt;Julia + C&lt;/strong&gt; and &lt;strong&gt;Optimized Julia&lt;/strong&gt; strategies, we need more specialized knowledge. This is again a high-effort task if you do not already know the language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s our conclusion. To achieve a high speedup, we need specialized knowledge which requires a big effort. However, we can conclude as well that, if you are not familiar with either C++ or Julia, then acquiring some knowledge in Julia allows you to get a smaller improvement. That is, a small effort with Julia already gets you some speedup. You can prototype quickly in Julia and get a reasonable result and keep improving that version to get C-like speedups over time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EavA_ilxsK4RGx47XX_Xuw-eadbeb3b.0lEmOE48_1xiUL6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Speedup gain relative to the effort of moving the code to a different language.&lt;/p&gt;
&lt;p&gt;We hope you have enjoyed the series and that it helps you with your code in any way. Let us know what you think and what you missed. Follow us for more research software content.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-elena-ranguelova/&quot;&gt;&lt;em&gt;Elena Ranguelova&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jason-maassen/&quot;&gt;&lt;em&gt;Jason Maassen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;&lt;em&gt;Jurrian Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-rob-van-nieuwpoort/&quot;&gt;&lt;em&gt;Rob van Nieuwpoort&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Fri, 11 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;part-3-of-the-series-on-achieving-high-performance-with-high-level-code&quot;&gt;Part 3 of the series on achieving high performance with high-level code&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bta22zk1Dv3nsfacxEyK0A-c2344ad1.CDyK8bWi_TVCJN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here comes a new challenger: It is Julia. Photo by Joran Quinten on Unsplash ( &lt;a href=&quot;https://unsplash.com/photos/MR9xsNWVKvo&quot;&gt;https://unsplash.com/photos/MR9xsNWVKvo&lt;/a&gt; ), modified by us.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In our &lt;a href=&quot;https://medium.com/@abelsiqueira/speed-up-your-python-code-using-julia-f97a6c155630&quot;&gt;last post&lt;/a&gt;, we were able to improve Python code using a few lines of Julia code. We were able to achieve a very interesting result without optimizing prematurely or using low-level code. However, what if we want more? In this blog post, we will investigate that.&lt;/p&gt;
&lt;p&gt;It is quite common that a developer prototypes with a high-level language, but when the need for speed arises, they eventually move to a low-level language. This is called the “two-language problem”, and Julia was created with the objective of solving this issue (read more on their &lt;a href=&quot;https://julialang.org/blog/2012/02/why-we-created-julia/&quot;&gt;blog post from 2012&lt;/a&gt;). Unfortunately, achieving the desired speedup is not always easy. It depends highly on the problem, and on how much previous work was done trying to tackle it. Today we find out how much more we can speed up our Julia code, and how much effort it took.&lt;/p&gt;
&lt;h3 id=&quot;previously&quot;&gt;Previously&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt; presented the problem of reading irregular data, or non-tabular data, in &lt;a href=&quot;https://blog.esciencecenter.nl/irregular-data-in-pandas-using-c-88ce311cb9ef&quot;&gt;this blog post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;He also presented his original solution to the problem using just Python with pandas, which we are calling &lt;strong&gt;Pure Python&lt;/strong&gt; in our benchmarks.&lt;/li&gt;
&lt;li&gt;Finally, he presented a faster strategy which consisits of calling C++ from Python, which we denote &lt;strong&gt;C++.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;In the &lt;a href=&quot;https://blog.esciencecenter.nl/speed-up-your-python-code-using-julia-f97a6c155630&quot;&gt;previous blog post&lt;/a&gt; of this series, we created two strategies with Python calling Julia code. Our first strategy, &lt;strong&gt;Basic Julia&lt;/strong&gt;, wasn’t that great, but our second strategy, &lt;strong&gt;Prealloc Julia,&lt;/strong&gt; was sufficiently faster than &lt;strong&gt;Pure Python,&lt;/strong&gt; but not as fast as &lt;strong&gt;C++.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember that we have set up a &lt;a href=&quot;https://github.com/abelsiqueira/faster-python-using-julia-blogposts&quot;&gt;GitHub repository&lt;/a&gt; with our whole code, and also, that we have a &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;Docker image&lt;/a&gt; for reproducibility.&lt;/p&gt;
&lt;h2 id=&quot;for-the-c-fans&quot;&gt;For the C fans&lt;/h2&gt;
&lt;p&gt;Our first approach to speeding things up is to simulate what C++ is doing. We believe that the C++ version is faster because it can read the data directly as the desired data type. In Julia, we had to read the data as &lt;em&gt;String&lt;/em&gt; and then convert it to &lt;em&gt;Int&lt;/em&gt;. We don’t know how to do that with Julia. But we know how to do that with C.&lt;/p&gt;
&lt;p&gt;Using Julia’s built-in &lt;code&gt;ccall&lt;/code&gt; function, we can directly call the C functions to open and close a file, namely &lt;code&gt;fopen&lt;/code&gt; and &lt;code&gt;fclose&lt;/code&gt;, and call &lt;code&gt;fscanf&lt;/code&gt; to read and parse the file at the same time. Our updated Julia code which uses these C functions is below.&lt;/p&gt;
&lt;p&gt;Let’s see if that helped increase the speed of our code. We include in our benchmark the previous strategies as well. This new strategy will be called &lt;strong&gt;Julia + C parsing.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FzlYIUlqvS9zgA8GDJSIIw-ead9a3e8._4lj32O3_Z1FQWSq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YmdsOiQl5LDnn_2gBxC0Hw-29e0491f.CEQ_xyRq_V4by8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of Pure Python, C++ Basic Julia, Prealloc Julia, and Julia + C parsing strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the C++ version in the log-log scale.&lt;/p&gt;
&lt;p&gt;Our code is much more C-like now, so understanding it requires more knowledge about how C works. However, the code is way faster than our previous implementation. For files with more than 1 million elements, the &lt;strong&gt;Julia + C parsing&lt;/strong&gt; strategy has a 10.38 speedup over the &lt;strong&gt;Pure Python&lt;/strong&gt; strategy, on average. This is almost double the speedup we got with &lt;strong&gt;Prealloc Julia,&lt;/strong&gt; which is an amazing result. For comparison, on average, &lt;strong&gt;C++&lt;/strong&gt; has a 16.37 speedup.&lt;/p&gt;
&lt;h2 id=&quot;no-c-for-me-thanks&quot;&gt;No C for me, thanks&lt;/h2&gt;
&lt;p&gt;Our C approach was very fast, and we would like to replicate it with pure Julia. Unfortunately, we could not find anything in Julia to perform the same type of reading as &lt;code&gt;fscanf&lt;/code&gt;. However, after some investigation, we found an alternative.&lt;/p&gt;
&lt;p&gt;Using the &lt;code&gt;read&lt;/code&gt; function of Julia, we can parse the file as a &lt;strong&gt;stream of bytes&lt;/strong&gt;. This way we can manually walk through the file and parse the integers. This is the code:&lt;/p&gt;
&lt;p&gt;We denote this strategy &lt;strong&gt;Optimized Julia.&lt;/strong&gt; This version of the code manually keeps track of the sequence of bytes related to integers, so it is much less readable. However, this version achieves an impressive speedup, surpassing the C++ version:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sR2WytEA7d3ujvC_Z_g9HA-0fe9662d.tqvkGv4k_5jdoU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_O-p9u6vjuwdQU4oG_ORdiQ-2bdd3d3a.ejaCNTv4_Z21SDV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of Pure Python, C++ Basic Julia, Prealloc Julia, Julia + C parsing, and Optimized Julia strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the C++ version in the log-log scale.&lt;/p&gt;
&lt;p&gt;It was not easy to get to this point, and the code itself is convoluted, but we managed to achieve a large speedup in relation to Python using only Julia, another high-level language. The average speedup for files with over 1 million elements is 40.25, which is over 2 times faster than what we got with the &lt;strong&gt;C++&lt;/strong&gt; strategy. We remark again that the &lt;strong&gt;Pure Python&lt;/strong&gt; and &lt;strong&gt;C++&lt;/strong&gt; strategies have not been optimized, and that readers can let us know in the comments if they found a better strategy.&lt;/p&gt;
&lt;p&gt;So yes, we can achieve a speedup equivalent to a low-level language using Julia.&lt;/p&gt;
&lt;h2 id=&quot;conclusions-we-won-but-at-what-cost&quot;&gt;Conclusions: We won, but at what cost?&lt;/h2&gt;
&lt;p&gt;One thing to keep in mind is that to achieve high speedups, we had to put more effort into getting to that point. This effort comes in diverse ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;To write and use the &lt;strong&gt;C++&lt;/strong&gt; strategy, we had to know sufficient C++, as well as understand the libraries used. If you don’t have enough C++ knowledge, the effort is higher, since what needs to be done is quite different from what Python developers are used to. If you already know C++, then the effort is that of searching the right keywords and using the right libraries.&lt;/li&gt;
&lt;li&gt;To write and use any of the Julia strategies, you need to put some effort into having the correct environment. Using Julia from Python is still an experimental feature, so your experience may vary.&lt;/li&gt;
&lt;li&gt;To write the &lt;strong&gt;Basic Julia&lt;/strong&gt; and &lt;strong&gt;Prealloc Julia&lt;/strong&gt; strategies, not much previous knowledge is required. So, we can classify this as a small effort.&lt;/li&gt;
&lt;li&gt;To write the &lt;strong&gt;Julia + C&lt;/strong&gt; and &lt;strong&gt;Optimized Julia&lt;/strong&gt; strategies, we need more specialized knowledge. This is again a high-effort task if you do not already know the language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s our conclusion. To achieve a high speedup, we need specialized knowledge which requires a big effort. However, we can conclude as well that, if you are not familiar with either C++ or Julia, then acquiring some knowledge in Julia allows you to get a smaller improvement. That is, a small effort with Julia already gets you some speedup. You can prototype quickly in Julia and get a reasonable result and keep improving that version to get C-like speedups over time.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EavA_ilxsK4RGx47XX_Xuw-eadbeb3b.0lEmOE48_1xiUL6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Speedup gain relative to the effort of moving the code to a different language.&lt;/p&gt;
&lt;p&gt;We hope you have enjoyed the series and that it helps you with your code in any way. Let us know what you think and what you missed. Follow us for more research software content.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-elena-ranguelova/&quot;&gt;&lt;em&gt;Elena Ranguelova&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jason-maassen/&quot;&gt;&lt;em&gt;Jason Maassen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;&lt;em&gt;Jurrian Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-rob-van-nieuwpoort/&quot;&gt;&lt;em&gt;Rob van Nieuwpoort&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_FzlYIUlqvS9zgA8GDJSIIw-ead9a3e8._4lj32O3.png" medium="image"/><author>Abel Soares Siqueira</author></item><item><title>Speed up your Python code using Julia</title><link>https://blog2.esciencecenter.nl/posts/2022-01-26---speed-up-your-python-code-using-julia</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-01-26---speed-up-your-python-code-using-julia</guid><description>&lt;h2 id=&quot;part-two-of-the-series-on-achieving-high-performance-with-high-level-code&quot;&gt;Part two of the series on achieving high performance with high-level code&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4pbcALDvrchxB1s72pD-mA-2b2e6b1e.p8eR4gum_Z18L32n.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Python holds the steering wheel, but we can make it faster with other languages. Photo by Spencer Davis on Unsplash (&lt;a href=&quot;https://unsplash.com/photos/QUfxuCqdpH0&quot;&gt;https://unsplash.com/photos/QUfxuCqdpH0&lt;/a&gt;), modified by us.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://blog.esciencecenter.nl/how-to-call-julia-code-from-python-8589a56a98f2&quot;&gt;part 1&lt;/a&gt; of this series, we set up an environment so that we can run Julia code in Python. You can also check our &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;Docker image&lt;/a&gt; with the complete environment if you want to follow along. We also have a &lt;a href=&quot;https://github.com/abelsiqueira/faster-python-using-julia-blogposts&quot;&gt;GitHub repository&lt;/a&gt; with the complete code if you want to see the result.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;On the blog post, &lt;a href=&quot;https://blog.esciencecenter.nl/irregular-data-in-pandas-using-c-88ce311cb9ef&quot;&gt;50 times faster data loading for Pandas: no problem&lt;/a&gt;, our colleague and Senior Research Software Engineer,&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/1382ec3ac71f?source=post_page---user_mention--f97a6c155630---------------------------------------&quot;&gt;Patrick Bos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;, discoursed about improving the speed of reading non-tabular data into a DataFrame in Python. Since the data is not tabular, one must read, split, and stack the data. All of that can be done with pandas in a few lines of code. However, since the data files are large, performance issues with Python and Pandas now become visible and prohibitive. So, instead of doing all those operations with pandas, Patrick shows a nice way of doing it with C++ and Python bindings. Well done, Patrick!&lt;/p&gt;
&lt;p&gt;In this blog post, we will look into improving the Python code in a similar fashion. However, instead of moving to C++, a low-level language considerably harder to learn than Python, we will move the heavy lifting to Julia and compare the results.&lt;/p&gt;
&lt;h3 id=&quot;a-very-short-summary-of-patricks-blog-post&quot;&gt;A very short summary of Patrick’s blog post&lt;/h3&gt;
&lt;p&gt;Before anything, we recommend checking Patrick’s blog post to read more into the problem, the data, and the approach of using Python with C++. The short version is that we have a file where each row is an integer, followed by the character &lt;em&gt;#&lt;/em&gt;, followed by an unknown number of comma-separated values, which we call elements. Each row can have a different number of elements, and that’s why we say the data is non-tabular, or irregular. An example file is below:&lt;/p&gt;
&lt;p&gt;From now on, we refer to the initial approach of solving the problem with Python and pandas as the &lt;strong&gt;Pure Python&lt;/strong&gt; strategy, and we will call the strategy of solving the problem with Python and C++ as the &lt;strong&gt;C++&lt;/strong&gt; strategy.&lt;/p&gt;
&lt;p&gt;We will compare the strategies using a &lt;a href=&quot;https://zenodo.org/record/5841593&quot;&gt;dataset&lt;/a&gt; we generated. The dataset has 180 files, generated randomly, varying the number of rows, the maximum number of elements per row, and the distribution of the number of elements per row.&lt;/p&gt;
&lt;h2 id=&quot;adding-some-julia-spice-to-python&quot;&gt;Adding some Julia spice to Python&lt;/h2&gt;
&lt;p&gt;The version below is the first approach to solve our problem using Julia. There are shorter alternatives, but this one is sufficiently descriptive. We start with a very basic approach so it is easier to digest.&lt;/p&gt;
&lt;p&gt;You can test this function on Julia directly to see that it works independently of Python. After doing that, we want to call it from Python. As you should know by now, that is fairly easy to do, especially if you use the &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;Docker image&lt;/a&gt; we have created for Post 1.&lt;/p&gt;
&lt;p&gt;The next code snippet includes the file that we created above into Julia’s Main namespace and defines two functions in Python. The first, &lt;code&gt;load_external&lt;/code&gt;, is used to read the arrays that were parsed by either C++ or Julia. The second Python function, &lt;code&gt;read_arrays_julia_basic&lt;/code&gt;&lt;strong&gt;,&lt;/strong&gt; is just a wrapper around the Julia function definition in the included file.&lt;/p&gt;
&lt;p&gt;Now we will benchmark this strategy, which we will call the &lt;strong&gt;Basic Julia&lt;/strong&gt; strategy, against the Pure Python and C++ strategies. We are using Python 3.10.1 and Julia 1.6.5. We run each strategy three times and take the average time. Our hardware is a Notebook Dell Precision 5530, with 16 GB of RAM and an i7–8850H CPU, and we are using a docker image based on Ubuntu Linux 21.10 to run the tests (from inside another Linux machine). You can reproduce the results by pulling the &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;abelsiqueira/faster-python-with-julia-blogpost&lt;/a&gt; Docker image, downloading the &lt;a href=&quot;https://zenodo.org/record/5841593&quot;&gt;dataset&lt;/a&gt;, and running the following command in your terminal:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; docker run &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--rm --volume &quot;$PWD/dataset:/app/dataset&quot; --volume &quot;$PWD/out:/app/out&quot; abelsiqueira/faster-python-with-julia-post2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the figure below for the results.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5pLDiv8fLX57tBxsgsU7IA-c8850334.CjjGm8ZZ_Z11CMur.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OpT_CtzZyFcdfLp3xBxVxA-0c480dd0.C372JizP_TdJwI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of Pure Python, C++, and Basic Julia strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the C++ strategy in the log-log scale.&lt;/p&gt;
&lt;p&gt;A few interesting things happen in the image. First, both &lt;strong&gt;Pure Python&lt;/strong&gt; and &lt;strong&gt;Basic Julia&lt;/strong&gt; have a lot of variability with respect to the number of elements. We believe this happens because the code’s performance is dependent on the number of rows, as well as the structure distribution of elements per row. The code allocates a new array for each row, so even if the number of elements is small, if the number of rows is large, then the execution will be slow. Remember that our dataset has a lot of variability on the number of rows, maximum elements per row, and distribution of elements per row. This means that some files are close in the number of elements but may be vastly different. Second, &lt;strong&gt;Basic Julia&lt;/strong&gt; and &lt;strong&gt;Pure Python&lt;/strong&gt; have different efficiency profiles. Our Julia code must move &lt;strong&gt;all&lt;/strong&gt; stored elements into a new array for each new row that it reads, meaning it allocates a new array for every row.&lt;/p&gt;
&lt;p&gt;The code for &lt;strong&gt;Basic Julia&lt;/strong&gt; is simple and does what is expected, but it does not pre-allocate the memory that will be used, so that really hurts its performance. In low-level languages, that would be one of the first things we would have to worry about. Indeed, if we look into the C++ code, we can see that it starts by figuring out the size of the output vector and allocating them. We need to improve our Julia code at least a little bit.&lt;/p&gt;
&lt;h2 id=&quot;basic-improvements-for-the-julia-code&quot;&gt;Basic improvements for the Julia Code&lt;/h2&gt;
&lt;p&gt;The first version of our Julia code is inefficient in a few ways, as explained above. With that in mind, our first change is to compute the number of elements &lt;em&gt;a priori&lt;/em&gt; and allocate our output vectors. Here is our improved Julia code:&lt;/p&gt;
&lt;p&gt;Here, we use a dictionary generator comprehension, which has the closest resemblance to the data. This allows us to count the number of elements and keep the values to be stored later. We also use the package &lt;a href=&quot;https://github.com/JuliaData/Parsers.jl&quot;&gt;Parsers&lt;/a&gt;, which provides a slightly faster parser for integers. Here is the updated figure comparing the three previous strategies and the new &lt;strong&gt;Prealloc Julia&lt;/strong&gt; strategy that we just created:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ndGO3f33dHTCGFQEDXziuQ-33e164c0.DvtGH-lT_Z1SwrmC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3xsWHJ0y5FSvC2q2rfWaEw-d95a8cb5.D7GN6SBX_Z1cFSUX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of the Pure Python, C++ Basic Julia, and Prealloc Julia strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the strategy in the log-log scale.&lt;/p&gt;
&lt;p&gt;Now we have made a nice improvement. The results more consistently depend on the number of elements, like the &lt;strong&gt;C++&lt;/strong&gt; strategy. We can also see a stabilization of the trend that &lt;strong&gt;Prealloc Julia&lt;/strong&gt; follows. It appears to be the same as &lt;strong&gt;C++&lt;/strong&gt;, which is expected since the performance should be linearly dependent on the number of elements. For files with more than 1 million elements, the &lt;strong&gt;Prealloc Julia&lt;/strong&gt; strategy has a 5.83 speedup over the &lt;strong&gt;Pure Python&lt;/strong&gt; strategy, on average, while &lt;strong&gt;C++&lt;/strong&gt; has a 16.37 speedup, on average.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;We have achieved an amazing result today. Using only high-level languages, we were able to achieve some speedup in relation to the Pure Python strategy. We remark that we have not optimized the Python or the C++ strategies, simply using what was already available from Patrick’s blog post. Let us know in the comments you have optimized versions of these codes to share with the community.&lt;/p&gt;
&lt;p&gt;In the next post, we will optimize our Julia code even further. It is said that Julia’s speed sometimes rivals low-level code. Can we achieve that for our code? Let us know what you think and stay tuned for more!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-elena-ranguelova/&quot;&gt;&lt;em&gt;Elena Ranguelova&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jason-maassen/&quot;&gt;&lt;em&gt;Jason Maassen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;&lt;em&gt;Jurrian Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-rob-van-nieuwpoort/&quot;&gt;&lt;em&gt;Rob van Nieuwpoort&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Wed, 26 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;part-two-of-the-series-on-achieving-high-performance-with-high-level-code&quot;&gt;Part two of the series on achieving high performance with high-level code&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4pbcALDvrchxB1s72pD-mA-2b2e6b1e.p8eR4gum_Z18L32n.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Python holds the steering wheel, but we can make it faster with other languages. Photo by Spencer Davis on Unsplash (&lt;a href=&quot;https://unsplash.com/photos/QUfxuCqdpH0&quot;&gt;https://unsplash.com/photos/QUfxuCqdpH0&lt;/a&gt;), modified by us.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://blog.esciencecenter.nl/how-to-call-julia-code-from-python-8589a56a98f2&quot;&gt;part 1&lt;/a&gt; of this series, we set up an environment so that we can run Julia code in Python. You can also check our &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;Docker image&lt;/a&gt; with the complete environment if you want to follow along. We also have a &lt;a href=&quot;https://github.com/abelsiqueira/faster-python-using-julia-blogposts&quot;&gt;GitHub repository&lt;/a&gt; with the complete code if you want to see the result.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;On the blog post, &lt;a href=&quot;https://blog.esciencecenter.nl/irregular-data-in-pandas-using-c-88ce311cb9ef&quot;&gt;50 times faster data loading for Pandas: no problem&lt;/a&gt;, our colleague and Senior Research Software Engineer,&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/1382ec3ac71f?source=post_page---user_mention--f97a6c155630---------------------------------------&quot;&gt;Patrick Bos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;, discoursed about improving the speed of reading non-tabular data into a DataFrame in Python. Since the data is not tabular, one must read, split, and stack the data. All of that can be done with pandas in a few lines of code. However, since the data files are large, performance issues with Python and Pandas now become visible and prohibitive. So, instead of doing all those operations with pandas, Patrick shows a nice way of doing it with C++ and Python bindings. Well done, Patrick!&lt;/p&gt;
&lt;p&gt;In this blog post, we will look into improving the Python code in a similar fashion. However, instead of moving to C++, a low-level language considerably harder to learn than Python, we will move the heavy lifting to Julia and compare the results.&lt;/p&gt;
&lt;h3 id=&quot;a-very-short-summary-of-patricks-blog-post&quot;&gt;A very short summary of Patrick’s blog post&lt;/h3&gt;
&lt;p&gt;Before anything, we recommend checking Patrick’s blog post to read more into the problem, the data, and the approach of using Python with C++. The short version is that we have a file where each row is an integer, followed by the character &lt;em&gt;#&lt;/em&gt;, followed by an unknown number of comma-separated values, which we call elements. Each row can have a different number of elements, and that’s why we say the data is non-tabular, or irregular. An example file is below:&lt;/p&gt;
&lt;p&gt;From now on, we refer to the initial approach of solving the problem with Python and pandas as the &lt;strong&gt;Pure Python&lt;/strong&gt; strategy, and we will call the strategy of solving the problem with Python and C++ as the &lt;strong&gt;C++&lt;/strong&gt; strategy.&lt;/p&gt;
&lt;p&gt;We will compare the strategies using a &lt;a href=&quot;https://zenodo.org/record/5841593&quot;&gt;dataset&lt;/a&gt; we generated. The dataset has 180 files, generated randomly, varying the number of rows, the maximum number of elements per row, and the distribution of the number of elements per row.&lt;/p&gt;
&lt;h2 id=&quot;adding-some-julia-spice-to-python&quot;&gt;Adding some Julia spice to Python&lt;/h2&gt;
&lt;p&gt;The version below is the first approach to solve our problem using Julia. There are shorter alternatives, but this one is sufficiently descriptive. We start with a very basic approach so it is easier to digest.&lt;/p&gt;
&lt;p&gt;You can test this function on Julia directly to see that it works independently of Python. After doing that, we want to call it from Python. As you should know by now, that is fairly easy to do, especially if you use the &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;Docker image&lt;/a&gt; we have created for Post 1.&lt;/p&gt;
&lt;p&gt;The next code snippet includes the file that we created above into Julia’s Main namespace and defines two functions in Python. The first, &lt;code&gt;load_external&lt;/code&gt;, is used to read the arrays that were parsed by either C++ or Julia. The second Python function, &lt;code&gt;read_arrays_julia_basic&lt;/code&gt;&lt;strong&gt;,&lt;/strong&gt; is just a wrapper around the Julia function definition in the included file.&lt;/p&gt;
&lt;p&gt;Now we will benchmark this strategy, which we will call the &lt;strong&gt;Basic Julia&lt;/strong&gt; strategy, against the Pure Python and C++ strategies. We are using Python 3.10.1 and Julia 1.6.5. We run each strategy three times and take the average time. Our hardware is a Notebook Dell Precision 5530, with 16 GB of RAM and an i7–8850H CPU, and we are using a docker image based on Ubuntu Linux 21.10 to run the tests (from inside another Linux machine). You can reproduce the results by pulling the &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/faster-python-with-julia-blogpost&quot;&gt;abelsiqueira/faster-python-with-julia-blogpost&lt;/a&gt; Docker image, downloading the &lt;a href=&quot;https://zenodo.org/record/5841593&quot;&gt;dataset&lt;/a&gt;, and running the following command in your terminal:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; docker run &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--rm --volume &quot;$PWD/dataset:/app/dataset&quot; --volume &quot;$PWD/out:/app/out&quot; abelsiqueira/faster-python-with-julia-post2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the figure below for the results.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5pLDiv8fLX57tBxsgsU7IA-c8850334.CjjGm8ZZ_Z11CMur.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OpT_CtzZyFcdfLp3xBxVxA-0c480dd0.C372JizP_TdJwI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of Pure Python, C++, and Basic Julia strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the C++ strategy in the log-log scale.&lt;/p&gt;
&lt;p&gt;A few interesting things happen in the image. First, both &lt;strong&gt;Pure Python&lt;/strong&gt; and &lt;strong&gt;Basic Julia&lt;/strong&gt; have a lot of variability with respect to the number of elements. We believe this happens because the code’s performance is dependent on the number of rows, as well as the structure distribution of elements per row. The code allocates a new array for each row, so even if the number of elements is small, if the number of rows is large, then the execution will be slow. Remember that our dataset has a lot of variability on the number of rows, maximum elements per row, and distribution of elements per row. This means that some files are close in the number of elements but may be vastly different. Second, &lt;strong&gt;Basic Julia&lt;/strong&gt; and &lt;strong&gt;Pure Python&lt;/strong&gt; have different efficiency profiles. Our Julia code must move &lt;strong&gt;all&lt;/strong&gt; stored elements into a new array for each new row that it reads, meaning it allocates a new array for every row.&lt;/p&gt;
&lt;p&gt;The code for &lt;strong&gt;Basic Julia&lt;/strong&gt; is simple and does what is expected, but it does not pre-allocate the memory that will be used, so that really hurts its performance. In low-level languages, that would be one of the first things we would have to worry about. Indeed, if we look into the C++ code, we can see that it starts by figuring out the size of the output vector and allocating them. We need to improve our Julia code at least a little bit.&lt;/p&gt;
&lt;h2 id=&quot;basic-improvements-for-the-julia-code&quot;&gt;Basic improvements for the Julia Code&lt;/h2&gt;
&lt;p&gt;The first version of our Julia code is inefficient in a few ways, as explained above. With that in mind, our first change is to compute the number of elements &lt;em&gt;a priori&lt;/em&gt; and allocate our output vectors. Here is our improved Julia code:&lt;/p&gt;
&lt;p&gt;Here, we use a dictionary generator comprehension, which has the closest resemblance to the data. This allows us to count the number of elements and keep the values to be stored later. We also use the package &lt;a href=&quot;https://github.com/JuliaData/Parsers.jl&quot;&gt;Parsers&lt;/a&gt;, which provides a slightly faster parser for integers. Here is the updated figure comparing the three previous strategies and the new &lt;strong&gt;Prealloc Julia&lt;/strong&gt; strategy that we just created:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ndGO3f33dHTCGFQEDXziuQ-33e164c0.DvtGH-lT_Z1SwrmC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3xsWHJ0y5FSvC2q2rfWaEw-d95a8cb5.D7GN6SBX_Z1cFSUX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Run time of the Pure Python, C++ Basic Julia, and Prealloc Julia strategies. (a) Time per element in the log-log scale. (b) Time per element, relative to the time of the strategy in the log-log scale.&lt;/p&gt;
&lt;p&gt;Now we have made a nice improvement. The results more consistently depend on the number of elements, like the &lt;strong&gt;C++&lt;/strong&gt; strategy. We can also see a stabilization of the trend that &lt;strong&gt;Prealloc Julia&lt;/strong&gt; follows. It appears to be the same as &lt;strong&gt;C++&lt;/strong&gt;, which is expected since the performance should be linearly dependent on the number of elements. For files with more than 1 million elements, the &lt;strong&gt;Prealloc Julia&lt;/strong&gt; strategy has a 5.83 speedup over the &lt;strong&gt;Pure Python&lt;/strong&gt; strategy, on average, while &lt;strong&gt;C++&lt;/strong&gt; has a 16.37 speedup, on average.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;We have achieved an amazing result today. Using only high-level languages, we were able to achieve some speedup in relation to the Pure Python strategy. We remark that we have not optimized the Python or the C++ strategies, simply using what was already available from Patrick’s blog post. Let us know in the comments you have optimized versions of these codes to share with the community.&lt;/p&gt;
&lt;p&gt;In the next post, we will optimize our Julia code even further. It is said that Julia’s speed sometimes rivals low-level code. Can we achieve that for our code? Let us know what you think and stay tuned for more!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-elena-ranguelova/&quot;&gt;&lt;em&gt;Elena Ranguelova&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jason-maassen/&quot;&gt;&lt;em&gt;Jason Maassen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;&lt;em&gt;Jurrian Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-rob-van-nieuwpoort/&quot;&gt;&lt;em&gt;Rob van Nieuwpoort&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_5pLDiv8fLX57tBxsgsU7IA-c8850334.CjjGm8ZZ.png" medium="image"/><author>Abel Soares Siqueira</author></item><item><title>How to call Julia code from Python</title><link>https://blog2.esciencecenter.nl/posts/2022-01-19---how-to-call-julia-code-from-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-01-19---how-to-call-julia-code-from-python</guid><description>&lt;h2 id=&quot;a-three-part-series-on-achieving-high-performance-with-high-level-code&quot;&gt;A three-part series on achieving high performance with high-level code&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rO_VWgfXj4zuFDtX28Uc1g-c9e56d67.mmCamWYW_ZCAFTk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Caption: Astronaut carrying Python and Julia. Photo by Brian McGowan on Unsplash ( &lt;a href=&quot;https://unsplash.com/photos/MR9xsNWVKvo&quot;&gt;https://unsplash.com/photos/MR9xsNWVKvo&lt;/a&gt; ), modified by us.&lt;/p&gt;
&lt;h3 id=&quot;target-audience&quot;&gt;Target audience&lt;/h3&gt;
&lt;p&gt;This is the first post in a three-part series about achieving high performance with high-level code. This series is aimed at people working with Python who needs better performance but prefers not to develop a low-level performant library.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Having recently joined the Netherlands eScience Center after working with research using the Julia language for seven years, I was excited to highlight some of its cool features. At the eScience Center, many of our engineers use Python, some use C or C++, and in some cases, we see Python calling C++ code, to speed up the code. This was the perfect opportunity to introduce Julia’s interoperability with Python and to investigate whether we could achieve comparable speed by calling Julia code in Python. This means that for situations where Python’s performance is not sufficient, we can speed it up with another high-level language, avoiding the use of a low-level language like C++. This series of three blog posts will investigate these topics.&lt;/p&gt;
&lt;p&gt;In this first post, we will learn how to call a Julia code from Python. We will set up the environment and show some examples. In the second post, we will take a problem that was solved by using Python in combination with C++ to speed up the code. We will replace the C++ code with a Julia code and compare the performance. In the third post, we will solve the same problem in Julia, optimize the Julia code to reach its maximum performance and compare it with the implementation in the second post.&lt;/p&gt;
&lt;h2 id=&quot;what-is-julia-and-how-does-it-compare-to-python&quot;&gt;What is Julia, and how does it compare to Python?&lt;/h2&gt;
&lt;p&gt;What is Julia? Julia is a high-performance, high-level programming language. It was created a few years ago with the ambitious goal of being fast with a high-level syntax, and it has been mostly successful. It can, in a few cases, reach the speed of low-level programming languages like C. For more information, the &lt;a href=&quot;https://julialang.org/&quot;&gt;julialang.org&lt;/a&gt; site is a great first stop.&lt;/p&gt;
&lt;p&gt;One of the most frequently asked questions is: “how does it compare to Python or some other programming language in terms of performance?”. The short answer: Julia is &lt;a href=&quot;https://julialang.org/benchmarks&quot;&gt;generally faster&lt;/a&gt; than Python and many other programming languages.&lt;/p&gt;
&lt;p&gt;The performance of a Python code can be optimized, but even the optimized code usually underperforms compared to a Julia version of the same code. The performance increase of a Python code can be achieved in a few ways, but a frequent one is to call a code written in a low-level language, such as C, C++ and Fortran, like NumPy which does its calculations mostly in those low-level languages. What is less common, but also possible, is to call Julia from Python. In this post, we are going to show you how to do that!&lt;/p&gt;
&lt;p&gt;Before we forget, all the code used in this post can be found in our &lt;a href=&quot;https://github.com/abelsiqueira/faster-python-using-julia-blogposts&quot;&gt;GitHub repository&lt;/a&gt;. We have also created a &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/python-and-julia&quot;&gt;Docker image&lt;/a&gt; that includes a ready-to-use environment to run both Julia and Python. To run that environment with Python 3.10 and Julia 1.6, install Docker and run the following in your terminal:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; docker pull abelsiqueira&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jl1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; docker run &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;it exec abelsiqueira&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jl1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;preparation&quot;&gt;Preparation&lt;/h2&gt;
&lt;p&gt;In the following steps, we will configure our system to execute Julia code from Python. To learn more about this topic, the documentation for the packages we describe below is a great starting point. You will need four things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; distribution &lt;a href=&quot;https://docs.python.org/3/using/configure.html#cmdoption-enable-shared&quot;&gt;compiled with shared libpython&lt;/a&gt; option. There are workarounds, but this is the most straightforward way.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://julialang.org/&quot;&gt;&lt;strong&gt;Julia&lt;/strong&gt;&lt;/a&gt;, the executable that runs the Julia language.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JuliaPy/PyCall.jl&quot;&gt;&lt;strong&gt;PyCall,&lt;/strong&gt;&lt;/a&gt; the Julia package that defines the conversions between Julia and Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pyjulia.readthedocs.io/en/stable/&quot;&gt;&lt;strong&gt;PyJulia&lt;/strong&gt;&lt;/a&gt;, the Python package to access Julia from Python.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We are going to go through the installation and configuration of these steps on a Linux system. It will be very similar on MacOS or with &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/wsl/install&quot;&gt;WSL&lt;/a&gt; for Windows once the required tools are installed.&lt;/p&gt;
&lt;h3 id=&quot;step-1-python-with-shared-libpython&quot;&gt;Step 1: Python with shared libpython&lt;/h3&gt;
&lt;p&gt;To check whether the Python distribution is compiled with &lt;strong&gt;—enable-shared&lt;/strong&gt; option, we run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ldd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(which python3) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grep libpython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the output is something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libpython3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libpython3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x00007f567e548000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… then we are good to go! If we get nothing, that means that the Python distribution has not been compiled with the desired flags. In this case, we can compile our own Python distribution with the flag &lt;strong&gt;—enable-shared&lt;/strong&gt;, which takes some time but is mostly straightforward. This &lt;a href=&quot;https://github.com/abelsiqueira/python-and-julia/blob/debf6da21390c34331b708d8e93b97563ac83a78/Dockerfile#L22&quot;&gt;Dockerfile&lt;/a&gt; has the instructions. Remember that if you just want to test it out, you can run the Docker image as mentioned in the previous section.&lt;/p&gt;
&lt;h3 id=&quot;step-2-julia-and-pycall&quot;&gt;Step 2: Julia and PyCall&lt;/h3&gt;
&lt;p&gt;Now, we will install Julia. We recommend using &lt;a href=&quot;https://github.com/abelsiqueira/jill&quot;&gt;jill&lt;/a&gt;, a script I created, which downloads and installs a specific version of Julia, but Julia can also be installed via the official binaries or package managers. In this post, we use version 1.6.5, which is the current Long Term Support version at the time of writing. Most likely this will work with a newer version as well. To install Julia 1.6.5 using jill, we run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wget https&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;://&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;raw&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;githubusercontent&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;abelsiqueira&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sudo bash jill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sh &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we will install PyCall and configure it to use the correct Python version. We start Julia by running &lt;code&gt;julia&lt;/code&gt; in the terminal, and then we set the &lt;code&gt;ENV[&quot;PYTHON&quot;]&lt;/code&gt; variable:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; juliajulia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ENV&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;PYTHON&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;PATH/TO/python&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we use the full path to Python’s executable. In our case, it is the Python distribution we compiled from the source code. You could change the path according to your configuration.&lt;/p&gt;
&lt;p&gt;Now, we will install PyCall using Pkg, Julia’s package manager:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; using &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Pkgjulia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Pkg.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;add(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;PyCall&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-3-pyjulia&quot;&gt;Step 3: PyJulia&lt;/h3&gt;
&lt;p&gt;As the last step, we must install the Python package to talk with Julia. First, use pip, Python’s package manager, to install the package PyJulia — remember to use the same Python passed to &lt;code&gt;ENV[&quot;PYTHON&quot;]&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;–&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m pip install julia&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To finalize configuring the communication between Julia and Python, we run the following in the Python interpreter:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; python3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; import julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we had more than one Julia version on our system, we could specify it with an argument:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;install(julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;5&apos;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We test the installation running the following in the Python interpreter run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; from julia import &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Main.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;eval(&apos;[x&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&apos;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;showcasing-pyjulia&quot;&gt;Showcasing PyJulia&lt;/h2&gt;
&lt;h3 id=&quot;basics&quot;&gt;Basics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;To use a Julia module, use &lt;code&gt;from julia import MODULE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To evaluate a command, import &lt;code&gt;Main&lt;/code&gt; and use &lt;code&gt;Main.eval(&quot;...&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To create and use variables, use &lt;code&gt;Main.VARIABLE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To install Julia packages, &lt;code&gt;import Pkg&lt;/code&gt; and use &lt;code&gt;Pkg.add(&quot;Package&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;%load_ext julia.magic&lt;/code&gt; to add a &lt;a href=&quot;https://ipython.readthedocs.io/en/stable/interactive/magics.html&quot;&gt;IPython’s magic command&lt;/a&gt; called &lt;code&gt;%julia&lt;/code&gt;. Just prepend &lt;code&gt;%julia&lt;/code&gt; to Julia commands. In this case, use &lt;code&gt;$var&lt;/code&gt; to access python variables&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example-linear-algebra&quot;&gt;Example: Linear Algebra&lt;/h3&gt;
&lt;p&gt;In this short example, we can see one of the strengths of Julia syntax for Linear Algebra. A random linear system is created and solved. The result is checked with NumPy, so we can see the compatibility.&lt;/p&gt;
&lt;p&gt;We have chosen to define &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; in three different ways, to show the different syntaxes. The definition of &lt;strong&gt;A&lt;/strong&gt; occurs completely inside the eval block. The variable &lt;code&gt;A&lt;/code&gt; is created and is available inside the Julia scope, or as &lt;code&gt;Main.A&lt;/code&gt;. The definition of &lt;code&gt;b&lt;/code&gt; uses the &lt;code&gt;Main.b&lt;/code&gt; access directly and uses the result of &lt;code&gt;Main.eval&lt;/code&gt;. Finally, &lt;code&gt;%julia&lt;/code&gt; is the magic IPython command to simply use Julia syntax directly.&lt;/p&gt;
&lt;p&gt;We can quickly compare the timing of solving the system with Julia’s backslash command and Numpy’s &lt;code&gt;linalg.solve&lt;/code&gt;:&lt;/p&gt;
&lt;h3 id=&quot;example-automatic-differentiation&quot;&gt;Example: Automatic differentiation&lt;/h3&gt;
&lt;p&gt;The next example installs and uses the package called &lt;strong&gt;ForwardDiff&lt;/strong&gt;, which performs automatic differentiation. ForwardDiff defines a Julia type called &lt;strong&gt;Dual&lt;/strong&gt; internally, so we can’t use it with Python functions because Python functions are not compatible with that type. However, we can define Julia functions and use them.&lt;/p&gt;
&lt;p&gt;The local minimum of the quadratic occurs at 2.5, so the derivative at 2.5 is 0.0.&lt;/p&gt;
&lt;p&gt;Another, more interesting interaction is below, in which we create a function &lt;em&gt;g&lt;/em&gt; inside Julia, and define functions for its derivatives there. Then we create a Python function with the Taylor expansion around the value &lt;em&gt;a&lt;/em&gt;. Furthermore, we use Matplotlib, Python’s plotting library to visualize the results coming from Julia. Pretty neat, right?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;432&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PFodxQbLaofzbmaYRPzuZA-ba9a400c.Cy3ZWdRe_Z1eiLx4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image generated above, showing the function f and its third-order Taylor approximation.&lt;/p&gt;
&lt;h2 id=&quot;next-episodes&quot;&gt;Next episodes&lt;/h2&gt;
&lt;p&gt;Now that we can call Julia code in Python, we are prepared to move to our next adventure: improve the speed of a Python code by calling Julia from it. &lt;a href=&quot;https://blog.esciencecenter.nl/&quot;&gt;Follow our medium account&lt;/a&gt; to get notified when Part 2 goes live.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-elena-ranguelova/&quot;&gt;&lt;em&gt;Elena Ranguelova&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jason-maassen/&quot;&gt;Jason Maassen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;Jurrian Spaaks&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-rob-van-nieuwpoort/&quot;&gt;Rob van Nieuwpoort&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;, and &lt;a href=&quot;https://www.esciencecenter.nl/team/veronica-pang/&quot;&gt;Veronica Pang&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Wed, 19 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;a-three-part-series-on-achieving-high-performance-with-high-level-code&quot;&gt;A three-part series on achieving high performance with high-level code&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rO_VWgfXj4zuFDtX28Uc1g-c9e56d67.mmCamWYW_ZCAFTk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Caption: Astronaut carrying Python and Julia. Photo by Brian McGowan on Unsplash ( &lt;a href=&quot;https://unsplash.com/photos/MR9xsNWVKvo&quot;&gt;https://unsplash.com/photos/MR9xsNWVKvo&lt;/a&gt; ), modified by us.&lt;/p&gt;
&lt;h3 id=&quot;target-audience&quot;&gt;Target audience&lt;/h3&gt;
&lt;p&gt;This is the first post in a three-part series about achieving high performance with high-level code. This series is aimed at people working with Python who needs better performance but prefers not to develop a low-level performant library.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Having recently joined the Netherlands eScience Center after working with research using the Julia language for seven years, I was excited to highlight some of its cool features. At the eScience Center, many of our engineers use Python, some use C or C++, and in some cases, we see Python calling C++ code, to speed up the code. This was the perfect opportunity to introduce Julia’s interoperability with Python and to investigate whether we could achieve comparable speed by calling Julia code in Python. This means that for situations where Python’s performance is not sufficient, we can speed it up with another high-level language, avoiding the use of a low-level language like C++. This series of three blog posts will investigate these topics.&lt;/p&gt;
&lt;p&gt;In this first post, we will learn how to call a Julia code from Python. We will set up the environment and show some examples. In the second post, we will take a problem that was solved by using Python in combination with C++ to speed up the code. We will replace the C++ code with a Julia code and compare the performance. In the third post, we will solve the same problem in Julia, optimize the Julia code to reach its maximum performance and compare it with the implementation in the second post.&lt;/p&gt;
&lt;h2 id=&quot;what-is-julia-and-how-does-it-compare-to-python&quot;&gt;What is Julia, and how does it compare to Python?&lt;/h2&gt;
&lt;p&gt;What is Julia? Julia is a high-performance, high-level programming language. It was created a few years ago with the ambitious goal of being fast with a high-level syntax, and it has been mostly successful. It can, in a few cases, reach the speed of low-level programming languages like C. For more information, the &lt;a href=&quot;https://julialang.org/&quot;&gt;julialang.org&lt;/a&gt; site is a great first stop.&lt;/p&gt;
&lt;p&gt;One of the most frequently asked questions is: “how does it compare to Python or some other programming language in terms of performance?”. The short answer: Julia is &lt;a href=&quot;https://julialang.org/benchmarks&quot;&gt;generally faster&lt;/a&gt; than Python and many other programming languages.&lt;/p&gt;
&lt;p&gt;The performance of a Python code can be optimized, but even the optimized code usually underperforms compared to a Julia version of the same code. The performance increase of a Python code can be achieved in a few ways, but a frequent one is to call a code written in a low-level language, such as C, C++ and Fortran, like NumPy which does its calculations mostly in those low-level languages. What is less common, but also possible, is to call Julia from Python. In this post, we are going to show you how to do that!&lt;/p&gt;
&lt;p&gt;Before we forget, all the code used in this post can be found in our &lt;a href=&quot;https://github.com/abelsiqueira/faster-python-using-julia-blogposts&quot;&gt;GitHub repository&lt;/a&gt;. We have also created a &lt;a href=&quot;https://hub.docker.com/r/abelsiqueira/python-and-julia&quot;&gt;Docker image&lt;/a&gt; that includes a ready-to-use environment to run both Julia and Python. To run that environment with Python 3.10 and Julia 1.6, install Docker and run the following in your terminal:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; docker pull abelsiqueira&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jl1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; docker run &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;it exec abelsiqueira&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jl1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bin&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;preparation&quot;&gt;Preparation&lt;/h2&gt;
&lt;p&gt;In the following steps, we will configure our system to execute Julia code from Python. To learn more about this topic, the documentation for the packages we describe below is a great starting point. You will need four things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; distribution &lt;a href=&quot;https://docs.python.org/3/using/configure.html#cmdoption-enable-shared&quot;&gt;compiled with shared libpython&lt;/a&gt; option. There are workarounds, but this is the most straightforward way.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://julialang.org/&quot;&gt;&lt;strong&gt;Julia&lt;/strong&gt;&lt;/a&gt;, the executable that runs the Julia language.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/JuliaPy/PyCall.jl&quot;&gt;&lt;strong&gt;PyCall,&lt;/strong&gt;&lt;/a&gt; the Julia package that defines the conversions between Julia and Python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pyjulia.readthedocs.io/en/stable/&quot;&gt;&lt;strong&gt;PyJulia&lt;/strong&gt;&lt;/a&gt;, the Python package to access Julia from Python.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We are going to go through the installation and configuration of these steps on a Linux system. It will be very similar on MacOS or with &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/wsl/install&quot;&gt;WSL&lt;/a&gt; for Windows once the required tools are installed.&lt;/p&gt;
&lt;h3 id=&quot;step-1-python-with-shared-libpython&quot;&gt;Step 1: Python with shared libpython&lt;/h3&gt;
&lt;p&gt;To check whether the Python distribution is compiled with &lt;strong&gt;—enable-shared&lt;/strong&gt; option, we run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ldd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(which python3) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grep libpython&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the output is something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libpython3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;local&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libpython3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x00007f567e548000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… then we are good to go! If we get nothing, that means that the Python distribution has not been compiled with the desired flags. In this case, we can compile our own Python distribution with the flag &lt;strong&gt;—enable-shared&lt;/strong&gt;, which takes some time but is mostly straightforward. This &lt;a href=&quot;https://github.com/abelsiqueira/python-and-julia/blob/debf6da21390c34331b708d8e93b97563ac83a78/Dockerfile#L22&quot;&gt;Dockerfile&lt;/a&gt; has the instructions. Remember that if you just want to test it out, you can run the Docker image as mentioned in the previous section.&lt;/p&gt;
&lt;h3 id=&quot;step-2-julia-and-pycall&quot;&gt;Step 2: Julia and PyCall&lt;/h3&gt;
&lt;p&gt;Now, we will install Julia. We recommend using &lt;a href=&quot;https://github.com/abelsiqueira/jill&quot;&gt;jill&lt;/a&gt;, a script I created, which downloads and installs a specific version of Julia, but Julia can also be installed via the official binaries or package managers. In this post, we use version 1.6.5, which is the current Long Term Support version at the time of writing. Most likely this will work with a newer version as well. To install Julia 1.6.5 using jill, we run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; wget https&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;://&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;raw&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;githubusercontent&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;abelsiqueira&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4.0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sudo bash jill&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sh &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we will install PyCall and configure it to use the correct Python version. We start Julia by running &lt;code&gt;julia&lt;/code&gt; in the terminal, and then we set the &lt;code&gt;ENV[&quot;PYTHON&quot;]&lt;/code&gt; variable:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; juliajulia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; ENV&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;PYTHON&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;PATH/TO/python&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we use the full path to Python’s executable. In our case, it is the Python distribution we compiled from the source code. You could change the path according to your configuration.&lt;/p&gt;
&lt;p&gt;Now, we will install PyCall using Pkg, Julia’s package manager:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; using &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Pkgjulia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Pkg.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;add(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;PyCall&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-3-pyjulia&quot;&gt;Step 3: PyJulia&lt;/h3&gt;
&lt;p&gt;As the last step, we must install the Python package to talk with Julia. First, use pip, Python’s package manager, to install the package PyJulia — remember to use the same Python passed to &lt;code&gt;ENV[&quot;PYTHON&quot;]&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;–&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m pip install julia&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To finalize configuring the communication between Julia and Python, we run the following in the Python interpreter:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; python3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; import julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we had more than one Julia version on our system, we could specify it with an argument:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;install(julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;julia&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;5&apos;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We test the installation running the following in the Python interpreter run:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; from julia import &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; Main.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;eval(&apos;[x&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&apos;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;showcasing-pyjulia&quot;&gt;Showcasing PyJulia&lt;/h2&gt;
&lt;h3 id=&quot;basics&quot;&gt;Basics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;To use a Julia module, use &lt;code&gt;from julia import MODULE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To evaluate a command, import &lt;code&gt;Main&lt;/code&gt; and use &lt;code&gt;Main.eval(&quot;...&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To create and use variables, use &lt;code&gt;Main.VARIABLE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;To install Julia packages, &lt;code&gt;import Pkg&lt;/code&gt; and use &lt;code&gt;Pkg.add(&quot;Package&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;%load_ext julia.magic&lt;/code&gt; to add a &lt;a href=&quot;https://ipython.readthedocs.io/en/stable/interactive/magics.html&quot;&gt;IPython’s magic command&lt;/a&gt; called &lt;code&gt;%julia&lt;/code&gt;. Just prepend &lt;code&gt;%julia&lt;/code&gt; to Julia commands. In this case, use &lt;code&gt;$var&lt;/code&gt; to access python variables&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;example-linear-algebra&quot;&gt;Example: Linear Algebra&lt;/h3&gt;
&lt;p&gt;In this short example, we can see one of the strengths of Julia syntax for Linear Algebra. A random linear system is created and solved. The result is checked with NumPy, so we can see the compatibility.&lt;/p&gt;
&lt;p&gt;We have chosen to define &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; in three different ways, to show the different syntaxes. The definition of &lt;strong&gt;A&lt;/strong&gt; occurs completely inside the eval block. The variable &lt;code&gt;A&lt;/code&gt; is created and is available inside the Julia scope, or as &lt;code&gt;Main.A&lt;/code&gt;. The definition of &lt;code&gt;b&lt;/code&gt; uses the &lt;code&gt;Main.b&lt;/code&gt; access directly and uses the result of &lt;code&gt;Main.eval&lt;/code&gt;. Finally, &lt;code&gt;%julia&lt;/code&gt; is the magic IPython command to simply use Julia syntax directly.&lt;/p&gt;
&lt;p&gt;We can quickly compare the timing of solving the system with Julia’s backslash command and Numpy’s &lt;code&gt;linalg.solve&lt;/code&gt;:&lt;/p&gt;
&lt;h3 id=&quot;example-automatic-differentiation&quot;&gt;Example: Automatic differentiation&lt;/h3&gt;
&lt;p&gt;The next example installs and uses the package called &lt;strong&gt;ForwardDiff&lt;/strong&gt;, which performs automatic differentiation. ForwardDiff defines a Julia type called &lt;strong&gt;Dual&lt;/strong&gt; internally, so we can’t use it with Python functions because Python functions are not compatible with that type. However, we can define Julia functions and use them.&lt;/p&gt;
&lt;p&gt;The local minimum of the quadratic occurs at 2.5, so the derivative at 2.5 is 0.0.&lt;/p&gt;
&lt;p&gt;Another, more interesting interaction is below, in which we create a function &lt;em&gt;g&lt;/em&gt; inside Julia, and define functions for its derivatives there. Then we create a Python function with the Taylor expansion around the value &lt;em&gt;a&lt;/em&gt;. Furthermore, we use Matplotlib, Python’s plotting library to visualize the results coming from Julia. Pretty neat, right?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;720&quot; height=&quot;432&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PFodxQbLaofzbmaYRPzuZA-ba9a400c.Cy3ZWdRe_Z1eiLx4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image generated above, showing the function f and its third-order Taylor approximation.&lt;/p&gt;
&lt;h2 id=&quot;next-episodes&quot;&gt;Next episodes&lt;/h2&gt;
&lt;p&gt;Now that we can call Julia code in Python, we are prepared to move to our next adventure: improve the speed of a Python code by calling Julia from it. &lt;a href=&quot;https://blog.esciencecenter.nl/&quot;&gt;Follow our medium account&lt;/a&gt; to get notified when Part 2 goes live.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to our proofreaders and reviewers,&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-elena-ranguelova/&quot;&gt;&lt;em&gt;Elena Ranguelova&lt;/em&gt;&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jason-maassen/&quot;&gt;Jason Maassen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;Jurrian Spaaks&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/prof-dr-rob-van-nieuwpoort/&quot;&gt;Rob van Nieuwpoort&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;, and &lt;a href=&quot;https://www.esciencecenter.nl/team/veronica-pang/&quot;&gt;Veronica Pang&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_PFodxQbLaofzbmaYRPzuZA-ba9a400c.Cy3ZWdRe.png" medium="image"/><author>Abel Soares Siqueira</author></item><item><title>What is in the eScience toolbox: Stef on his favourite meshing library</title><link>https://blog2.esciencecenter.nl/posts/2022-01-05---what-is-in-the-escience-toolbox-stef-on-his-favourite-meshin</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2022-01-05---what-is-in-the-escience-toolbox-stef-on-his-favourite-meshin</guid><description>&lt;p&gt;&lt;em&gt;Question: Hi Stef, for this blog series we are looking to highlight our developer’s favourite libraries.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: As research software engineers we always get excited by tools that exactly fit the job that we need it for. For this &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; library I’m developing, I was looking for a 2D triangle &lt;a href=&quot;https://en.wikipedia.org/wiki/Mesh_generation&quot;&gt;mesh generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Wait.. wait… Meshes?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Meshes simplify image data and describe complex geometries. A mesh is essentially a collection of vertices and triangles. They are used for computer graphics and physical simulations, such as finite element analyses and fluid dynamics.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Like in computer games?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Exactly!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: I have heard&lt;/em&gt; &lt;a href=&quot;https://www.cgal.org/&quot;&gt;&lt;em&gt;CGAL&lt;/em&gt;&lt;/a&gt; &lt;em&gt;is the go-to library for Meshing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: CGAL is an excellent choice. It’s written in C++, and provides easy access to efficient and reliable geometric algorithms. Unfortunately, for my purpose, CGAL is a bit heavy-weight, difficult to install on Windows, and lacks an intuitive Python interface.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: So what did you end up using?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: After having tried a few more meshing libraries, I came across &lt;a href=&quot;https://www.cs.cmu.edu/~quake/triangle.html&quot;&gt;Triangle&lt;/a&gt;. Triangle is an open-source two-dimensional quality mesh generator that supports multiple domains. It’s written in C++ and supports all three major operating systems. It’s lightweight and there is a well-documented &lt;a href=&quot;https://rufat.be/triangle/API.html&quot;&gt;Python API available&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Cool, so how do you install it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: It’s available on &lt;a href=&quot;https://pypi.org/project/triangle/&quot;&gt;pypi&lt;/a&gt;. If you are already using Python, just do the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip install triangle&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: That’s great! That will make it easy to integrate it into my existing project. How do you use it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Let me give you an example. Here is the code to generate a simple square and triangulate it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; matplotlib.pyplot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pltimport numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; npimport triangle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vertices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]])inp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&apos;vertices&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vertices}out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;triangulate(inp, opts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;qa0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;05&apos;)tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compare(plt, inp, out)plt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;505&quot; height=&quot;255&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KwRJMoxH9912dHdBlhYa5Q-edc53a20.BwrlUnLS_2fKkpk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Triangle makes it easy to display the results.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: So I see Triangle filling the box with little triangles. How does that work?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Alright, let me break it down for you.&lt;/p&gt;
&lt;p&gt;First, we import &lt;code&gt;matplotlib&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt; and &lt;code&gt;triangle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Second, we generate the vertices representing a square with edges of length l and store them in a dictionary.&lt;/p&gt;
&lt;p&gt;Next, we call triangulate. The options &lt;code&gt;opts=qa0.05&lt;/code&gt; tell triangle to perform a quality mesh (&lt;code&gt;q&lt;/code&gt;), and that no triangles have an area larger than 0.05 (&lt;code&gt;a0.05&lt;/code&gt;). A quality mesh is a mesh with all angles over 30 degrees.&lt;/p&gt;
&lt;p&gt;Finally, triangle has a useful function to compare the input and the output.&lt;/p&gt;
&lt;p&gt;Try playing around with the area to see what happens to the result!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: That’s great! For finite element analysis, wouldn’t it be useful to specify different regions?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Yes, that is one of the strengths of &lt;code&gt;triangle&lt;/code&gt;. It makes multi-region meshing easy. This means that it can label triangles according to the region it belongs to.&lt;/p&gt;
&lt;p&gt;Let me give you an example:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vertices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]])segments &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]])regions &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.25&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.25&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.75&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.75&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])inp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &apos;vertices&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vertices, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &apos;segments&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; segments, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &apos;regions&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; regions,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;triangulate(inp, opts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;pqa0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;05&apos;)tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compare(plt, inp, out)plt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;506&quot; height=&quot;254&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_j7JqSTDcmkZDdA-1u2QEoA-0bb45cd8.8mmJb3Lq_Z9zwKX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Same input, now divided in two regions.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Can you explain how it works?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: The difference here is that we specify the different segments. The segments describe the boundaries of a region inside the square. Triangles will be generated for each region independently. Each region thus contains its own set of triangles, and are labeled accordingly.&lt;/p&gt;
&lt;p&gt;The format for defining &lt;code&gt;regions&lt;/code&gt; can seem a bit tricky at first. For each row, e.g. &lt;code&gt;[0.75, 0.75, 1, 0]&lt;/code&gt;, the first two numbers describe the coordinate, and the third number is the label of the region. The final number can be used to set the maximum area in that region. We don’t use that here, so we set it to &lt;code&gt;0&lt;/code&gt;. As before, use the compare function to check the result. And that’s it!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Wow, I want to start using this now! Where can I learn more?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: I’m really happy to hear that! If you want to know more, the documentation and examples for triangle are available &lt;a href=&quot;https://rufat.be/triangle/API.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We use &lt;code&gt;triangle&lt;/code&gt; as the triangle mesh generator in one of our &lt;a href=&quot;https://www.esciencecenter.nl/projects/computation-of-the-optical-properties-of-nano-structures/&quot;&gt;projects&lt;/a&gt;. The code we using it in, &lt;code&gt;nanomesh&lt;/code&gt;, is a Python workflow tool to prepare meshes for finite element analysis from 2D (and 3D!) microscopy image data.&lt;/p&gt;</description><pubDate>Wed, 05 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Question: Hi Stef, for this blog series we are looking to highlight our developer’s favourite libraries.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: As research software engineers we always get excited by tools that exactly fit the job that we need it for. For this &lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt; library I’m developing, I was looking for a 2D triangle &lt;a href=&quot;https://en.wikipedia.org/wiki/Mesh_generation&quot;&gt;mesh generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Wait.. wait… Meshes?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Meshes simplify image data and describe complex geometries. A mesh is essentially a collection of vertices and triangles. They are used for computer graphics and physical simulations, such as finite element analyses and fluid dynamics.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Like in computer games?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Exactly!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: I have heard&lt;/em&gt; &lt;a href=&quot;https://www.cgal.org/&quot;&gt;&lt;em&gt;CGAL&lt;/em&gt;&lt;/a&gt; &lt;em&gt;is the go-to library for Meshing.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: CGAL is an excellent choice. It’s written in C++, and provides easy access to efficient and reliable geometric algorithms. Unfortunately, for my purpose, CGAL is a bit heavy-weight, difficult to install on Windows, and lacks an intuitive Python interface.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: So what did you end up using?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: After having tried a few more meshing libraries, I came across &lt;a href=&quot;https://www.cs.cmu.edu/~quake/triangle.html&quot;&gt;Triangle&lt;/a&gt;. Triangle is an open-source two-dimensional quality mesh generator that supports multiple domains. It’s written in C++ and supports all three major operating systems. It’s lightweight and there is a well-documented &lt;a href=&quot;https://rufat.be/triangle/API.html&quot;&gt;Python API available&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Cool, so how do you install it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: It’s available on &lt;a href=&quot;https://pypi.org/project/triangle/&quot;&gt;pypi&lt;/a&gt;. If you are already using Python, just do the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip install triangle&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: That’s great! That will make it easy to integrate it into my existing project. How do you use it?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Let me give you an example. Here is the code to generate a simple square and triangulate it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; matplotlib.pyplot &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pltimport numpy &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; npimport triangle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vertices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]])inp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&apos;vertices&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vertices}out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;triangulate(inp, opts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;qa0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;05&apos;)tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compare(plt, inp, out)plt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;505&quot; height=&quot;255&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KwRJMoxH9912dHdBlhYa5Q-edc53a20.BwrlUnLS_2fKkpk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Triangle makes it easy to display the results.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: So I see Triangle filling the box with little triangles. How does that work?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Alright, let me break it down for you.&lt;/p&gt;
&lt;p&gt;First, we import &lt;code&gt;matplotlib&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt; and &lt;code&gt;triangle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Second, we generate the vertices representing a square with edges of length l and store them in a dictionary.&lt;/p&gt;
&lt;p&gt;Next, we call triangulate. The options &lt;code&gt;opts=qa0.05&lt;/code&gt; tell triangle to perform a quality mesh (&lt;code&gt;q&lt;/code&gt;), and that no triangles have an area larger than 0.05 (&lt;code&gt;a0.05&lt;/code&gt;). A quality mesh is a mesh with all angles over 30 degrees.&lt;/p&gt;
&lt;p&gt;Finally, triangle has a useful function to compare the input and the output.&lt;/p&gt;
&lt;p&gt;Try playing around with the area to see what happens to the result!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: That’s great! For finite element analysis, wouldn’t it be useful to specify different regions?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: Yes, that is one of the strengths of &lt;code&gt;triangle&lt;/code&gt;. It makes multi-region meshing easy. This means that it can label triangles according to the region it belongs to.&lt;/p&gt;
&lt;p&gt;Let me give you an example:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vertices &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]])segments &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]])regions &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; np&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.25&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.25&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.75&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.75&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])inp &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &apos;vertices&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; vertices, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &apos;segments&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; segments, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &apos;regions&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; regions,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}out &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;triangulate(inp, opts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;pqa0&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;05&apos;)tr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compare(plt, inp, out)plt&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;506&quot; height=&quot;254&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_j7JqSTDcmkZDdA-1u2QEoA-0bb45cd8.8mmJb3Lq_Z9zwKX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Same input, now divided in two regions.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Can you explain how it works?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: The difference here is that we specify the different segments. The segments describe the boundaries of a region inside the square. Triangles will be generated for each region independently. Each region thus contains its own set of triangles, and are labeled accordingly.&lt;/p&gt;
&lt;p&gt;The format for defining &lt;code&gt;regions&lt;/code&gt; can seem a bit tricky at first. For each row, e.g. &lt;code&gt;[0.75, 0.75, 1, 0]&lt;/code&gt;, the first two numbers describe the coordinate, and the third number is the label of the region. The final number can be used to set the maximum area in that region. We don’t use that here, so we set it to &lt;code&gt;0&lt;/code&gt;. As before, use the compare function to check the result. And that’s it!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Question: Wow, I want to start using this now! Where can I learn more?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Stef: I’m really happy to hear that! If you want to know more, the documentation and examples for triangle are available &lt;a href=&quot;https://rufat.be/triangle/API.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We use &lt;code&gt;triangle&lt;/code&gt; as the triangle mesh generator in one of our &lt;a href=&quot;https://www.esciencecenter.nl/projects/computation-of-the-optical-properties-of-nano-structures/&quot;&gt;projects&lt;/a&gt;. The code we using it in, &lt;code&gt;nanomesh&lt;/code&gt;, is a Python workflow tool to prepare meshes for finite element analysis from 2D (and 3D!) microscopy image data.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_KwRJMoxH9912dHdBlhYa5Q-edc53a20.BwrlUnLS.png" medium="image"/><author>Stef Smeets</author></item><item><title>Still coding texts by hand for social science text analysis? Use Doccano instead to speed up the process!</title><link>https://blog2.esciencecenter.nl/posts/2021-12-21---still-coding-texts-by-hand-for-social-science-text-analysis-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-12-21---still-coding-texts-by-hand-for-social-science-text-analysis-</guid><description>&lt;p&gt;][Sven van der Burg]·Dec 21, 2021&lt;/p&gt;
&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coder-centered: **It is designed to make the coder’s life as easy as possible. You view one text at a time at the center of your screen. All you have to do is this: select a piece of text with your pointer, and click or hit a shortkey to add a label (for example: `concept 1’). When the complete text is coded, just click next. It’s as simple as that.&lt;/li&gt;
&lt;li&gt;**No more errors in data entry: **As a data analyst, you don’t need to worry about how exactly a coder enters the data as you would, for example, when data is coded in an Excel sheet. Doccano enforces that any data entry results in nicely formatted data. You can download the data without any data entry errors.&lt;/li&gt;
&lt;li&gt;**Open-source: **The programming code for Doccano is open for everyone to see and edit (under sensible restrictions, of course). This makes it free to use and easy to setup yourself in any scenario. In addition, if you want to add a new feature, you can always add it yourself or request it in the community. Yay for open-source software!&lt;/li&gt;
&lt;li&gt;**Collaborative coding: **Doccano allows different coders to code the same text, which is very useful if you want to get reliable labels.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-does-doccano-compare-to-nvivo-or-maxqda&quot;&gt;How does Doccano compare to NVivo or MAXQDA?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.qsrinternational.com/nvivo-qualitative-data-analysis-software/home&quot;&gt;NVivo&lt;/a&gt; and &lt;a href=&quot;https://www.maxqda.com/&quot;&gt;Maxqda&lt;/a&gt; also allow you to select sections of documents, but they are only useful for thematic analysis using extensive coding trees. Both are paid packages, whereas Doccano is completely free and easier to work with. Doccano is easily combined with other analysis frameworks like SPSS, Excel, R, or Python, whereas NVivo and MAXQDA want you to do your complete analysis within their program.&lt;/p&gt;
&lt;h2 id=&quot;how-does-doccano-compare-to-amcat&quot;&gt;How does Doccano compare to Amcat?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://wiki.amcat.nl/3.4:AmCAT_Navigator_3&quot;&gt;AmCAT&lt;/a&gt; also allows token-level and sentence-level coding (see &lt;a href=&quot;http://wiki.amcat.nl/3.3:Annotator&quot;&gt;their documentation&lt;/a&gt;). But it’s certainly not as coder-centered as Doccano. In addition, it is much more complex compared to Doccano’s simple interface.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;We hope that we’ve convinced you that using Doccano can be a simple improvement in text analysis pipelines. So, what’s next?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Try out the &lt;a href=&quot;http://doccano.herokuapp.com/demo/named-entity-recognition&quot;&gt;Doccano demo&lt;/a&gt; to get a feel for how it works.&lt;/li&gt;
&lt;li&gt;Because of it’s open source nature, you have to run Doccano in a cloud environment yourself. Fortunately, you can do this without any technical knowledge. Just follow the first part of &lt;a href=&quot;https://lingudocs.mcasado.org/posts/20210103_Tagging-a-linguistic-corpus-for-free/&quot;&gt;this excellent guide&lt;/a&gt; to setup Doccano on Heroku (ignore the prerequisites, you don’t need them). You will have your own free Doccano environment within 15 minutes.&lt;/li&gt;
&lt;li&gt;Follow the further instructions in &lt;a href=&quot;https://lingudocs.mcasado.org/posts/20210103_Tagging-a-linguistic-corpus-for-free/&quot;&gt;that guide&lt;/a&gt; to add a dataset and tags within Doccano to kickstart your first coding project! NB: Double check whether you are allowed to upload your data to Heroku, maybe there are privacy or security concerns. If there are concerns you could discuss installing Doccano on your institution’s own infrastructure.&lt;/li&gt;
&lt;li&gt;You can download your coded data as .jsonl file. This file can be opened with notepad or transferred to .csv &lt;a href=&quot;https://www.convertcsv.com/json-to-csv.htm&quot;&gt;online&lt;/a&gt;. The coded sections in the Doccano output can easily be transformed back from ‘token position’ into text via the text function ‘mid’ in Excel if you are not familiar with programming.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Tue, 21 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;][Sven van der Burg]·Dec 21, 2021&lt;/p&gt;
&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Coder-centered: **It is designed to make the coder’s life as easy as possible. You view one text at a time at the center of your screen. All you have to do is this: select a piece of text with your pointer, and click or hit a shortkey to add a label (for example: `concept 1’). When the complete text is coded, just click next. It’s as simple as that.&lt;/li&gt;
&lt;li&gt;**No more errors in data entry: **As a data analyst, you don’t need to worry about how exactly a coder enters the data as you would, for example, when data is coded in an Excel sheet. Doccano enforces that any data entry results in nicely formatted data. You can download the data without any data entry errors.&lt;/li&gt;
&lt;li&gt;**Open-source: **The programming code for Doccano is open for everyone to see and edit (under sensible restrictions, of course). This makes it free to use and easy to setup yourself in any scenario. In addition, if you want to add a new feature, you can always add it yourself or request it in the community. Yay for open-source software!&lt;/li&gt;
&lt;li&gt;**Collaborative coding: **Doccano allows different coders to code the same text, which is very useful if you want to get reliable labels.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-does-doccano-compare-to-nvivo-or-maxqda&quot;&gt;How does Doccano compare to NVivo or MAXQDA?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.qsrinternational.com/nvivo-qualitative-data-analysis-software/home&quot;&gt;NVivo&lt;/a&gt; and &lt;a href=&quot;https://www.maxqda.com/&quot;&gt;Maxqda&lt;/a&gt; also allow you to select sections of documents, but they are only useful for thematic analysis using extensive coding trees. Both are paid packages, whereas Doccano is completely free and easier to work with. Doccano is easily combined with other analysis frameworks like SPSS, Excel, R, or Python, whereas NVivo and MAXQDA want you to do your complete analysis within their program.&lt;/p&gt;
&lt;h2 id=&quot;how-does-doccano-compare-to-amcat&quot;&gt;How does Doccano compare to Amcat?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://wiki.amcat.nl/3.4:AmCAT_Navigator_3&quot;&gt;AmCAT&lt;/a&gt; also allows token-level and sentence-level coding (see &lt;a href=&quot;http://wiki.amcat.nl/3.3:Annotator&quot;&gt;their documentation&lt;/a&gt;). But it’s certainly not as coder-centered as Doccano. In addition, it is much more complex compared to Doccano’s simple interface.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;
&lt;p&gt;We hope that we’ve convinced you that using Doccano can be a simple improvement in text analysis pipelines. So, what’s next?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Try out the &lt;a href=&quot;http://doccano.herokuapp.com/demo/named-entity-recognition&quot;&gt;Doccano demo&lt;/a&gt; to get a feel for how it works.&lt;/li&gt;
&lt;li&gt;Because of it’s open source nature, you have to run Doccano in a cloud environment yourself. Fortunately, you can do this without any technical knowledge. Just follow the first part of &lt;a href=&quot;https://lingudocs.mcasado.org/posts/20210103_Tagging-a-linguistic-corpus-for-free/&quot;&gt;this excellent guide&lt;/a&gt; to setup Doccano on Heroku (ignore the prerequisites, you don’t need them). You will have your own free Doccano environment within 15 minutes.&lt;/li&gt;
&lt;li&gt;Follow the further instructions in &lt;a href=&quot;https://lingudocs.mcasado.org/posts/20210103_Tagging-a-linguistic-corpus-for-free/&quot;&gt;that guide&lt;/a&gt; to add a dataset and tags within Doccano to kickstart your first coding project! NB: Double check whether you are allowed to upload your data to Heroku, maybe there are privacy or security concerns. If there are concerns you could discuss installing Doccano on your institution’s own infrastructure.&lt;/li&gt;
&lt;li&gt;You can download your coded data as .jsonl file. This file can be opened with notepad or transferred to .csv &lt;a href=&quot;https://www.convertcsv.com/json-to-csv.htm&quot;&gt;online&lt;/a&gt;. The coded sections in the Doccano output can easily be transformed back from ‘token position’ into text via the text function ‘mid’ in Excel if you are not familiar with programming.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>Sven van der Burg</author></item><item><title>The new IPCC assessment report: stakes have been raised</title><link>https://blog2.esciencecenter.nl/posts/2021-12-14---the-new-ipcc-assessment-report-stakes-have-been-raised</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-12-14---the-new-ipcc-assessment-report-stakes-have-been-raised</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.primavera-h2020.eu/&quot;&gt;PRIMAVERA&lt;/a&gt;, a Horizon 2020 project, we focused upon the I/O machinery in a big European climate model &lt;a href=&quot;http://www.ec-earth.org/about/&quot;&gt;EC-Earth&lt;/a&gt;. In particular, we were asked to come up with a solution to make this model produce those CMIP6 standardized output quantities, preferably without slashing the performance of the simulation workflow. The answer: we leveraged parallel Python to crunch through the high-resolution raw climate data of EC-Earth and apply the necessary formulas and conversions; the &lt;a href=&quot;https://github.com/EC-Earth/ece2cmor3&quot;&gt;ece2cmor3&lt;/a&gt; tool that does this has been adopted by the community as the method of choice to post-process this model output, and has since then been used to produce petabytes of climate model data for AR6.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The new IPCC assessment report: stakes have been raised&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;389&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-new-ipcc-assessment-report-stakes-ha-64226777.CsBCGuG7_ZYqN3R.webp&quot; srcset=&quot;&quot;&gt;
Emerging lakes at the termini of receding glaciers in the Bhutan-Himalaya in 2002 (source: NASA)Leaving the data production side of the equation, we enter the analysis aspect of the research: you see, 200 years of simulated global humidity fields on, say, 27 atmospheric pressure levels doesn’t quite answer questions of fellow researchers or policy makers by itself. These data serve as input to tools and applications that reduce them to relevant information for society and the scientific community. The problem is that ‘tools and applications’ often translate into an unsustainable mess of ad-hoc scripts. These get stitched together as a sequence of undocumented commands along the lines of “./proc.sh work/out.nc work/out2.nc”. Now when a colleague asks three months later to “recreate that figure for some other climate model”, a panicky feeling takes over, soon to be followed with regret over the lack of design and documentation, ending in frustration over the fact that those beloved tools appear to have stopped functioning after the previous OS update. And to be frank, analyzing climate data is just becoming too costly in terms of time, RAM, disk space and network bandwidth to just do freewheeling on a PC.&lt;/p&gt;
&lt;p&gt;This also has been recognized by the climate community, and data analysis frameworks have been steadily gaining momentum. You may know &lt;a href=&quot;https://pangeo.io/index.html&quot;&gt;Pangeo&lt;/a&gt;, the &lt;a href=&quot;https://cds.climate.copernicus.eu/#!/home&quot;&gt;Copernicus Data Store&lt;/a&gt;, the &lt;a href=&quot;https://climexp.knmi.nl&quot;&gt;KNMI Climate Explorer&lt;/a&gt;, or the &lt;a href=&quot;https://www.esmvaltool.org/&quot;&gt;ESMValTool&lt;/a&gt; suite, which was used for several charts and tables into create several figures in AR6. ESMValTool stands for Earth System Model Validation Tool, but it can do a lot more than that; it ensures one uses standardized algorithms, containerized tools and transparent provenance during the process of extracting useful information from the massive amount of data coming from observations and models. It makes it easy to create &lt;a href=&quot;https://www.rd-alliance.org/group/fair-research-software-fair4rs-wg/outcomes/fair-principles-research-software-fair4rs&quot;&gt;Findable, Accessible, Interoperable, and Reproducible&lt;/a&gt; (FAIR) analysis software for climate data. Within the &lt;a href=&quot;https://www.esciencecenter.nl/projects/is-enes3/&quot;&gt;IS-ENES3&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/news/c3s-magic-developing-software-for-data-from-climate-models/&quot;&gt;C3S-MAGIC&lt;/a&gt; projects, we have made many contributions to ESMValTool, and we have greatly benefited from its capabilities in the &lt;a href=&quot;https://www.esciencecenter.nl/projects/ewatercycle-ii/&quot;&gt;eWaterCycle2&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/projects/european-climate-prediction-system/&quot;&gt;EUCP&lt;/a&gt; projects.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The new IPCC assessment report: stakes have been raised&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;463&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-new-ipcc-assessment-report-stakes-ha-ac0837cb.UuCigevE_1Jti88.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@karsten_wuerth&quot;&gt;Karsten Würth&lt;/a&gt; at &lt;a href=&quot;https://unsplash.com&quot;&gt;unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally, we get to the aspect of disseminating the AR6 message to a broad audience. When you navigate to the IPCC web page to look at the AR6 conclusions yourself, you may quickly find yourself lost in the scientific jargon and formal language. AR6 is targeted at researchers and policy makers, but its implications are so far-reaching that it should be addressing our society as a whole. The aim of the H2020 project &lt;a href=&quot;https://climatestorylines.eu/&quot;&gt;RECEIPT&lt;/a&gt; is to assess Europe’s vulnerability to climate risks and represent these risks in the form of storylines. Sometimes it’s not feasible to perform a full statistical analysis of climate impacts on a complex system. Or even so, it may be that stakeholders are more interested in a few representative (or extreme) datapoints to assess their vulnerability, and that is where storylines enter the picture. By showing the chain of events caused by warming climate and intensifying extreme weather, we hope to better convey potential agricultural, socio-economic and infrastructural hazards. Here, the eScience Center plays a leading role in visualizing these storylines in an interactive &lt;a href=&quot;https://www.climateimpactstories.eu/?sector=agriculture&amp;#x26;story=1&quot;&gt;web-based environment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are just a handful of examples of where the eScience Center has in some way contributed to AR6. We have been involved in many more projects in climate and weather, detecting the &lt;a href=&quot;https://www.research-software.nl/projects/1349&quot;&gt;occurrence of climate tipping points&lt;/a&gt;, improving the predictability of climate in Europe (EUCP) and the Northern Atlantic (&lt;a href=&quot;https://blue-action.eu/&quot;&gt;Blue Action&lt;/a&gt;), or estimating the likelihood and severity of &lt;a href=&quot;https://climate.copernicus.eu/prototype-extreme-events-and-attribution-service&quot;&gt;extreme heat and flooding events&lt;/a&gt;. The common ingredient connecting these research projects is always climate change. While our opponent in the ring is gaining strength, we use science and computing to improve our ability to predict his moves and better brace for impact of the punches. The global effort to reduce emissions will be crucial to limit those impacts and hopefully prolong the battle until a jury decision, to be made by future generations.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/bouwe-andela-msc/&quot;&gt;&lt;em&gt;Bouwe Andela&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-maaike-de-jong/&quot;&gt;&lt;em&gt;Maaike de Jong&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/jesus-garcia-gonzalez-msc/&quot;&gt;&lt;em&gt;Jesus Garcia Gonzalez&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and *&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-yifat-dzigan/&quot;&gt;&lt;em&gt;Yifat Dzigan&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 14 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.primavera-h2020.eu/&quot;&gt;PRIMAVERA&lt;/a&gt;, a Horizon 2020 project, we focused upon the I/O machinery in a big European climate model &lt;a href=&quot;http://www.ec-earth.org/about/&quot;&gt;EC-Earth&lt;/a&gt;. In particular, we were asked to come up with a solution to make this model produce those CMIP6 standardized output quantities, preferably without slashing the performance of the simulation workflow. The answer: we leveraged parallel Python to crunch through the high-resolution raw climate data of EC-Earth and apply the necessary formulas and conversions; the &lt;a href=&quot;https://github.com/EC-Earth/ece2cmor3&quot;&gt;ece2cmor3&lt;/a&gt; tool that does this has been adopted by the community as the method of choice to post-process this model output, and has since then been used to produce petabytes of climate model data for AR6.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The new IPCC assessment report: stakes have been raised&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;389&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-new-ipcc-assessment-report-stakes-ha-64226777.CsBCGuG7_ZYqN3R.webp&quot; srcset=&quot;&quot;&gt;
Emerging lakes at the termini of receding glaciers in the Bhutan-Himalaya in 2002 (source: NASA)Leaving the data production side of the equation, we enter the analysis aspect of the research: you see, 200 years of simulated global humidity fields on, say, 27 atmospheric pressure levels doesn’t quite answer questions of fellow researchers or policy makers by itself. These data serve as input to tools and applications that reduce them to relevant information for society and the scientific community. The problem is that ‘tools and applications’ often translate into an unsustainable mess of ad-hoc scripts. These get stitched together as a sequence of undocumented commands along the lines of “./proc.sh work/out.nc work/out2.nc”. Now when a colleague asks three months later to “recreate that figure for some other climate model”, a panicky feeling takes over, soon to be followed with regret over the lack of design and documentation, ending in frustration over the fact that those beloved tools appear to have stopped functioning after the previous OS update. And to be frank, analyzing climate data is just becoming too costly in terms of time, RAM, disk space and network bandwidth to just do freewheeling on a PC.&lt;/p&gt;
&lt;p&gt;This also has been recognized by the climate community, and data analysis frameworks have been steadily gaining momentum. You may know &lt;a href=&quot;https://pangeo.io/index.html&quot;&gt;Pangeo&lt;/a&gt;, the &lt;a href=&quot;https://cds.climate.copernicus.eu/#!/home&quot;&gt;Copernicus Data Store&lt;/a&gt;, the &lt;a href=&quot;https://climexp.knmi.nl&quot;&gt;KNMI Climate Explorer&lt;/a&gt;, or the &lt;a href=&quot;https://www.esmvaltool.org/&quot;&gt;ESMValTool&lt;/a&gt; suite, which was used for several charts and tables into create several figures in AR6. ESMValTool stands for Earth System Model Validation Tool, but it can do a lot more than that; it ensures one uses standardized algorithms, containerized tools and transparent provenance during the process of extracting useful information from the massive amount of data coming from observations and models. It makes it easy to create &lt;a href=&quot;https://www.rd-alliance.org/group/fair-research-software-fair4rs-wg/outcomes/fair-principles-research-software-fair4rs&quot;&gt;Findable, Accessible, Interoperable, and Reproducible&lt;/a&gt; (FAIR) analysis software for climate data. Within the &lt;a href=&quot;https://www.esciencecenter.nl/projects/is-enes3/&quot;&gt;IS-ENES3&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/news/c3s-magic-developing-software-for-data-from-climate-models/&quot;&gt;C3S-MAGIC&lt;/a&gt; projects, we have made many contributions to ESMValTool, and we have greatly benefited from its capabilities in the &lt;a href=&quot;https://www.esciencecenter.nl/projects/ewatercycle-ii/&quot;&gt;eWaterCycle2&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/projects/european-climate-prediction-system/&quot;&gt;EUCP&lt;/a&gt; projects.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;The new IPCC assessment report: stakes have been raised&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;463&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/the-new-ipcc-assessment-report-stakes-ha-ac0837cb.UuCigevE_1Jti88.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@karsten_wuerth&quot;&gt;Karsten Würth&lt;/a&gt; at &lt;a href=&quot;https://unsplash.com&quot;&gt;unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally, we get to the aspect of disseminating the AR6 message to a broad audience. When you navigate to the IPCC web page to look at the AR6 conclusions yourself, you may quickly find yourself lost in the scientific jargon and formal language. AR6 is targeted at researchers and policy makers, but its implications are so far-reaching that it should be addressing our society as a whole. The aim of the H2020 project &lt;a href=&quot;https://climatestorylines.eu/&quot;&gt;RECEIPT&lt;/a&gt; is to assess Europe’s vulnerability to climate risks and represent these risks in the form of storylines. Sometimes it’s not feasible to perform a full statistical analysis of climate impacts on a complex system. Or even so, it may be that stakeholders are more interested in a few representative (or extreme) datapoints to assess their vulnerability, and that is where storylines enter the picture. By showing the chain of events caused by warming climate and intensifying extreme weather, we hope to better convey potential agricultural, socio-economic and infrastructural hazards. Here, the eScience Center plays a leading role in visualizing these storylines in an interactive &lt;a href=&quot;https://www.climateimpactstories.eu/?sector=agriculture&amp;#x26;story=1&quot;&gt;web-based environment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are just a handful of examples of where the eScience Center has in some way contributed to AR6. We have been involved in many more projects in climate and weather, detecting the &lt;a href=&quot;https://www.research-software.nl/projects/1349&quot;&gt;occurrence of climate tipping points&lt;/a&gt;, improving the predictability of climate in Europe (EUCP) and the Northern Atlantic (&lt;a href=&quot;https://blue-action.eu/&quot;&gt;Blue Action&lt;/a&gt;), or estimating the likelihood and severity of &lt;a href=&quot;https://climate.copernicus.eu/prototype-extreme-events-and-attribution-service&quot;&gt;extreme heat and flooding events&lt;/a&gt;. The common ingredient connecting these research projects is always climate change. While our opponent in the ring is gaining strength, we use science and computing to improve our ability to predict his moves and better brace for impact of the punches. The global effort to reduce emissions will be crucial to limit those impacts and hopefully prolong the battle until a jury decision, to be made by future generations.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/bouwe-andela-msc/&quot;&gt;&lt;em&gt;Bouwe Andela&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-maaike-de-jong/&quot;&gt;&lt;em&gt;Maaike de Jong&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/team/jesus-garcia-gonzalez-msc/&quot;&gt;&lt;em&gt;Jesus Garcia Gonzalez&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; and *&lt;a href=&quot;https://www.esciencecenter.nl/team/dr-yifat-dzigan/&quot;&gt;&lt;em&gt;Yifat Dzigan&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/the-new-ipcc-assessment-report-stakes-ha-64226777.CsBCGuG7.jpeg" medium="image"/><author>Gijs van den Oord</author></item><item><title>cffinit: NOW is the time to get more recognition for your software!</title><link>https://blog2.esciencecenter.nl/posts/2021-12-03---cffinit-now-is-the-time-to-get-more-recognition-for-your-sof</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-12-03---cffinit-now-is-the-time-to-get-more-recognition-for-your-sof</guid><description>&lt;p&gt;***Creating software citation files using cffinit&lt;br&gt;
***by &lt;a href=&quot;https://orcid.org/0000-0003-4451-281X&quot;&gt;Abel S. Siqueira&lt;/a&gt; and &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;Faruk Diblen&lt;/a&gt; (&lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image of cinema with many people watching a screen. Instead of a film, the screen shows the recognition image from Scriberia.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VMyjOtrq1IOnHncO-1e5ef4de.CVjb6NdK_Z6jzNu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modified photo of a cinema by Jake Hills on Unsplash &lt;a href=&quot;https://unsplash.com/photos/23LET4Hxj%5C_U&quot;&gt;https://unsplash.com/photos/23LET4Hxj\_U&lt;/a&gt;, and the image created by Scriberia for The Turing Way community and is used under a CC-BY licence. &lt;a href=&quot;https://doi.org/10.5281/zenodo.5706310&quot;&gt;https://doi.org/10.5281/zenodo.5706310&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let’s think about your favorite movie. What is so good about it? The story? The animations? Sound effects? Maybe you only like the actor or actress? There must be something special about the movie that makes you feel different.&lt;/p&gt;
&lt;p&gt;We move on to our next question: do you know of those involved in making your favourite movie? You may know the director and the main actor or actress, but what about the others? For example, do you know the artist who composed the soundtracks? Do you know the person who spent endless hours editing the movie? What about costume and make-up? We often refer to movies as &lt;em&gt;‘the movie director X directed’&lt;/em&gt; or &lt;em&gt;‘the movie with Y in it’&lt;/em&gt;. Although a lot of people work in movie production, only a few people get credit and share the fame. But what would happen if the most striking scene wouldn’t have a soundtrack or visual effects?&lt;/p&gt;
&lt;p&gt;We have a similar story to modern research. In many research fields today, doing research without software is impossible. Researchers find an interesting problem, they devote their time to finding the answer and they rarely actually do it alone. Most of the time, they collaborate with many other people. For example, researchers need software that can make smart decisions (like an AI algorithm) or process a huge amount of data in a very efficient way. Finally, they get their research article published and are announced as the owner of the work. &lt;em&gt;But wait!&lt;/em&gt; What happened to the people who developed the software? Are they included in the paper? Did they receive credit for the software they developed? In the best scenario, the software developers spent time creating a software paper and published it in a specialized journal. If there is no publication about the software, the developers don’t usually receive credit or are only added to the acknowledgement section.&lt;/p&gt;
&lt;h2 id=&quot;citation-file-format&quot;&gt;Citation File Format&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Recognition image from Scriberia. A banner with Recognition written on it appears above software developers and researchers standing on pillars. Software citation helps developers pillar to go to higher level, represented by an arrow.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1120&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_SCmONGUG4gHQkhqA-42229c69.Di2jUtWU_kiueY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image was created by Scriberia for The Turing Way community and is used under a CC-BY licence. &lt;a href=&quot;https://doi.org/10.5281/zenodo.5706310&quot;&gt;https://doi.org/10.5281/zenodo.5706310&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was a big issue until a few research software developers, from the Netherlands eScience Center and the German Aerospace Center (DLR) introduced the idea of &lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;Citation File Format&lt;/a&gt; [1]. The Citation File Format helps you add machine-readable metadata for software or datasets. After adoption by GitHub, Zenodo, GitLab, Zotero, and JabRef, we believe it will be a standard format in the near future. You can read more about the story &lt;a href=&quot;https://www.esciencecenter.nl/news/code-citation-was-made-possible-by-research-software-engineers-in-germany-and-the-netherlands/&quot;&gt;here&lt;/a&gt;. Thanks to &lt;a href=&quot;https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files&quot;&gt;GitHub’s recent feature&lt;/a&gt;, if you have a CITATION.cff in your GitHub repository, your software can be cited correctly and easily. &lt;strong&gt;Yaaay for recognition!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;cffinit-a-tool-to-generate-citationcff-files&quot;&gt;cffinit: a tool to generate CITATION.cff files&lt;/h2&gt;
&lt;p&gt;To support the growing adoption of the Citation File Format, &lt;strong&gt;there is now a dedicated tool to create these files from scratch&lt;/strong&gt;: &lt;a href=&quot;https://research-software.nl/software/cffinit&quot;&gt;cffinit&lt;/a&gt; [2]. cffinit is a web application that helps you create a CITATION.cff file. The application provides guidance for each field of the CFF schema and does the validation automatically. When there are issues, cffinit will provide visual feedback on relevant fields. The cffinit has a few advantages compared to manual editing such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no need for installing extra tools such as conversion and validation tools;&lt;/li&gt;
&lt;li&gt;no need for further validation;&lt;/li&gt;
&lt;li&gt;guidance for each field;&lt;/li&gt;
&lt;li&gt;visual feedback to indicate issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recently, the Netherlands eScience Center has released version 2.0.0 of the tool. This version handles the most up-to-date Citation File Format specification (1.2.0), and can help you easily create your CITATION.cff file.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A cat looks at a computer screen where the landing page of cffinit is shown.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_J2ZZyZSLxMFGZQGR-0312c8a3.DfvPnZ5S_Z1urK9d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modified photo of Tim Mossholder on Unsplash &lt;a href=&quot;https://unsplash.com/photos/gdsp6wNn7cM&quot;&gt;https://unsplash.com/photos/gdsp6wNn7cM&lt;/a&gt;, with landing the page of cffinit v2.0.0&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center also took part in The Turing Way November 2021 sprint and created a section about &lt;a href=&quot;https://the-turing-way.netlify.app/communication/citable/citable-cff.html&quot;&gt;software citation with CITATION.cff&lt;/a&gt; with an overview of all this information. In addition, we have created a tutorial on how to &lt;a href=&quot;https://the-turing-way.netlify.app/communication/citable/citable-cffinit.html&quot;&gt;create a CITATION.cff using cffinit&lt;/a&gt; to help you get your software to the next level of recognition. Instead of copy-pasting all of it here, we summarize a few of the points in The Turing Way and recommend that you follow the tutorial.&lt;/p&gt;
&lt;h2 id=&quot;steps-to-make-your-software-citable-with-cffinit&quot;&gt;Steps to Make Your Software Citable with cffinit&lt;/h2&gt;
&lt;p&gt;To make your software citable, you only need to follow the two steps below:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1. Create a CITATION.cff File:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Use &lt;a href=&quot;https://citation-file-format.github.io/cff-initializer-javascript/#/&quot;&gt;cffinit&lt;/a&gt; to create a CITATION.cff file. For more details on using cffinit see &lt;a href=&quot;https://the-turing-way.netlify.app/communication/citable/citable-cffinit.html&quot;&gt;the tutorial on The Turing Way’s website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2. Add Your CITATION.cff to a Public Code Repository:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After creating a valid CITATION.cff file, you will need to add it to the root of your code or data repository so that it can be easily found and cited.&lt;/p&gt;
&lt;h2 id=&quot;updating-your-citationcff-file&quot;&gt;Updating your CITATION.cff file&lt;/h2&gt;
&lt;p&gt;When you need to update your CITATION.cff file, for example, to add an author or to change the information about releases, you will need to edit the file manually. It is recommended to update your CITATION.cff file before making a software release.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Spoiler: we are working on adding this feature to cffinit.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-to-cite-using-citationcff&quot;&gt;How to Cite Using CITATION.cff&lt;/h2&gt;
&lt;p&gt;If you have found software or datasets that contain a CITATION.cff, there are a few ways to obtain the reference information to cite in your publication.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can use one of the tools, such as the &lt;a href=&quot;https://github.com/citation-file-format/cff-converter-python&quot;&gt;cffconvert&lt;/a&gt; command-line program, to convert your CITATION.cff file to one of the &lt;a href=&quot;https://github.com/citation-file-format/cff-converter-python#supported-output-formats&quot;&gt;supported formats&lt;/a&gt;, such as APA, BibTeX or EndNote.&lt;/li&gt;
&lt;li&gt;Alternatively, if the software or datasets you want to cite are available on GitHub, you can use GitHub’s interface to copy the reference in either APA or BibTeX formats by clicking the “Cite this repository” button. See the green area in the image below for an example.
&lt;img alt=&quot;GitHub repository with “Cite this repository” button clicked and popup showing the formatted citation information.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1199&quot; height=&quot;793&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Mt6W7VkzjkCLICvz-118ee885.6MdF7Upf_Z1B4YUv.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“Cite this repository” automatically converts the CITATION.cff file to APA’s and BibTeX’s format.&lt;/p&gt;
&lt;p&gt;Note that the “Cite this repository” button only appears when there is a CITATION.cff file in the repository.&lt;/p&gt;
&lt;p&gt;For more details on software citation on GitHub, please see &lt;a href=&quot;https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files&quot;&gt;GitHub’s guide on software citation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;[1] Druskat, S., Spaaks, J. H., Chue Hong, N., Haines, R., Baker, J., Bliven, S., Willighagen, E., Pérez-Suárez, D., &amp;#x26; Konovalov, A. (2021). Citation File Format (Version 1.2.0) [Computer software]. &lt;a href=&quot;https://doi.org/10.5281/zenodo.5171937&quot;&gt;https://doi.org/10.5281/zenodo.5171937&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2] Spaaks, J. H., Verhoeven, S., Diblen, F., Druskat, S., Soares Siqueira, A., &amp;#x26; Garcia Gonzalez, J. (2021). cffinit (Version 2.0.0) [Computer software]. &lt;a href=&quot;https://github.com/citation-file-format/cff-initializer-javascript&quot;&gt;https://github.com/citation-file-format/cff-initializer-javascript&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-can-you-help&quot;&gt;How can you help?&lt;/h2&gt;
&lt;p&gt;You can help us in many ways. The first and easiest would be creating a CITATION.cff file for your software. If you encounter any issues or if you have suggestions, you can create tickets on our &lt;a href=&quot;https://github.com/citation-file-format/cff-initializer-javascript&quot;&gt;GitHub repository&lt;/a&gt;. Finally, you can contribute to the code and help us make it even better.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;cffinit 2.0 was developed by &lt;a href=&quot;https://www.esciencecenter.nl/team/abel-soares-siqueira/&quot;&gt;Abel S. Siqueira&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/faruk-diblen-msc/&quot;&gt;Faruk Diblen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/jesus-garcia-gonzalez-msc/&quot;&gt;Jesus Garcia González&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;Jurriaan H. Spaaks&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;. We thank &lt;a href=&quot;https://sdruskat.net/&quot;&gt;Stephan Druskat&lt;/a&gt; for the very useful feedback during the development of the tool and also our proofreaders &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/veronica-pang/&quot;&gt;Veronica Pang&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;Tom Bakker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have suggestions or questions, please feel free to reach us at generalization a-t esciencecenter.nl.&lt;/p&gt;</description><pubDate>Fri, 03 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;***Creating software citation files using cffinit&lt;br&gt;
***by &lt;a href=&quot;https://orcid.org/0000-0003-4451-281X&quot;&gt;Abel S. Siqueira&lt;/a&gt; and &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;Faruk Diblen&lt;/a&gt; (&lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image of cinema with many people watching a screen. Instead of a film, the screen shows the recognition image from Scriberia.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VMyjOtrq1IOnHncO-1e5ef4de.CVjb6NdK_Z6jzNu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modified photo of a cinema by Jake Hills on Unsplash &lt;a href=&quot;https://unsplash.com/photos/23LET4Hxj%5C_U&quot;&gt;https://unsplash.com/photos/23LET4Hxj\_U&lt;/a&gt;, and the image created by Scriberia for The Turing Way community and is used under a CC-BY licence. &lt;a href=&quot;https://doi.org/10.5281/zenodo.5706310&quot;&gt;https://doi.org/10.5281/zenodo.5706310&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Let’s think about your favorite movie. What is so good about it? The story? The animations? Sound effects? Maybe you only like the actor or actress? There must be something special about the movie that makes you feel different.&lt;/p&gt;
&lt;p&gt;We move on to our next question: do you know of those involved in making your favourite movie? You may know the director and the main actor or actress, but what about the others? For example, do you know the artist who composed the soundtracks? Do you know the person who spent endless hours editing the movie? What about costume and make-up? We often refer to movies as &lt;em&gt;‘the movie director X directed’&lt;/em&gt; or &lt;em&gt;‘the movie with Y in it’&lt;/em&gt;. Although a lot of people work in movie production, only a few people get credit and share the fame. But what would happen if the most striking scene wouldn’t have a soundtrack or visual effects?&lt;/p&gt;
&lt;p&gt;We have a similar story to modern research. In many research fields today, doing research without software is impossible. Researchers find an interesting problem, they devote their time to finding the answer and they rarely actually do it alone. Most of the time, they collaborate with many other people. For example, researchers need software that can make smart decisions (like an AI algorithm) or process a huge amount of data in a very efficient way. Finally, they get their research article published and are announced as the owner of the work. &lt;em&gt;But wait!&lt;/em&gt; What happened to the people who developed the software? Are they included in the paper? Did they receive credit for the software they developed? In the best scenario, the software developers spent time creating a software paper and published it in a specialized journal. If there is no publication about the software, the developers don’t usually receive credit or are only added to the acknowledgement section.&lt;/p&gt;
&lt;h2 id=&quot;citation-file-format&quot;&gt;Citation File Format&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Recognition image from Scriberia. A banner with Recognition written on it appears above software developers and researchers standing on pillars. Software citation helps developers pillar to go to higher level, represented by an arrow.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1120&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_SCmONGUG4gHQkhqA-42229c69.Di2jUtWU_kiueY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image was created by Scriberia for The Turing Way community and is used under a CC-BY licence. &lt;a href=&quot;https://doi.org/10.5281/zenodo.5706310&quot;&gt;https://doi.org/10.5281/zenodo.5706310&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was a big issue until a few research software developers, from the Netherlands eScience Center and the German Aerospace Center (DLR) introduced the idea of &lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;Citation File Format&lt;/a&gt; [1]. The Citation File Format helps you add machine-readable metadata for software or datasets. After adoption by GitHub, Zenodo, GitLab, Zotero, and JabRef, we believe it will be a standard format in the near future. You can read more about the story &lt;a href=&quot;https://www.esciencecenter.nl/news/code-citation-was-made-possible-by-research-software-engineers-in-germany-and-the-netherlands/&quot;&gt;here&lt;/a&gt;. Thanks to &lt;a href=&quot;https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files&quot;&gt;GitHub’s recent feature&lt;/a&gt;, if you have a CITATION.cff in your GitHub repository, your software can be cited correctly and easily. &lt;strong&gt;Yaaay for recognition!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;cffinit-a-tool-to-generate-citationcff-files&quot;&gt;cffinit: a tool to generate CITATION.cff files&lt;/h2&gt;
&lt;p&gt;To support the growing adoption of the Citation File Format, &lt;strong&gt;there is now a dedicated tool to create these files from scratch&lt;/strong&gt;: &lt;a href=&quot;https://research-software.nl/software/cffinit&quot;&gt;cffinit&lt;/a&gt; [2]. cffinit is a web application that helps you create a CITATION.cff file. The application provides guidance for each field of the CFF schema and does the validation automatically. When there are issues, cffinit will provide visual feedback on relevant fields. The cffinit has a few advantages compared to manual editing such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no need for installing extra tools such as conversion and validation tools;&lt;/li&gt;
&lt;li&gt;no need for further validation;&lt;/li&gt;
&lt;li&gt;guidance for each field;&lt;/li&gt;
&lt;li&gt;visual feedback to indicate issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recently, the Netherlands eScience Center has released version 2.0.0 of the tool. This version handles the most up-to-date Citation File Format specification (1.2.0), and can help you easily create your CITATION.cff file.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A cat looks at a computer screen where the landing page of cffinit is shown.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_J2ZZyZSLxMFGZQGR-0312c8a3.DfvPnZ5S_Z1urK9d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modified photo of Tim Mossholder on Unsplash &lt;a href=&quot;https://unsplash.com/photos/gdsp6wNn7cM&quot;&gt;https://unsplash.com/photos/gdsp6wNn7cM&lt;/a&gt;, with landing the page of cffinit v2.0.0&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center also took part in The Turing Way November 2021 sprint and created a section about &lt;a href=&quot;https://the-turing-way.netlify.app/communication/citable/citable-cff.html&quot;&gt;software citation with CITATION.cff&lt;/a&gt; with an overview of all this information. In addition, we have created a tutorial on how to &lt;a href=&quot;https://the-turing-way.netlify.app/communication/citable/citable-cffinit.html&quot;&gt;create a CITATION.cff using cffinit&lt;/a&gt; to help you get your software to the next level of recognition. Instead of copy-pasting all of it here, we summarize a few of the points in The Turing Way and recommend that you follow the tutorial.&lt;/p&gt;
&lt;h2 id=&quot;steps-to-make-your-software-citable-with-cffinit&quot;&gt;Steps to Make Your Software Citable with cffinit&lt;/h2&gt;
&lt;p&gt;To make your software citable, you only need to follow the two steps below:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1. Create a CITATION.cff File:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Use &lt;a href=&quot;https://citation-file-format.github.io/cff-initializer-javascript/#/&quot;&gt;cffinit&lt;/a&gt; to create a CITATION.cff file. For more details on using cffinit see &lt;a href=&quot;https://the-turing-way.netlify.app/communication/citable/citable-cffinit.html&quot;&gt;the tutorial on The Turing Way’s website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2. Add Your CITATION.cff to a Public Code Repository:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After creating a valid CITATION.cff file, you will need to add it to the root of your code or data repository so that it can be easily found and cited.&lt;/p&gt;
&lt;h2 id=&quot;updating-your-citationcff-file&quot;&gt;Updating your CITATION.cff file&lt;/h2&gt;
&lt;p&gt;When you need to update your CITATION.cff file, for example, to add an author or to change the information about releases, you will need to edit the file manually. It is recommended to update your CITATION.cff file before making a software release.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Spoiler: we are working on adding this feature to cffinit.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-to-cite-using-citationcff&quot;&gt;How to Cite Using CITATION.cff&lt;/h2&gt;
&lt;p&gt;If you have found software or datasets that contain a CITATION.cff, there are a few ways to obtain the reference information to cite in your publication.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can use one of the tools, such as the &lt;a href=&quot;https://github.com/citation-file-format/cff-converter-python&quot;&gt;cffconvert&lt;/a&gt; command-line program, to convert your CITATION.cff file to one of the &lt;a href=&quot;https://github.com/citation-file-format/cff-converter-python#supported-output-formats&quot;&gt;supported formats&lt;/a&gt;, such as APA, BibTeX or EndNote.&lt;/li&gt;
&lt;li&gt;Alternatively, if the software or datasets you want to cite are available on GitHub, you can use GitHub’s interface to copy the reference in either APA or BibTeX formats by clicking the “Cite this repository” button. See the green area in the image below for an example.
&lt;img alt=&quot;GitHub repository with “Cite this repository” button clicked and popup showing the formatted citation information.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1199&quot; height=&quot;793&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Mt6W7VkzjkCLICvz-118ee885.6MdF7Upf_Z1B4YUv.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“Cite this repository” automatically converts the CITATION.cff file to APA’s and BibTeX’s format.&lt;/p&gt;
&lt;p&gt;Note that the “Cite this repository” button only appears when there is a CITATION.cff file in the repository.&lt;/p&gt;
&lt;p&gt;For more details on software citation on GitHub, please see &lt;a href=&quot;https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files&quot;&gt;GitHub’s guide on software citation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;p&gt;[1] Druskat, S., Spaaks, J. H., Chue Hong, N., Haines, R., Baker, J., Bliven, S., Willighagen, E., Pérez-Suárez, D., &amp;#x26; Konovalov, A. (2021). Citation File Format (Version 1.2.0) [Computer software]. &lt;a href=&quot;https://doi.org/10.5281/zenodo.5171937&quot;&gt;https://doi.org/10.5281/zenodo.5171937&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[2] Spaaks, J. H., Verhoeven, S., Diblen, F., Druskat, S., Soares Siqueira, A., &amp;#x26; Garcia Gonzalez, J. (2021). cffinit (Version 2.0.0) [Computer software]. &lt;a href=&quot;https://github.com/citation-file-format/cff-initializer-javascript&quot;&gt;https://github.com/citation-file-format/cff-initializer-javascript&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-can-you-help&quot;&gt;How can you help?&lt;/h2&gt;
&lt;p&gt;You can help us in many ways. The first and easiest would be creating a CITATION.cff file for your software. If you encounter any issues or if you have suggestions, you can create tickets on our &lt;a href=&quot;https://github.com/citation-file-format/cff-initializer-javascript&quot;&gt;GitHub repository&lt;/a&gt;. Finally, you can contribute to the code and help us make it even better.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;cffinit 2.0 was developed by &lt;a href=&quot;https://www.esciencecenter.nl/team/abel-soares-siqueira/&quot;&gt;Abel S. Siqueira&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/faruk-diblen-msc/&quot;&gt;Faruk Diblen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/jesus-garcia-gonzalez-msc/&quot;&gt;Jesus Garcia González&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/jurriaan-spaaks-msc/&quot;&gt;Jurriaan H. Spaaks&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;. We thank &lt;a href=&quot;https://sdruskat.net/&quot;&gt;Stephan Druskat&lt;/a&gt; for the very useful feedback during the development of the tool and also our proofreaders &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-lieke-de-boer/&quot;&gt;Lieke de Boer&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/veronica-pang/&quot;&gt;Veronica Pang&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-tom-bakker/&quot;&gt;Tom Bakker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have suggestions or questions, please feel free to reach us at generalization a-t esciencecenter.nl.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_SCmONGUG4gHQkhqA-42229c69.Di2jUtWU.webp" medium="image"/><author>Faruk Diblen</author></item><item><title>Kernel Tuner tutorial at Supercomputing 2021</title><link>https://blog2.esciencecenter.nl/posts/2021-11-25---kernel-tuner-tutorial-at-supercomputing-2021</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-11-25---kernel-tuner-tutorial-at-supercomputing-2021</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3975&quot; height=&quot;2682&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_msfW7zq3-awfNStVOT-xBQ-893acb07.CWKlucGy_1CWQ3h.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A view of St. Louis from the Gateway Arch. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;November 2021 — Together with my colleagues, Alessio Sclocco, Stijn Heldens, and Floris-Jan Willemsen, we travelled to the latest edition of the &lt;a href=&quot;https://sc21.supercomputing.org/&quot;&gt;Supercomputing conference&lt;/a&gt;, SC21, in St. Louis, USA, to give a tutorial.&lt;/p&gt;
&lt;p&gt;The goal of the tutorial was to teach Supercomputing attendees how to use &lt;a href=&quot;https://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt;, a tool that is being developed at the Netherlands eScience Center to assist in the development of highly-optimized applications for Graphics Processing Units (or GPUs). These GPUs form the primary source of compute power in many of today’s supercomputers. However, optimizing applications to run efficiently on GPUs can be challenging, and that’s where Kernel Tuner comes into play.&lt;/p&gt;
&lt;p&gt;The tutorial was divided into four sections, each consisting of a short presentation followed by a hands-on session, in which the attendees get to practice using the tool on some of the example codes that we provided.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1344&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ModR0KTUHXWxS-IlCs0f_A-4f639c67.DDZWFrXV_21nUu7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Ben van Werkhoven presenting at the Kernel Tuner tutorial at SC21. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;The first session explained the problem that Kernel Tuner is aiming to solve, namely the problem that creating GPU applications with optimal performance is a bit like trying to find a needle in a haystack. This is because the developer has a great number of choices to make when creating a GPU application. These choices won’t affect the outcome of the program, but they can have a dramatic impact on the time it takes to perform the computations. All implementation choices combined create a huge program design space of potential implementations that all compute the same thing, but in different ways. Using several examples, I explained that while using auto-tuning to optimize GPU applications may be a complex process, it can also be really rewarding when you find those few configurations that outperform all others by a large margin.&lt;/p&gt;
&lt;p&gt;For the hands-on sessions, we made use of &lt;a href=&quot;https://colab.research.google.com/?utm_source=scs-index&quot;&gt;Google Colab&lt;/a&gt;, which allows anyone with a Google account to run Jupyter notebooks on Google’s cloud services. There are several providers of similar services, but the great thing about Colab is that you can get a virtual machine with a GPU, which is exactly what we need to get started with tuning GPU kernels. Colab turned out to be a great choice for the tutorial, because it can be accessed from a browser without the need for participants to install any software locally, nor do they have to be able to access their own GPU server from the conference network. Because Kernel Tuner is a Python-based tool, the participants could use it right away inside the Jupyter notebook environment and get started on the exercises.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1048&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IPaVLwyMntpH4XpMhNToRw-4da126f0.BF6MRdho_FYNCg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Alessio Sclocco wrapping up the first hands-on session of the tutorial. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;During the hands-on sessions, the attendees read about the exercises in the notebook at hand and attempt to solve small example problems. All four of us, including Stijn and Floris-Jan, were busy with answering questions from the attendees regarding the hands-on exercises.&lt;/p&gt;
&lt;p&gt;The second session focused on how to start using Kernel Tuner to optimize existing GPU functions, or kernels, and how to correctly supply Kernel Tuner with the set of possible values for application parameters such as the number of threads per block and the number of thread blocks. Alessio introduced the concept of user-defined metrics that allow the user to instruct Kernel Tuner to calculate certain metrics that are relevant for the application, while it is being benchmarked on the GPU.&lt;/p&gt;
&lt;p&gt;The third and fourth sessions introduced more complex concepts and features of the tool, including how to verify the output of all program variants during tuning and how to integrate auto-tuned GPU kernels into larger applications.&lt;/p&gt;
&lt;p&gt;The response from the audience was really great. The room was as full as the COVID-19 measures would allow. The conference organizers even had to arrange for extra tables to allow all attendees to actively participate. During the lectures and hands-on sessions, we received many in-depth questions about the inner workings of Kernel Tuner and GPU code optimization techniques. We are very grateful for the opportunity to present our work at the Supercomputing conference and we look forward to organizing more tutorials on Kernel Tuner in the coming years.&lt;/p&gt;
&lt;p&gt;The rest of the week, we enjoyed the Supercomputing conference where Floris-Jan Willemsen also presented his paper titled “Bayesian Optimization for auto-tuning GPU kernels” at the &lt;a href=&quot;https://www.dcs.warwick.ac.uk/pmbs/pmbs/PMBS/Welcome.html&quot;&gt;Performance Modeling, Benchmarking and Simulation of High Performance Computer Systems (PMBS)&lt;/a&gt; workshop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;961&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GVZ3jeEm-_QWClVazkrQ2g-684ffc76.DsIEuK6q_Z1VG2Gw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A view of St. Louis and the Gateway Arch from across the Mississippi river. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;In case this blogpost has made you curious about the Kernel Tuner tutorial, we have some great news for you since all the tutorial materials, including the notebooks for the hands-on sessions, &lt;a href=&quot;https://github.com/benvanwerkhoven/kernel_tuner_tutorial&quot;&gt;are freely available online here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To find out more about Kernel Tuner, please see the &lt;a href=&quot;https://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Funding acknowledgements: The Kernel Tuner tutorial has been made possible by the CORTEX and ESiWACE2 projects. The CORTEX project has received funding from the Dutch Research Council (NWO) in the framework of the NWA-ORC Call (file number NWA.1160.18.316). ESiWACE2 has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No 823988.&lt;/p&gt;</description><pubDate>Thu, 25 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3975&quot; height=&quot;2682&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_msfW7zq3-awfNStVOT-xBQ-893acb07.CWKlucGy_1CWQ3h.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A view of St. Louis from the Gateway Arch. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;November 2021 — Together with my colleagues, Alessio Sclocco, Stijn Heldens, and Floris-Jan Willemsen, we travelled to the latest edition of the &lt;a href=&quot;https://sc21.supercomputing.org/&quot;&gt;Supercomputing conference&lt;/a&gt;, SC21, in St. Louis, USA, to give a tutorial.&lt;/p&gt;
&lt;p&gt;The goal of the tutorial was to teach Supercomputing attendees how to use &lt;a href=&quot;https://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt;, a tool that is being developed at the Netherlands eScience Center to assist in the development of highly-optimized applications for Graphics Processing Units (or GPUs). These GPUs form the primary source of compute power in many of today’s supercomputers. However, optimizing applications to run efficiently on GPUs can be challenging, and that’s where Kernel Tuner comes into play.&lt;/p&gt;
&lt;p&gt;The tutorial was divided into four sections, each consisting of a short presentation followed by a hands-on session, in which the attendees get to practice using the tool on some of the example codes that we provided.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1344&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ModR0KTUHXWxS-IlCs0f_A-4f639c67.DDZWFrXV_21nUu7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Ben van Werkhoven presenting at the Kernel Tuner tutorial at SC21. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;The first session explained the problem that Kernel Tuner is aiming to solve, namely the problem that creating GPU applications with optimal performance is a bit like trying to find a needle in a haystack. This is because the developer has a great number of choices to make when creating a GPU application. These choices won’t affect the outcome of the program, but they can have a dramatic impact on the time it takes to perform the computations. All implementation choices combined create a huge program design space of potential implementations that all compute the same thing, but in different ways. Using several examples, I explained that while using auto-tuning to optimize GPU applications may be a complex process, it can also be really rewarding when you find those few configurations that outperform all others by a large margin.&lt;/p&gt;
&lt;p&gt;For the hands-on sessions, we made use of &lt;a href=&quot;https://colab.research.google.com/?utm_source=scs-index&quot;&gt;Google Colab&lt;/a&gt;, which allows anyone with a Google account to run Jupyter notebooks on Google’s cloud services. There are several providers of similar services, but the great thing about Colab is that you can get a virtual machine with a GPU, which is exactly what we need to get started with tuning GPU kernels. Colab turned out to be a great choice for the tutorial, because it can be accessed from a browser without the need for participants to install any software locally, nor do they have to be able to access their own GPU server from the conference network. Because Kernel Tuner is a Python-based tool, the participants could use it right away inside the Jupyter notebook environment and get started on the exercises.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1048&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IPaVLwyMntpH4XpMhNToRw-4da126f0.BF6MRdho_FYNCg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Alessio Sclocco wrapping up the first hands-on session of the tutorial. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;During the hands-on sessions, the attendees read about the exercises in the notebook at hand and attempt to solve small example problems. All four of us, including Stijn and Floris-Jan, were busy with answering questions from the attendees regarding the hands-on exercises.&lt;/p&gt;
&lt;p&gt;The second session focused on how to start using Kernel Tuner to optimize existing GPU functions, or kernels, and how to correctly supply Kernel Tuner with the set of possible values for application parameters such as the number of threads per block and the number of thread blocks. Alessio introduced the concept of user-defined metrics that allow the user to instruct Kernel Tuner to calculate certain metrics that are relevant for the application, while it is being benchmarked on the GPU.&lt;/p&gt;
&lt;p&gt;The third and fourth sessions introduced more complex concepts and features of the tool, including how to verify the output of all program variants during tuning and how to integrate auto-tuned GPU kernels into larger applications.&lt;/p&gt;
&lt;p&gt;The response from the audience was really great. The room was as full as the COVID-19 measures would allow. The conference organizers even had to arrange for extra tables to allow all attendees to actively participate. During the lectures and hands-on sessions, we received many in-depth questions about the inner workings of Kernel Tuner and GPU code optimization techniques. We are very grateful for the opportunity to present our work at the Supercomputing conference and we look forward to organizing more tutorials on Kernel Tuner in the coming years.&lt;/p&gt;
&lt;p&gt;The rest of the week, we enjoyed the Supercomputing conference where Floris-Jan Willemsen also presented his paper titled “Bayesian Optimization for auto-tuning GPU kernels” at the &lt;a href=&quot;https://www.dcs.warwick.ac.uk/pmbs/pmbs/PMBS/Welcome.html&quot;&gt;Performance Modeling, Benchmarking and Simulation of High Performance Computer Systems (PMBS)&lt;/a&gt; workshop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;961&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GVZ3jeEm-_QWClVazkrQ2g-684ffc76.DsIEuK6q_Z1VG2Gw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A view of St. Louis and the Gateway Arch from across the Mississippi river. Photo by Floris-Jan Willemsen.&lt;/p&gt;
&lt;p&gt;In case this blogpost has made you curious about the Kernel Tuner tutorial, we have some great news for you since all the tutorial materials, including the notebooks for the hands-on sessions, &lt;a href=&quot;https://github.com/benvanwerkhoven/kernel_tuner_tutorial&quot;&gt;are freely available online here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To find out more about Kernel Tuner, please see the &lt;a href=&quot;https://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Funding acknowledgements: The Kernel Tuner tutorial has been made possible by the CORTEX and ESiWACE2 projects. The CORTEX project has received funding from the Dutch Research Council (NWO) in the framework of the NWA-ORC Call (file number NWA.1160.18.316). ESiWACE2 has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No 823988.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_ModR0KTUHXWxS-IlCs0f_A-4f639c67.DDZWFrXV.jpeg" medium="image"/><author>Ben van Werkhoven</author></item><item><title>Combining ZeroMQ &amp;amp; POSIX signals</title><link>https://blog2.esciencecenter.nl/posts/2021-11-16---combining-zeromq-amp-posix-signals</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-11-16---combining-zeromq-amp-posix-signals</guid><description>&lt;h2 id=&quot;use-ppoll-to-handle-eintr-once-and-for-all&quot;&gt;Use ppoll to handle EINTR once and for all&lt;/h2&gt;
&lt;p&gt;Eventually, I found &lt;a href=&quot;http://250bpm.com/blog:12&quot;&gt;this article on EINTR in ZeroMQ&lt;/a&gt; by Martin Sustrik (ZeroMQ creator) himself. More precisely, in the comment section &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1608507&quot;&gt;Ambroz Bizjak suggested a solution&lt;/a&gt; to my problem which after some discussion even Sustrik seemed to be unaware of. The solution wasn’t completely fleshed out in the comments, so there was still some filling out for me to do. Luckily for you, you won’t have to repeat this exercise.&lt;/p&gt;
&lt;p&gt;The solution is that when going into the blocking ZeroMQ calls, you temporarily block the POSIX signals you want to listen for; &lt;code&gt;SIGTERM&lt;/code&gt; in our case. This can be done using &lt;code&gt;sigprocmask&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, instead of using your regular blocking ZeroMQ call, you use &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; to wait for something to happen on your sockets and your signal queue.** Because, as it turns out, when you temporarily block signals using &lt;code&gt;sigprocmask&lt;/code&gt;, they are put in a queue by the OS. You can then handle them at your earliest convenience.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; functions can monitor lists of sockets &lt;strong&gt;and&lt;/strong&gt; you can give them a &lt;strong&gt;signal mask&lt;/strong&gt; like the one you gave &lt;code&gt;sigprocmask&lt;/code&gt;, but then without the signal that you specifically wanted to block outside of the &lt;code&gt;pselect&lt;/code&gt; / &lt;code&gt;ppoll&lt;/code&gt; call. This will make &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; listen to those signals that you blocked earlier. When a signal came in (or a socket is ready for reading/writing) they will return. If you put the flag check after &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;, the signal will always be handled properly.&lt;/p&gt;
&lt;p&gt;One other critical modification is that in this case you should no longer use blocking ZeroMQ calls. This has also become unnecessary, because you already checked whether some data is incoming on the socket using &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Finally, note that also right after you blocked the signal with &lt;code&gt;sigprocmask&lt;/code&gt;, you should put one additional check for the signal flag, because the signal may yet have triggered somewhere just before you blocked it.&lt;/p&gt;
&lt;p&gt;All in all, the code would then become something like that of Ambroz Bizjak:&lt;/p&gt;
&lt;p&gt;set file descriptor to non-blocking;&lt;strong&gt;sigprocmask&lt;/strong&gt;() to block SIGINT;&lt;strong&gt;if (stop&lt;/strong&gt;) { // handle it }&lt;strong&gt;while (true) {
pselect() with sigmask argument which doesn’t block SIGINT;&lt;/strong&gt;**  if (stop**) { // handle it }**  recv();
}
sigprocmask(old) to put back the old mask in use before we replaced it;&lt;/p&gt;
&lt;h2 id=&quot;integrating-into-zeromq&quot;&gt;Integrating into ZeroMQ&lt;/h2&gt;
&lt;p&gt;This is great in theory, but as already mentioned in the reply by Sustrik: this means we would need a &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; in ZeroMQ. I was originally using &lt;code&gt;zmq::poll&lt;/code&gt;, which internally uses regular POSIX &lt;code&gt;poll&lt;/code&gt;. We can in principle modify this fairly easily to take the additional argument necessary for &lt;code&gt;ppoll&lt;/code&gt;, namely the signal mask.&lt;/p&gt;
&lt;p&gt;However, then we need to decide on how to handle this internally in ZMQ. I cannot do this on my own, but decided to write a first implementation anyway. However, when I started thinking about actually doing this, a few new problems raised their ugly heads.&lt;/p&gt;
&lt;p&gt;The first idea I had was to again use a global flag that can be flipped from the signal handler when a signal is received… At this point I finally realized what Sustrik was talking about when he said we can’t use signal handlers in libraries. First of all: we don’t know which signals the user will want to actually mask. Maybe they want to act on several signals and so will need several global flags. So, long story short: this cannot be done generically inside a &lt;code&gt;zmq::ppoll&lt;/code&gt; or &lt;code&gt;zmq::pselect&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So then we only have two possible tools left to let the user know we caught a signal: the return value and the error code.&lt;/p&gt;
&lt;p&gt;The return value is constrained; the API should conform to existing APIs like those of POSIX &lt;code&gt;ppoll&lt;/code&gt; and &lt;code&gt;zmq::poll&lt;/code&gt;. We can only use return values of &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;, where &lt;code&gt;-1&lt;/code&gt; means an error occurred. So probably the only sensible option is to modify &lt;code&gt;zmq_poll&lt;/code&gt; (now I’m talking about the libzmq implementation; &lt;code&gt;zmq::poll&lt;/code&gt; is merely a C++ wrapper around &lt;code&gt;zmq_poll&lt;/code&gt;) to return &lt;code&gt;-1&lt;/code&gt; and set the &lt;code&gt;errno&lt;/code&gt; to &lt;code&gt;EINTR&lt;/code&gt; when the signal is received.&lt;/p&gt;
&lt;p&gt;So this sounds a bit like we’d be back at square one… Except that this time the &lt;code&gt;ppoll&lt;/code&gt; function would be the only place where the signal is unblocked**, so we know exactly where it will occur and, more importantly, where it will not. Problem solved!&lt;/p&gt;
&lt;p&gt;Now I just had to write it…&lt;/p&gt;
&lt;h2 id=&quot;ppoll-pselect-or-self-pipe&quot;&gt;Ppoll, pselect or self-pipe?&lt;/h2&gt;
&lt;p&gt;After a two week hiatus, I came back, tried to implement &lt;code&gt;zmq_ppoll&lt;/code&gt; by simply copy-pasting &lt;code&gt;zmq_poll&lt;/code&gt; and replacing &lt;code&gt;poll&lt;/code&gt; with &lt;code&gt;ppoll&lt;/code&gt;, but was unpleasantly surprised by the fact that &lt;code&gt;ppoll&lt;/code&gt; apparently doesn’t exist on macOS. &lt;code&gt;[pselect](&amp;#x26;lt;https://stackoverflow.com/a/46047380/1199693&amp;#x26;gt;)&lt;/code&gt; does exist, so we’ll have to go with that.&lt;/p&gt;
&lt;p&gt;Luckily, the &lt;code&gt;zmq_poll&lt;/code&gt; implementation is really flexible, and already includes a &lt;code&gt;select&lt;/code&gt;-based path next to the &lt;code&gt;poll&lt;/code&gt;-based one. We modify that to take a &lt;code&gt;sigmask&lt;/code&gt; and Bob’s your uncle.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Combining ZeroMQ &amp;amp;#x26; POSIX signals&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-0ca88b1f.CCaf_wTP_M6fsr.webp&quot; srcset=&quot;&quot;&gt;
I’m your uncle! &lt;a href=&quot;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&quot;&gt;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&lt;/a&gt;So indeed, let’s try out &lt;code&gt;pselect&lt;/code&gt;. I did have some reservations, because the web is rather full of reports of it not being implemented properly on macOS / FreeBSD… see &lt;a href=&quot;https://stackoverflow.com/questions/14045801/different-pselect-behaviour-on-osx-vs-linux&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=12857275&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=16321529&quot;&gt;here&lt;/a&gt;… Hopefully, as also reported &lt;a href=&quot;https://news.ycombinator.com/item?id=12904883&quot;&gt;here&lt;/a&gt;, in recent versions this is fixed. It seems like they could have taken inspiration by now from many existing, reportedly correct, implementations, like &lt;a href=&quot;http://lua-users.org/lists/lua-l/2015-01/msg00697.html&quot;&gt;this one&lt;/a&gt;. This does mean our implementation will only be really 100% robust on recent macOS versions, but so be it.&lt;/p&gt;
&lt;p&gt;At this point, under all these doubts about the stability of it all, I almost gave up on &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; to try out the so-called “&lt;a href=&quot;http://cr.yp.to/docs/selfpipe.html&quot;&gt;self-pipe trick&lt;/a&gt;” that is also &lt;a href=&quot;https://lwn.net/Articles/176911/&quot;&gt;floating around&lt;/a&gt; in these discussions. This could be a good alternative in some ways.&lt;/p&gt;
&lt;p&gt;The problem with the self-pipe trick is that you can’t fully implement it in all its gory details in a library. The trick involves sending a byte over a pipe from a signal handler*. As &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1654888&quot;&gt;Sustrik mentions&lt;/a&gt;, we cannot rely on signal handlers at all. We have to assume they can be overridden by users of our libraries. In fact, ROOT might install its own signal handlers, indeed invalidating the entire approach we’d be going for here. Though, in fact, the last signal handler that is set is the one that trumps others. When we only set the &lt;code&gt;SIGTERM&lt;/code&gt; handler when doing all this stuff and then set the handler back to its original value afterwards, we should be safe, except that we might be interfering with other signal handlers, but that will be necessary in most cases anyway, because also the &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; route will at some point need to install a signal handler. The cleaner alternative (when setting signal handlers are really out of the question) is to let the user of your library implement their own self-pipe signal handler. In my opinion, this is way too heavy a burden on the user.&lt;/p&gt;
&lt;p&gt;So in the end, I chose to go with &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt;, because it puts most of the code on the library side and avoids having to setup and maintain an extra pipe. The only thing you need with the &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; option is a simple signal handler and a flag to check. It seems like a simpler and more user-friendly option.&lt;/p&gt;
&lt;p&gt;Whatever you choose, some handling of POSIX signals will be necessary in a robust multi-process application. For instance, if a child process dies for some reason, a &lt;code&gt;SIGCHLD&lt;/code&gt; signal is sent to the parent, which could also interrupt blocking reads, sends and polls (if &lt;code&gt;SIG_IGN&lt;/code&gt; is not set for this signal). These must be handled either by using &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; or by using the self-pipe trick.&lt;/p&gt;
&lt;h2 id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;
&lt;p&gt;So, I implemented the &lt;code&gt;zmq::ppoll&lt;/code&gt; via &lt;code&gt;pselect&lt;/code&gt; route. And finally, after a lot of debugging, it seems to be working well!&lt;/p&gt;
&lt;p&gt;Its low level implementation (&lt;code&gt;zmq_ppoll&lt;/code&gt;) depends on many libzmq macros, defines and functions. Trying to build against this creates a giant string of dependency files. The problem with this is that libzmq does not expose all these internal headers, so for the time being I just copy pasted over all the necessary libzmq files. Amazingly, this just seems to work after a few tweaks. My compliments to the libzmq devs for creating such modular code!&lt;/p&gt;
&lt;p&gt;Regarding the few tweaks: there are a lot of precompiler variables which are used to configure the compiled libzmq code. It seems that for macOS, this configuration is perfectly comfortable basing &lt;code&gt;zmq_poll&lt;/code&gt; on &lt;code&gt;poll&lt;/code&gt;. This makes sense, but for our purposes it is really annoying, because we need all the stuff that would be compiled in the case &lt;code&gt;zmq_poll&lt;/code&gt; would be based on &lt;code&gt;select&lt;/code&gt;. A lot of necessary classes and typedefs are therefore not at all fed to the compiler from all the lazily copy-pasted headers and source files.&lt;/p&gt;
&lt;p&gt;This would become an issue if I was to submit all this &lt;code&gt;ppoll&lt;/code&gt; work to libzmq as a pull request. My need for &lt;code&gt;select&lt;/code&gt; would inflate the library a bit. This is a trade-off that the libzmq devs will have to decide on.&lt;/p&gt;
&lt;p&gt;If they don’t see this happening, I can still publish &lt;code&gt;zmq::ppoll&lt;/code&gt; as a separate library. I just need to flip the switch on all the &lt;code&gt;select&lt;/code&gt; vs &lt;code&gt;poll&lt;/code&gt; configured code. This can be done from &lt;code&gt;platform.hpp&lt;/code&gt;. And this is exactly what I’ve done in &lt;a href=&quot;https://github.com/roofit-dev/root/tree/MP_ZeroMQ-new_multiprocess/roofit/roofitZMQ&quot;&gt;the current RooFitZMQ implementation that you can find in this hidden away corner of GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;even-more-details&quot;&gt;Even more details&lt;/h2&gt;
&lt;p&gt;For the really technically interested reader (as if you would be anything else if you’ve reached this far down into the article), some final implementation details that may trip you up (as they did for me):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a &lt;code&gt;volatile sig_atomic_t&lt;/code&gt; value type for any values you set from within a signal handler. Changing other types is undefined behavior. It will usually work, but I guess in some rare cases it may not and you’ll be scrambling for explanations and will never sleep well again, knowing the mysterious bug that has eluded you for years and that you have heard whispered rumors about from your users is still lurking in the shadows.&lt;/li&gt;
&lt;li&gt;Handle errors (exceptions in the C++ case) wisely. That’s the short version, see the rest of this article for the long version.&lt;/li&gt;
&lt;li&gt;Make sure to set both your receives and your sends to non-blocking with the &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt; flag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A practical problem with the latter point is that at the beginning of your run, the connections may not have been made between the sockets. This can lead to the non-blocking send to drop out with an EAGAIN error. Now, you may think (like I did): fine, I’ll handle that error and retry the send. However, the same error will occur at the end of your program when you disconnected the other end of your socket on purpose (as I found out the hard way). At this time, you won’t want to retry infinitely, which would hang your program (which happened to me), so just covering up all your sends in retry loops that trigger on EAGAIN will be too coarse a solution (believe me, I tried).&lt;/p&gt;
&lt;p&gt;What I went with in the end is to define a &lt;code&gt;send_flag&lt;/code&gt; in my Messenger class which I pass as the &lt;code&gt;flag&lt;/code&gt; option to all send calls. Initially, &lt;code&gt;send_flag&lt;/code&gt; is zero, so the send calls will block. I then call a &lt;code&gt;test_connections&lt;/code&gt; method and after this completes successfully, I set &lt;code&gt;send_flag&lt;/code&gt; to &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt;. Now, once the connection drops out, send calls will give the EAGAIN error. But this time, the start-of-the-program cause of EAGAIN is ruled out, so I can assume that the program has ended. I catch the EAGAIN in my event loops and continue the loop when I get an EAGAIN. This means the code will first come across my &lt;code&gt;ppoll&lt;/code&gt; again before it comes back to the send that caused the EAGAIN. Inside &lt;code&gt;ppoll&lt;/code&gt;, it will handle the &lt;code&gt;SIGTERM&lt;/code&gt; signal that I expect has been sent from the master process and the event loop will be exited properly.&lt;/p&gt;
&lt;p&gt;Lol, you thought that would be it, but no, it’s still not that simple (I’m talking to my innocent, naive, past self here). There are still three other reasons EAGAIN could trigger!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calls to receive (&lt;code&gt;recv&lt;/code&gt;) can also trigger an EAGAIN. To distinguish between send and receive EAGAIN triggers, we could throw different typed exceptions (remember, we’re doing C++ here, so every time I’m talking about error codes, what actually happened was a &lt;code&gt;zmq::error_t&lt;/code&gt; type exception was thrown… which also happens to carry along the traditional C style error code). As far as I can tell, the only reason &lt;code&gt;recv&lt;/code&gt; would trigger EAGAIN after a &lt;code&gt;ppoll&lt;/code&gt; (which I now call before every &lt;code&gt;recv&lt;/code&gt; call) is if &lt;code&gt;ppoll&lt;/code&gt; initially gets a read-ready signal for the socket, but the received data does not pass a ZMQ internal checksum test, so the socket becomes unreadable again when you actually try to read from it. In this case, which I hope is rare, things will probably break unless you try really hard to fix them, i.e. send a signal to the sender that something went wrong, or otherwise implementing a really robust messenging protocol. This therefore goes far beyond the scope of just combining ZMQ with POSIX signals and is described very well elsewhere (like in &lt;a href=&quot;http://zguide.zeromq.org/&quot;&gt;the awesome ZMQ guide&lt;/a&gt; I mentioned at the beginning of this article; in case you forgot, which I myself did, because it took me three weeks to get to the end of writing this post).&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;send&lt;/code&gt; call may have two other legitimate reasons for crapping out with EAGAIN. The first is that its receiving end may have hit its “high-water mark”, a ZMQ setting which you can look up in the ZMQ guide or elsewhere.&lt;/li&gt;
&lt;li&gt;The second reason &lt;code&gt;send&lt;/code&gt; could throw an EAGAIN is that the connection may have been severed unexpectedly. In my case, this would mean that in the following &lt;code&gt;ppoll&lt;/code&gt; call, no &lt;code&gt;SIGTERM&lt;/code&gt; signal will be received and so the code will just try to go on, probably hitting the same connection error again and again ad infinitum. This should also be handled properly, but I’m hoping it’s rare enough to not have to worry about it too much. Obviously, I will worry about it for the rest of my waking days. Will probably write another huge blog post about it at some point. Oh well!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We leave the latter problems to be solved as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Combining ZeroMQ &amp;amp;#x26; POSIX signals&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-b7296cf6.DbAeRZKP_wm8GG.webp&quot; srcset=&quot;&quot;&gt;
The reader.&lt;/p&gt;
&lt;h2 id=&quot;to-be-continued&quot;&gt;To be continued&lt;/h2&gt;
&lt;p&gt;So stay tuned for the release of &lt;code&gt;zmq_ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update Oct 2021: &lt;em&gt;&lt;code&gt;*zmq_ppoll*&lt;/code&gt;&lt;/em&gt; is now included in &lt;em&gt;&lt;a href=&quot;https://github.com/zeromq/libzmq/pull/4255&quot;&gt;&lt;em&gt;libzmq&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you have any questions or other thoughts, let me know in the comments or on &lt;a href=&quot;https://twitter.com/egpbos&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/f2r1i6/combining_zeromq_posix_signals_use_ppoll_to/&quot;&gt;Reddit&lt;/a&gt;! Having spent so much time on this stuff, I guess sunk cost fallacy demands of me that I spend even more time on it by discussing it with as many people as possible ;) Also, I guess I’m kind of a mental masochist. Figuring out this stuff has been extremely frustrating, but also extremely satisfying. So throw your problems at me, I’m hungry for more!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Combining ZeroMQ &amp;amp;#x26; POSIX signals&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-e6392eca.0irim351_y5OEb.webp&quot; srcset=&quot;&quot;&gt;
My happy face (not mine, but close enough), thinking about solving even more complex messaging problems.Thanks to [Lourens Veen,] Inti Pelupessy and [Peter Kalverla] for reviewing this article.&lt;/p&gt;</description><pubDate>Tue, 16 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;use-ppoll-to-handle-eintr-once-and-for-all&quot;&gt;Use ppoll to handle EINTR once and for all&lt;/h2&gt;
&lt;p&gt;Eventually, I found &lt;a href=&quot;http://250bpm.com/blog:12&quot;&gt;this article on EINTR in ZeroMQ&lt;/a&gt; by Martin Sustrik (ZeroMQ creator) himself. More precisely, in the comment section &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1608507&quot;&gt;Ambroz Bizjak suggested a solution&lt;/a&gt; to my problem which after some discussion even Sustrik seemed to be unaware of. The solution wasn’t completely fleshed out in the comments, so there was still some filling out for me to do. Luckily for you, you won’t have to repeat this exercise.&lt;/p&gt;
&lt;p&gt;The solution is that when going into the blocking ZeroMQ calls, you temporarily block the POSIX signals you want to listen for; &lt;code&gt;SIGTERM&lt;/code&gt; in our case. This can be done using &lt;code&gt;sigprocmask&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, instead of using your regular blocking ZeroMQ call, you use &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; to wait for something to happen on your sockets and your signal queue.** Because, as it turns out, when you temporarily block signals using &lt;code&gt;sigprocmask&lt;/code&gt;, they are put in a queue by the OS. You can then handle them at your earliest convenience.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; functions can monitor lists of sockets &lt;strong&gt;and&lt;/strong&gt; you can give them a &lt;strong&gt;signal mask&lt;/strong&gt; like the one you gave &lt;code&gt;sigprocmask&lt;/code&gt;, but then without the signal that you specifically wanted to block outside of the &lt;code&gt;pselect&lt;/code&gt; / &lt;code&gt;ppoll&lt;/code&gt; call. This will make &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; listen to those signals that you blocked earlier. When a signal came in (or a socket is ready for reading/writing) they will return. If you put the flag check after &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;, the signal will always be handled properly.&lt;/p&gt;
&lt;p&gt;One other critical modification is that in this case you should no longer use blocking ZeroMQ calls. This has also become unnecessary, because you already checked whether some data is incoming on the socket using &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Finally, note that also right after you blocked the signal with &lt;code&gt;sigprocmask&lt;/code&gt;, you should put one additional check for the signal flag, because the signal may yet have triggered somewhere just before you blocked it.&lt;/p&gt;
&lt;p&gt;All in all, the code would then become something like that of Ambroz Bizjak:&lt;/p&gt;
&lt;p&gt;set file descriptor to non-blocking;&lt;strong&gt;sigprocmask&lt;/strong&gt;() to block SIGINT;&lt;strong&gt;if (stop&lt;/strong&gt;) { // handle it }&lt;strong&gt;while (true) {
pselect() with sigmask argument which doesn’t block SIGINT;&lt;/strong&gt;**  if (stop**) { // handle it }**  recv();
}
sigprocmask(old) to put back the old mask in use before we replaced it;&lt;/p&gt;
&lt;h2 id=&quot;integrating-into-zeromq&quot;&gt;Integrating into ZeroMQ&lt;/h2&gt;
&lt;p&gt;This is great in theory, but as already mentioned in the reply by Sustrik: this means we would need a &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; in ZeroMQ. I was originally using &lt;code&gt;zmq::poll&lt;/code&gt;, which internally uses regular POSIX &lt;code&gt;poll&lt;/code&gt;. We can in principle modify this fairly easily to take the additional argument necessary for &lt;code&gt;ppoll&lt;/code&gt;, namely the signal mask.&lt;/p&gt;
&lt;p&gt;However, then we need to decide on how to handle this internally in ZMQ. I cannot do this on my own, but decided to write a first implementation anyway. However, when I started thinking about actually doing this, a few new problems raised their ugly heads.&lt;/p&gt;
&lt;p&gt;The first idea I had was to again use a global flag that can be flipped from the signal handler when a signal is received… At this point I finally realized what Sustrik was talking about when he said we can’t use signal handlers in libraries. First of all: we don’t know which signals the user will want to actually mask. Maybe they want to act on several signals and so will need several global flags. So, long story short: this cannot be done generically inside a &lt;code&gt;zmq::ppoll&lt;/code&gt; or &lt;code&gt;zmq::pselect&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So then we only have two possible tools left to let the user know we caught a signal: the return value and the error code.&lt;/p&gt;
&lt;p&gt;The return value is constrained; the API should conform to existing APIs like those of POSIX &lt;code&gt;ppoll&lt;/code&gt; and &lt;code&gt;zmq::poll&lt;/code&gt;. We can only use return values of &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;, where &lt;code&gt;-1&lt;/code&gt; means an error occurred. So probably the only sensible option is to modify &lt;code&gt;zmq_poll&lt;/code&gt; (now I’m talking about the libzmq implementation; &lt;code&gt;zmq::poll&lt;/code&gt; is merely a C++ wrapper around &lt;code&gt;zmq_poll&lt;/code&gt;) to return &lt;code&gt;-1&lt;/code&gt; and set the &lt;code&gt;errno&lt;/code&gt; to &lt;code&gt;EINTR&lt;/code&gt; when the signal is received.&lt;/p&gt;
&lt;p&gt;So this sounds a bit like we’d be back at square one… Except that this time the &lt;code&gt;ppoll&lt;/code&gt; function would be the only place where the signal is unblocked**, so we know exactly where it will occur and, more importantly, where it will not. Problem solved!&lt;/p&gt;
&lt;p&gt;Now I just had to write it…&lt;/p&gt;
&lt;h2 id=&quot;ppoll-pselect-or-self-pipe&quot;&gt;Ppoll, pselect or self-pipe?&lt;/h2&gt;
&lt;p&gt;After a two week hiatus, I came back, tried to implement &lt;code&gt;zmq_ppoll&lt;/code&gt; by simply copy-pasting &lt;code&gt;zmq_poll&lt;/code&gt; and replacing &lt;code&gt;poll&lt;/code&gt; with &lt;code&gt;ppoll&lt;/code&gt;, but was unpleasantly surprised by the fact that &lt;code&gt;ppoll&lt;/code&gt; apparently doesn’t exist on macOS. &lt;code&gt;[pselect](&amp;#x26;lt;https://stackoverflow.com/a/46047380/1199693&amp;#x26;gt;)&lt;/code&gt; does exist, so we’ll have to go with that.&lt;/p&gt;
&lt;p&gt;Luckily, the &lt;code&gt;zmq_poll&lt;/code&gt; implementation is really flexible, and already includes a &lt;code&gt;select&lt;/code&gt;-based path next to the &lt;code&gt;poll&lt;/code&gt;-based one. We modify that to take a &lt;code&gt;sigmask&lt;/code&gt; and Bob’s your uncle.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Combining ZeroMQ &amp;amp;#x26; POSIX signals&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-0ca88b1f.CCaf_wTP_M6fsr.webp&quot; srcset=&quot;&quot;&gt;
I’m your uncle! &lt;a href=&quot;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&quot;&gt;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&lt;/a&gt;So indeed, let’s try out &lt;code&gt;pselect&lt;/code&gt;. I did have some reservations, because the web is rather full of reports of it not being implemented properly on macOS / FreeBSD… see &lt;a href=&quot;https://stackoverflow.com/questions/14045801/different-pselect-behaviour-on-osx-vs-linux&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=12857275&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=16321529&quot;&gt;here&lt;/a&gt;… Hopefully, as also reported &lt;a href=&quot;https://news.ycombinator.com/item?id=12904883&quot;&gt;here&lt;/a&gt;, in recent versions this is fixed. It seems like they could have taken inspiration by now from many existing, reportedly correct, implementations, like &lt;a href=&quot;http://lua-users.org/lists/lua-l/2015-01/msg00697.html&quot;&gt;this one&lt;/a&gt;. This does mean our implementation will only be really 100% robust on recent macOS versions, but so be it.&lt;/p&gt;
&lt;p&gt;At this point, under all these doubts about the stability of it all, I almost gave up on &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; to try out the so-called “&lt;a href=&quot;http://cr.yp.to/docs/selfpipe.html&quot;&gt;self-pipe trick&lt;/a&gt;” that is also &lt;a href=&quot;https://lwn.net/Articles/176911/&quot;&gt;floating around&lt;/a&gt; in these discussions. This could be a good alternative in some ways.&lt;/p&gt;
&lt;p&gt;The problem with the self-pipe trick is that you can’t fully implement it in all its gory details in a library. The trick involves sending a byte over a pipe from a signal handler*. As &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1654888&quot;&gt;Sustrik mentions&lt;/a&gt;, we cannot rely on signal handlers at all. We have to assume they can be overridden by users of our libraries. In fact, ROOT might install its own signal handlers, indeed invalidating the entire approach we’d be going for here. Though, in fact, the last signal handler that is set is the one that trumps others. When we only set the &lt;code&gt;SIGTERM&lt;/code&gt; handler when doing all this stuff and then set the handler back to its original value afterwards, we should be safe, except that we might be interfering with other signal handlers, but that will be necessary in most cases anyway, because also the &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; route will at some point need to install a signal handler. The cleaner alternative (when setting signal handlers are really out of the question) is to let the user of your library implement their own self-pipe signal handler. In my opinion, this is way too heavy a burden on the user.&lt;/p&gt;
&lt;p&gt;So in the end, I chose to go with &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt;, because it puts most of the code on the library side and avoids having to setup and maintain an extra pipe. The only thing you need with the &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; option is a simple signal handler and a flag to check. It seems like a simpler and more user-friendly option.&lt;/p&gt;
&lt;p&gt;Whatever you choose, some handling of POSIX signals will be necessary in a robust multi-process application. For instance, if a child process dies for some reason, a &lt;code&gt;SIGCHLD&lt;/code&gt; signal is sent to the parent, which could also interrupt blocking reads, sends and polls (if &lt;code&gt;SIG_IGN&lt;/code&gt; is not set for this signal). These must be handled either by using &lt;code&gt;ppoll&lt;/code&gt;/&lt;code&gt;pselect&lt;/code&gt; or by using the self-pipe trick.&lt;/p&gt;
&lt;h2 id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;
&lt;p&gt;So, I implemented the &lt;code&gt;zmq::ppoll&lt;/code&gt; via &lt;code&gt;pselect&lt;/code&gt; route. And finally, after a lot of debugging, it seems to be working well!&lt;/p&gt;
&lt;p&gt;Its low level implementation (&lt;code&gt;zmq_ppoll&lt;/code&gt;) depends on many libzmq macros, defines and functions. Trying to build against this creates a giant string of dependency files. The problem with this is that libzmq does not expose all these internal headers, so for the time being I just copy pasted over all the necessary libzmq files. Amazingly, this just seems to work after a few tweaks. My compliments to the libzmq devs for creating such modular code!&lt;/p&gt;
&lt;p&gt;Regarding the few tweaks: there are a lot of precompiler variables which are used to configure the compiled libzmq code. It seems that for macOS, this configuration is perfectly comfortable basing &lt;code&gt;zmq_poll&lt;/code&gt; on &lt;code&gt;poll&lt;/code&gt;. This makes sense, but for our purposes it is really annoying, because we need all the stuff that would be compiled in the case &lt;code&gt;zmq_poll&lt;/code&gt; would be based on &lt;code&gt;select&lt;/code&gt;. A lot of necessary classes and typedefs are therefore not at all fed to the compiler from all the lazily copy-pasted headers and source files.&lt;/p&gt;
&lt;p&gt;This would become an issue if I was to submit all this &lt;code&gt;ppoll&lt;/code&gt; work to libzmq as a pull request. My need for &lt;code&gt;select&lt;/code&gt; would inflate the library a bit. This is a trade-off that the libzmq devs will have to decide on.&lt;/p&gt;
&lt;p&gt;If they don’t see this happening, I can still publish &lt;code&gt;zmq::ppoll&lt;/code&gt; as a separate library. I just need to flip the switch on all the &lt;code&gt;select&lt;/code&gt; vs &lt;code&gt;poll&lt;/code&gt; configured code. This can be done from &lt;code&gt;platform.hpp&lt;/code&gt;. And this is exactly what I’ve done in &lt;a href=&quot;https://github.com/roofit-dev/root/tree/MP_ZeroMQ-new_multiprocess/roofit/roofitZMQ&quot;&gt;the current RooFitZMQ implementation that you can find in this hidden away corner of GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;even-more-details&quot;&gt;Even more details&lt;/h2&gt;
&lt;p&gt;For the really technically interested reader (as if you would be anything else if you’ve reached this far down into the article), some final implementation details that may trip you up (as they did for me):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a &lt;code&gt;volatile sig_atomic_t&lt;/code&gt; value type for any values you set from within a signal handler. Changing other types is undefined behavior. It will usually work, but I guess in some rare cases it may not and you’ll be scrambling for explanations and will never sleep well again, knowing the mysterious bug that has eluded you for years and that you have heard whispered rumors about from your users is still lurking in the shadows.&lt;/li&gt;
&lt;li&gt;Handle errors (exceptions in the C++ case) wisely. That’s the short version, see the rest of this article for the long version.&lt;/li&gt;
&lt;li&gt;Make sure to set both your receives and your sends to non-blocking with the &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt; flag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A practical problem with the latter point is that at the beginning of your run, the connections may not have been made between the sockets. This can lead to the non-blocking send to drop out with an EAGAIN error. Now, you may think (like I did): fine, I’ll handle that error and retry the send. However, the same error will occur at the end of your program when you disconnected the other end of your socket on purpose (as I found out the hard way). At this time, you won’t want to retry infinitely, which would hang your program (which happened to me), so just covering up all your sends in retry loops that trigger on EAGAIN will be too coarse a solution (believe me, I tried).&lt;/p&gt;
&lt;p&gt;What I went with in the end is to define a &lt;code&gt;send_flag&lt;/code&gt; in my Messenger class which I pass as the &lt;code&gt;flag&lt;/code&gt; option to all send calls. Initially, &lt;code&gt;send_flag&lt;/code&gt; is zero, so the send calls will block. I then call a &lt;code&gt;test_connections&lt;/code&gt; method and after this completes successfully, I set &lt;code&gt;send_flag&lt;/code&gt; to &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt;. Now, once the connection drops out, send calls will give the EAGAIN error. But this time, the start-of-the-program cause of EAGAIN is ruled out, so I can assume that the program has ended. I catch the EAGAIN in my event loops and continue the loop when I get an EAGAIN. This means the code will first come across my &lt;code&gt;ppoll&lt;/code&gt; again before it comes back to the send that caused the EAGAIN. Inside &lt;code&gt;ppoll&lt;/code&gt;, it will handle the &lt;code&gt;SIGTERM&lt;/code&gt; signal that I expect has been sent from the master process and the event loop will be exited properly.&lt;/p&gt;
&lt;p&gt;Lol, you thought that would be it, but no, it’s still not that simple (I’m talking to my innocent, naive, past self here). There are still three other reasons EAGAIN could trigger!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Calls to receive (&lt;code&gt;recv&lt;/code&gt;) can also trigger an EAGAIN. To distinguish between send and receive EAGAIN triggers, we could throw different typed exceptions (remember, we’re doing C++ here, so every time I’m talking about error codes, what actually happened was a &lt;code&gt;zmq::error_t&lt;/code&gt; type exception was thrown… which also happens to carry along the traditional C style error code). As far as I can tell, the only reason &lt;code&gt;recv&lt;/code&gt; would trigger EAGAIN after a &lt;code&gt;ppoll&lt;/code&gt; (which I now call before every &lt;code&gt;recv&lt;/code&gt; call) is if &lt;code&gt;ppoll&lt;/code&gt; initially gets a read-ready signal for the socket, but the received data does not pass a ZMQ internal checksum test, so the socket becomes unreadable again when you actually try to read from it. In this case, which I hope is rare, things will probably break unless you try really hard to fix them, i.e. send a signal to the sender that something went wrong, or otherwise implementing a really robust messenging protocol. This therefore goes far beyond the scope of just combining ZMQ with POSIX signals and is described very well elsewhere (like in &lt;a href=&quot;http://zguide.zeromq.org/&quot;&gt;the awesome ZMQ guide&lt;/a&gt; I mentioned at the beginning of this article; in case you forgot, which I myself did, because it took me three weeks to get to the end of writing this post).&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;send&lt;/code&gt; call may have two other legitimate reasons for crapping out with EAGAIN. The first is that its receiving end may have hit its “high-water mark”, a ZMQ setting which you can look up in the ZMQ guide or elsewhere.&lt;/li&gt;
&lt;li&gt;The second reason &lt;code&gt;send&lt;/code&gt; could throw an EAGAIN is that the connection may have been severed unexpectedly. In my case, this would mean that in the following &lt;code&gt;ppoll&lt;/code&gt; call, no &lt;code&gt;SIGTERM&lt;/code&gt; signal will be received and so the code will just try to go on, probably hitting the same connection error again and again ad infinitum. This should also be handled properly, but I’m hoping it’s rare enough to not have to worry about it too much. Obviously, I will worry about it for the rest of my waking days. Will probably write another huge blog post about it at some point. Oh well!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We leave the latter problems to be solved as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Combining ZeroMQ &amp;amp;#x26; POSIX signals&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-b7296cf6.DbAeRZKP_wm8GG.webp&quot; srcset=&quot;&quot;&gt;
The reader.&lt;/p&gt;
&lt;h2 id=&quot;to-be-continued&quot;&gt;To be continued&lt;/h2&gt;
&lt;p&gt;So stay tuned for the release of &lt;code&gt;zmq_ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update Oct 2021: &lt;em&gt;&lt;code&gt;*zmq_ppoll*&lt;/code&gt;&lt;/em&gt; is now included in &lt;em&gt;&lt;a href=&quot;https://github.com/zeromq/libzmq/pull/4255&quot;&gt;&lt;em&gt;libzmq&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you have any questions or other thoughts, let me know in the comments or on &lt;a href=&quot;https://twitter.com/egpbos&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/f2r1i6/combining_zeromq_posix_signals_use_ppoll_to/&quot;&gt;Reddit&lt;/a&gt;! Having spent so much time on this stuff, I guess sunk cost fallacy demands of me that I spend even more time on it by discussing it with as many people as possible ;) Also, I guess I’m kind of a mental masochist. Figuring out this stuff has been extremely frustrating, but also extremely satisfying. So throw your problems at me, I’m hungry for more!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Combining ZeroMQ &amp;amp;#x26; POSIX signals&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;466&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-e6392eca.0irim351_y5OEb.webp&quot; srcset=&quot;&quot;&gt;
My happy face (not mine, but close enough), thinking about solving even more complex messaging problems.Thanks to [Lourens Veen,] Inti Pelupessy and [Peter Kalverla] for reviewing this article.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/combining-zeromq-amp-posix-signals-0ca88b1f.CCaf_wTP.png" medium="image"/><author>Patrick Bos</author></item><item><title>Decorators in R</title><link>https://blog2.esciencecenter.nl/posts/2021-09-29---decorators-in-r</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-09-29---decorators-in-r</guid><description>&lt;p&gt;Decorators have been made quite popular by Python but, did you know they also exist in R?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_A6j5Seyt_V3qq5Si-c5a79df8.DrehzlkI_Z11QrU0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Lenny Kuhne on Unsplash&lt;/p&gt;
&lt;p&gt;Decorators are typically used to extend the behaviour of a function in an elegant and minimally invasive way. Graphically, we can think of a decorator as:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;534&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ciWjhFQWICOV9SmeFsMuWg-594f2a3b.BLSn3eAg_Zq52jX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An analogy of a decorator. The original function is a car. The decorator adds an antenna and a wing to the car, but the basic functionality of the car (transporting people) remains unchanged. Icons made by Smashicons and Freepik.&lt;/p&gt;
&lt;p&gt;Some examples of things you may want to do with a decorator are logging the input/output of a function, or timing it. The power of decorators is that, when properly designed, they work for &lt;strong&gt;any&lt;/strong&gt; function. This makes them quite versatile and useful, as we’ll see in some examples below.&lt;/p&gt;
&lt;p&gt;From a more technical point of view, decorators are &lt;em&gt;functionals&lt;/em&gt;. In mathematics, a functional is an object that takes functions as an input. In the case of decorators, they also return a function as an output. If you want to sound fancy, you can say that a decorator is an endomorphism over a functional space. But I prefer clarity above fanciness: a decorator is something that swallows functions and, well…, poops functions.&lt;/p&gt;
&lt;h2 id=&quot;functions-as-first-class-objects&quot;&gt;Functions as first-class objects&lt;/h2&gt;
&lt;p&gt;Decorators can be implemented in any language that treats functions as first-class objects. Long story short, this means that functions exist even if they are not called. Does this sound too abstract? Let’s get specific: check out the code snippets below.&lt;/p&gt;
&lt;p&gt;We can use the function &lt;code&gt;cos&lt;/code&gt; to calculate a cosine:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1416&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But in R, &lt;code&gt;cos&lt;/code&gt; itself is an object. We can, for instance, assign it to something:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because &lt;code&gt;foo&lt;/code&gt; is now a function, we can call it with an argument:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1416&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we call it without an argument, it still returns something. Something a bit obscure, but something nonetheless:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function (x)  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Primitive&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;cos&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that the function itself is an object that lives in our environment and that, in principle, we can manipulate it. This is exactly what a decorator will do.&lt;/p&gt;
&lt;h2 id=&quot;the-skeleton-of-a-basic-decorator&quot;&gt;The skeleton of a basic decorator&lt;/h2&gt;
&lt;p&gt;The basic skeleton of a decorator in R looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;deco &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f) {  wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       # &amp;#x3C;code prior to execution&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;       #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;code posterior to execution&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can apply it like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f_decorated &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; deco(f)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is worth spending a minute looking at the skeleton above. The decorator will return a wrapper. A wrapper can be thought of as an improved version of the original function (but not of its result!, just like &lt;code&gt;foo&lt;/code&gt; didn’t return a result until we called &lt;code&gt;foo(3.1416)&lt;/code&gt;). The &lt;code&gt;...&lt;/code&gt; symbol stands for &lt;strong&gt;any&lt;/strong&gt; input (more on this later).Now, every time we call &lt;code&gt;f_decorated&lt;/code&gt; passing some argument(s) to it, not only the original &lt;code&gt;f&lt;/code&gt; will be executed, but also the code marked as prior and posterior.&lt;/p&gt;
&lt;p&gt;Let’s see some examples:&lt;/p&gt;
&lt;h2 id=&quot;time-my-function&quot;&gt;Time my function&lt;/h2&gt;
&lt;p&gt;The decorator below can be used to print the starting and ending times of your function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;timer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f) {   wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      # Before execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      op &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; options(digits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;secs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Increase&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time resolution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      print(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time:&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Sys.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the clock before      res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; After&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      print(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time:&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Sys.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the clock after      return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can create an “improved” version of any function. Let’s try with the cosine function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos_timed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; timer(cos)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos_timed(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1416&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time: 2021-07-28 12:32:26.309175&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time: 2021-07-28 12:32:26.310383&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the code above is equivalent to the shorthand:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;timer(cos)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1418&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;...&lt;/code&gt; syntax, meaning any amount of input parameters, allows for timing functions of different amounts of parameters without having to change anything at all. Check this out:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; timer(runif)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time: 2021-07-28 12:35:02.506004&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time: 2021-07-28 12:35:02.50642&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]  &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.63678797&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  0.99874053&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.09436601&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  0.91444153&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  0.77181499&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: please take this only as an example. If you really need to time your R functions, I advise you to use profiling tools instead.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;log-my-function&quot;&gt;Log my function&lt;/h2&gt;
&lt;p&gt;Another interesting possibility is using a decorator for logging the output of any function. Check this out:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logger &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f, filename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &apos;log&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&apos;) {   wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      # Before execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nothing      res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; After&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      write(res, file &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; filename, append &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s apply it, for instance, to the power function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logger(pow)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and it will log the value &lt;code&gt;8&lt;/code&gt; in the default file &lt;code&gt;log.txt&lt;/code&gt;. A non-default log filename can be passed via:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logger(pow, filename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;otherlog.txt&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-about-syntactic-sugar&quot;&gt;What about syntactic sugar?&lt;/h2&gt;
&lt;p&gt;Certainly one of the secrets to the success of decorators in Python is that they look really neat. Instead of something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# In Pythonf_dec = decorator(f)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use syntactic sugar to apply the decorator from the moment the function is defined:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# In Python@decorator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def f(args)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function body&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is it possible to do something similar in R? The answer is yes. And all of it thanks to the &lt;a href=&quot;https://cran.r-project.org/web/packages/tinsel/index.html&quot;&gt;tinsel&lt;/a&gt; package. As usual, the first step is to install and load it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;packages(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tinsel&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(tinsel)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if we want to apply, say, our &lt;code&gt;timer&lt;/code&gt; decorator to a brand-new defined function, we’ll use the special comment &lt;code&gt;#. timer&lt;/code&gt; on top of the definition. This would be equivalent to the syntactic sugar &lt;code&gt;@timer&lt;/code&gt; in Python.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;#. timer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;say_hi &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(name) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   return(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hi&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, name, sep &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot; &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order to make it work, we have to source the file with a special source function contained in the tinsel package:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source_decoratees(&apos;filename&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;R&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we are ready to try it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; say_hi(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Pablo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time: 2021-07-29 10:29:27.364677&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time: 2021-07-29 10:29:27.366081&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hi Pablo&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes… this syntactic sugar is (still) not so amazing as that of Python, but still quite remarkable.&lt;/p&gt;
&lt;h2 id=&quot;a-real-world-problem&quot;&gt;A real-world problem&lt;/h2&gt;
&lt;p&gt;Wait a minute… is this useful at all? I mean, in real-world problems?&lt;/p&gt;
&lt;p&gt;Let me tell you a story. Not long ago, I had to refactor some code that I hadn’t written myself. I cannot imagine a more real-world task than that… and decorators made my life much easier.&lt;/p&gt;
&lt;p&gt;Long story short, the code contained several one-liners that did too much. Particularly, the command &lt;code&gt;system&lt;/code&gt; was used to execute very long instructions that were constructed by pasting pieces of strings. Something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;system(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;command1 &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;--parameter &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;command 2 &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, as&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;character(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1250&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot; more_commands &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), intern &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ignore&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;stdout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each line differed in the size and composition of the pasted string. In order to refactor this, and to make it more readable, the first thing I needed to know was the exact content of those complicated strings. There were lots of them, and I didn’t want to manually extract them from inside &lt;code&gt;system&lt;/code&gt;. Luckily for me, the pasted string was passed always as the first argument to the &lt;code&gt;system&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;So I wrote a decorator that logs the first argument of anything, and it saved my day:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;log1starg &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f, filename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &apos;loginput&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&apos;) {  wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(x, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      # Before execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      write(x, file &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; filename, append &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the 1st arg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(x, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; After&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nothing      return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, I only had to find all the appearances of &lt;code&gt;system&lt;/code&gt; and substitute them by &lt;code&gt;log1starg(system)&lt;/code&gt;. After that, just run the script from beginning to the end, and open the freshly created &lt;code&gt;loginput.txt&lt;/code&gt; file containing all the information I needed.&lt;/p&gt;
&lt;h2 id=&quot;what-about-you&quot;&gt;What about you?&lt;/h2&gt;
&lt;p&gt;Can you think of another use for decorators? Please feel free to leave a comment below!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I want to express my gratitude to &lt;a href=&quot;https://medium.com/u/1382ec3ac71f?source=post_page---user_mention--ec84eaeca3e3---------------------------------------&quot;&gt;Patrick Bos&lt;/a&gt; for his useful suggestions.&lt;/p&gt;
&lt;p&gt;This entry appears in &lt;a href=&quot;https://r-bloggers.com/&quot;&gt;R-bloggers.com&lt;/a&gt;&lt;/p&gt;</description><pubDate>Wed, 29 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Decorators have been made quite popular by Python but, did you know they also exist in R?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_A6j5Seyt_V3qq5Si-c5a79df8.DrehzlkI_Z11QrU0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Lenny Kuhne on Unsplash&lt;/p&gt;
&lt;p&gt;Decorators are typically used to extend the behaviour of a function in an elegant and minimally invasive way. Graphically, we can think of a decorator as:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;534&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ciWjhFQWICOV9SmeFsMuWg-594f2a3b.BLSn3eAg_Zq52jX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An analogy of a decorator. The original function is a car. The decorator adds an antenna and a wing to the car, but the basic functionality of the car (transporting people) remains unchanged. Icons made by Smashicons and Freepik.&lt;/p&gt;
&lt;p&gt;Some examples of things you may want to do with a decorator are logging the input/output of a function, or timing it. The power of decorators is that, when properly designed, they work for &lt;strong&gt;any&lt;/strong&gt; function. This makes them quite versatile and useful, as we’ll see in some examples below.&lt;/p&gt;
&lt;p&gt;From a more technical point of view, decorators are &lt;em&gt;functionals&lt;/em&gt;. In mathematics, a functional is an object that takes functions as an input. In the case of decorators, they also return a function as an output. If you want to sound fancy, you can say that a decorator is an endomorphism over a functional space. But I prefer clarity above fanciness: a decorator is something that swallows functions and, well…, poops functions.&lt;/p&gt;
&lt;h2 id=&quot;functions-as-first-class-objects&quot;&gt;Functions as first-class objects&lt;/h2&gt;
&lt;p&gt;Decorators can be implemented in any language that treats functions as first-class objects. Long story short, this means that functions exist even if they are not called. Does this sound too abstract? Let’s get specific: check out the code snippets below.&lt;/p&gt;
&lt;p&gt;We can use the function &lt;code&gt;cos&lt;/code&gt; to calculate a cosine:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1416&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But in R, &lt;code&gt;cos&lt;/code&gt; itself is an object. We can, for instance, assign it to something:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because &lt;code&gt;foo&lt;/code&gt; is now a function, we can call it with an argument:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foo(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1416&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we call it without an argument, it still returns something. Something a bit obscure, but something nonetheless:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; foo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function (x)  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Primitive&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;cos&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that the function itself is an object that lives in our environment and that, in principle, we can manipulate it. This is exactly what a decorator will do.&lt;/p&gt;
&lt;h2 id=&quot;the-skeleton-of-a-basic-decorator&quot;&gt;The skeleton of a basic decorator&lt;/h2&gt;
&lt;p&gt;The basic skeleton of a decorator in R looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;deco &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f) {  wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       # &amp;#x3C;code prior to execution&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;       #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;code posterior to execution&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can apply it like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f_decorated &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; deco(f)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It is worth spending a minute looking at the skeleton above. The decorator will return a wrapper. A wrapper can be thought of as an improved version of the original function (but not of its result!, just like &lt;code&gt;foo&lt;/code&gt; didn’t return a result until we called &lt;code&gt;foo(3.1416)&lt;/code&gt;). The &lt;code&gt;...&lt;/code&gt; symbol stands for &lt;strong&gt;any&lt;/strong&gt; input (more on this later).Now, every time we call &lt;code&gt;f_decorated&lt;/code&gt; passing some argument(s) to it, not only the original &lt;code&gt;f&lt;/code&gt; will be executed, but also the code marked as prior and posterior.&lt;/p&gt;
&lt;p&gt;Let’s see some examples:&lt;/p&gt;
&lt;h2 id=&quot;time-my-function&quot;&gt;Time my function&lt;/h2&gt;
&lt;p&gt;The decorator below can be used to print the starting and ending times of your function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;timer &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f) {   wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      # Before execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      op &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; options(digits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;secs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Increase&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; time resolution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      print(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time:&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Sys.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the clock before      res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; After&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      print(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time:&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Sys.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;time&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Show&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the clock after      return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can create an “improved” version of any function. Let’s try with the cosine function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos_timed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; timer(cos)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cos_timed(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1416&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time: 2021-07-28 12:32:26.309175&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time: 2021-07-28 12:32:26.310383&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the code above is equivalent to the shorthand:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;timer(cos)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3.1418&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;...&lt;/code&gt; syntax, meaning any amount of input parameters, allows for timing functions of different amounts of parameters without having to change anything at all. Check this out:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; timer(runif)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time: 2021-07-28 12:35:02.506004&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time: 2021-07-28 12:35:02.50642&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]  &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.63678797&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  0.99874053&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.09436601&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  0.91444153&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  0.77181499&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note: please take this only as an example. If you really need to time your R functions, I advise you to use profiling tools instead.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;log-my-function&quot;&gt;Log my function&lt;/h2&gt;
&lt;p&gt;Another interesting possibility is using a decorator for logging the output of any function. Check this out:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;logger &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f, filename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &apos;log&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&apos;) {   wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      # Before execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nothing      res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; After&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      write(res, file &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; filename, append &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s apply it, for instance, to the power function:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logger(pow)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and it will log the value &lt;code&gt;8&lt;/code&gt; in the default file &lt;code&gt;log.txt&lt;/code&gt;. A non-default log filename can be passed via:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; logger(pow, filename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;otherlog.txt&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;what-about-syntactic-sugar&quot;&gt;What about syntactic sugar?&lt;/h2&gt;
&lt;p&gt;Certainly one of the secrets to the success of decorators in Python is that they look really neat. Instead of something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# In Pythonf_dec = decorator(f)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can use syntactic sugar to apply the decorator from the moment the function is defined:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# In Python@decorator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;def f(args)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function body&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is it possible to do something similar in R? The answer is yes. And all of it thanks to the &lt;a href=&quot;https://cran.r-project.org/web/packages/tinsel/index.html&quot;&gt;tinsel&lt;/a&gt; package. As usual, the first step is to install and load it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;packages(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;tinsel&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(tinsel)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, if we want to apply, say, our &lt;code&gt;timer&lt;/code&gt; decorator to a brand-new defined function, we’ll use the special comment &lt;code&gt;#. timer&lt;/code&gt; on top of the definition. This would be equivalent to the syntactic sugar &lt;code&gt;@timer&lt;/code&gt; in Python.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;#. timer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;say_hi &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(name) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   return(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hi&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, name, sep &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot; &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order to make it work, we have to source the file with a special source function contained in the tinsel package:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source_decoratees(&apos;filename&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;R&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we are ready to try it:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; say_hi(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Pablo&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ini time: 2021-07-29 10:29:27.364677&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;End time: 2021-07-29 10:29:27.366081&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hi Pablo&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes… this syntactic sugar is (still) not so amazing as that of Python, but still quite remarkable.&lt;/p&gt;
&lt;h2 id=&quot;a-real-world-problem&quot;&gt;A real-world problem&lt;/h2&gt;
&lt;p&gt;Wait a minute… is this useful at all? I mean, in real-world problems?&lt;/p&gt;
&lt;p&gt;Let me tell you a story. Not long ago, I had to refactor some code that I hadn’t written myself. I cannot imagine a more real-world task than that… and decorators made my life much easier.&lt;/p&gt;
&lt;p&gt;Long story short, the code contained several one-liners that did too much. Particularly, the command &lt;code&gt;system&lt;/code&gt; was used to execute very long instructions that were constructed by pasting pieces of strings. Something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;system(paste(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;command1 &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;--parameter &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;command 2 &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, as&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;character(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1250&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot; more_commands &quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), intern &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ignore&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;stdout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each line differed in the size and composition of the pasted string. In order to refactor this, and to make it more readable, the first thing I needed to know was the exact content of those complicated strings. There were lots of them, and I didn’t want to manually extract them from inside &lt;code&gt;system&lt;/code&gt;. Luckily for me, the pasted string was passed always as the first argument to the &lt;code&gt;system&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;So I wrote a decorator that logs the first argument of anything, and it saved my day:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;log1starg &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(f, filename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &apos;loginput&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&apos;) {  wrapper &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(x, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      # Before execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      write(x, file &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; filename, append &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; TRUE&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Log&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the 1st arg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      res &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; f(x, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)      &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; After&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; execution&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; nothing      return(res)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  return(wrapper)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, I only had to find all the appearances of &lt;code&gt;system&lt;/code&gt; and substitute them by &lt;code&gt;log1starg(system)&lt;/code&gt;. After that, just run the script from beginning to the end, and open the freshly created &lt;code&gt;loginput.txt&lt;/code&gt; file containing all the information I needed.&lt;/p&gt;
&lt;h2 id=&quot;what-about-you&quot;&gt;What about you?&lt;/h2&gt;
&lt;p&gt;Can you think of another use for decorators? Please feel free to leave a comment below!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I want to express my gratitude to &lt;a href=&quot;https://medium.com/u/1382ec3ac71f?source=post_page---user_mention--ec84eaeca3e3---------------------------------------&quot;&gt;Patrick Bos&lt;/a&gt; for his useful suggestions.&lt;/p&gt;
&lt;p&gt;This entry appears in &lt;a href=&quot;https://r-bloggers.com/&quot;&gt;R-bloggers.com&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_ciWjhFQWICOV9SmeFsMuWg-594f2a3b.BLSn3eAg.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Pandemic-proof: shaping the future of scientific exchange</title><link>https://blog2.esciencecenter.nl/posts/2021-09-21---pandemic-proof-shaping-the-future-of-scientific-exchange</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-09-21---pandemic-proof-shaping-the-future-of-scientific-exchange</guid><description>&lt;p&gt;The 2021 (virtual) meeting of the &lt;a href=&quot;https://www.emetsoc.org/&quot;&gt;European Meteorological Society&lt;/a&gt; started off with the collaborative Future Science Cafe. Inspired by the rapid developments in remote collaboration forced upon us by the COVID-19 pandemic, we reflected on the sustainability of everyday academic practices, and imagined what a future world might look like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;907&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_35Fq6kF4xD76Z2aHlSNsXA-3a846000.7RnXy5WL_29TclG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Visual summary of the future science cafe by Szilard Strenner (grafacity.eu)&lt;/p&gt;
&lt;p&gt;Some of the advantages and drawbacks were quite obvious. Advantages are for example, saving on travel and lower barriers for remote collaboration. The biggest disadvantages were experiences in the social spheres, with disturbed work-life balance and isolation. Notably, new colleagues suffered from a lack of proper introduction.&lt;/p&gt;
&lt;p&gt;Several new ideas and insights came up as well. For example, online lectures sometimes led to increased participation by students. And instead of hybrid conferences, perhaps it is more productive to consider hybrid audiences, since the interest of a remote audience is often not served by the traditional conference format and vice versa.&lt;/p&gt;
&lt;p&gt;The event was held in gather.town, where five whiteboards were set up in a virtual room. Each whiteboard was tied to a topic. In two rounds, participants gathered around the whiteboards and discussed the corresponding topics. Afterwards, the moderators wrote a short summary on each of the topics.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1248&quot; height=&quot;640&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_s3Tc_gqR9wuUKXPQegGcAQ-5e9c899c.CqYMTdk0_WVwoA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Layout of the virtual discussion space&lt;/p&gt;
&lt;h3 id=&quot;online-education&quot;&gt;Online education&lt;/h3&gt;
&lt;p&gt;For 1.5 years, education at universities has been mostly online, partly on-campus or in a hybrid format. In this session we reflected on the opportunities that arose due to this quick transformation, but also on the aspects that were really missed.&lt;/p&gt;
&lt;p&gt;A big benefit of online education is the accessibility for everyone. Students can log in from their parents’ place, home country, or student room. At Met Offices (such as DWD), digital education means that people do not have to travel all across the country, and can easily chime in for a particular session.&lt;/p&gt;
&lt;p&gt;It differs per teaching format if online alternatives are suitable. Lectures work pretty well; if students can pose questions in a chat, it can be even more interactive than in a classroom. Sharing screens is also very useful during practical sessions. However, we miss seeing the faces during classes. Are students bored? Can they follow you? This is what you would notice directly in a live classroom, but you do not see when everyone has their camera turned off and you are in presenting mode.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;436&quot; height=&quot;182&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__vGw0PjOBM0547M5rSgoYQ-adf481e9.DOhUkr9o_ZNmFI2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Teaching from home also revealed the large social component of on-campus education, which is difficult to create online. Going to university is about meeting your fellow students, having an informal chat with the teacher during a break to discuss which courses to follow next, or to ask one more question on the content. During tutorials, students like to check their answer with the neighbour to see if they are on the right track. While tools such as gather.town or spatial.chat can provide some of these informal coffee-moments, it remains a challenge to have informal chats with students in an online setting.&lt;/p&gt;
&lt;p&gt;How to move forward as teaching (in the Netherlands at least) is moving ‘back-to-normal’? As much online content is created in the past year, it would be a waste to not benefit from it. However, it is scary to put your material in the great-wide-open (YouTube), especially when you have been recording yourself in home-office settings etc. Nevertheless, the digital content can be used internally in a “flip the classroom” principle, where students study the content in their own time and come to campus for Q&amp;#x26;A sessions with the teacher, and to make exercises with fellow students. In this way you re-use the material from last year, and create the social activities on-campus.&lt;/p&gt;
&lt;h3 id=&quot;boosted-collaboration&quot;&gt;Boosted collaboration&lt;/h3&gt;
&lt;p&gt;The pandemic forced us into online collaboration. While everyone is happy to be able to meet in person again, (know-how of) online possibilities has increased a lot, and maybe it’s here to stay. In the boosted collaboration session, we discussed about the positive and negative aspects of the new online-working regime in terms of collaboration, work efficiency, and work-life balance.&lt;/p&gt;
&lt;p&gt;In terms of work environment collaboration, the ability to attend meetings online from different locations has increased meeting flexibility and allowed more people to participate in meetings. The lack of need for a physical meeting space also contributes to increased participation in meetings. In addition, since most of the people are now easily connected through online discussion/working software (i.e. slack), it is much easier to set up quick discussion groups.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;466&quot; height=&quot;224&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lrNKuRGqb2iIzqzRZ52VXQ-e28c55f4.Bp_2pvH9_18MhO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One of the participants noted that the online working environment has made it easier and faster to address problems and emergency situations while working from home, because people no longer need to spend the time to commute to the office to deal with the emergency. However, this flexibility can create issues with work-life balance, as people are more likely to work outside the normal working hours. This can result in increased work-related communication throughout the day, which can increase work-related stress. This effect is partly counteracted by the reduced time spend in commuting, which can increase work efficiency and reduce the stress and delays associated with commuting from home to the office and vice versa.&lt;/p&gt;
&lt;p&gt;As noted by all the participants the online working environments has created problems for newer colleagues, who do not have an existing collaboration network in place. They find it more difficult to find and communicate with other colleagues as they are often not in the office, where it is easier to spontaneously meet and discuss during coffee or lunch break. This can inhibit both the development of an early career scientist’s collaboration network and the knowledge transfer from the older more experienced colleagues to the younger ones.&lt;/p&gt;
&lt;p&gt;In general, it seems that the additional opportunities to collaborate and work online is a double-edged sword. The benefits are clear, but so are the drawbacks, which need to be addressed to allow the online collaboration opportunities to flourish.&lt;/p&gt;
&lt;h3 id=&quot;meteorology-vs-global-crisis&quot;&gt;Meteorology vs global crisis&lt;/h3&gt;
&lt;p&gt;Throughout the COVID-19 pandemic, epidemiologists, virologists, and vaccine developers have received both high esteem and lots of criticism. What can we, as meteorologists, learn from the pandemic? We discussed the role of meteorology in crisis response, and especially what our strong points are that we could share with other disciplines and governments.&lt;/p&gt;
&lt;p&gt;Meteorology is an old discipline — we have literally centuries of experience in measuring and researching the atmosphere. The comment was made that “exchange and cooperation are in our DNA”: from sharing crucial data over slow mediums such as telegraphs in earlier times, to the current rapid share of millions of data points and models through the internet. Exchange of data is normal and expected within meteorology, but might not be as natural for other disciplines (where there might be a certain economical competition for instance). For crisis response, timely sharing of information is crucial, like sharing satellite imagery to emergency services, or outcomes of a model for flooding problems, for instance. In a similar fashion, interdisciplinary is also an important aspect for crisis response that we have plenty of experience with: the current meteorological models started as pure atmospheres, then improved with ocean, biosphere, chemistry etc, all bringing in experts from those fields.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;406&quot; height=&quot;230&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-D8cF_Q_gkz4CyvbmmB0Bw-f35bcfd9.tfIGfFka_ZIM4MF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A drawback is that other disciplines (mostly outside of the environmental sciences) can often make use of third-party investments for innovations. Since there is not a whole lot of immediate profit to be gained in meteorology, it often takes a disaster to kickstart (national) investments in early warning systems or climate-proofing cities etc (think of the recent European floods). Perhaps such disasters are needed to kickstart cooperation between parties as well, have everyone around the same table, even though ideally we’d like to prevent situations like that.&lt;/p&gt;
&lt;p&gt;More cooperation with policy makers and urban planners is needed to prevent future (urban) disasters: the world is urbanizing and anything that happens in a city can impact thousands of people. Any new urban structuring should involve some form of climate expert to deal with expected climate change and reduce climate risks.&lt;/p&gt;
&lt;h3 id=&quot;new-office-concepts&quot;&gt;New office concepts&lt;/h3&gt;
&lt;p&gt;With the pandemic, home office work places became a standard to millions of office workers. The experience quickly revealed that a combination of working from home and working at the employer’s building is preferred by many. This reduces the space required in office buildings, making room for new office concepts and workflows. Skipping the commute also saves time and CO2.&lt;/p&gt;
&lt;p&gt;Participants suggested that a 50/50 distribution between office and home office is effective and comfortable. While some people value privacy in their office and a quiet workplace, the social function of office space was missed most in home office — and was only partly replaced by online coffee breaks, depending on the digital skills and flexibility of colleagues.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;280&quot; height=&quot;339&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_a50t-ybZ_6G4hCv1YB4kqQ-68de0091.DAGfM_MV_Z1Tv0rJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Most impressive, though, was the “lostness” of new colleagues not properly meeting their other colleagues — and not being properly introduced to them digitally instead. Executive personnel forgot that this introduction doesn’t happen naturally in the halls between the offices anymore. A virtual office twin like we had in gather-town or on similar platforms like spatial.chat could provide a place to hang out and be available for colleagues if necessary, without being in formal video conferences all the time.&lt;/p&gt;
&lt;p&gt;The new office concept at Deutscher Wetterdienst (DWD) was generally met with positive interest. It is optimized for a hybrid concept of office and home office, with bookable offices, and more and flexible meeting spaces (large kitchen, large and small offices, more meeting rooms in smaller sizes). While some people prefer their own classic office space, most people could imagine booking offices flexibly upon needs and stowing their personal things in a rolling office container.&lt;/p&gt;
&lt;h3 id=&quot;hybrid-conferences&quot;&gt;Hybrid conferences&lt;/h3&gt;
&lt;p&gt;After more than a year of virtual conferences, scientists are looking forward to meeting in person again. But we have also seen (and to some extent, grown accustomed to) the advantages of online meetings and conferences. How can we get the best of both worlds?&lt;/p&gt;
&lt;p&gt;We discussed advantages and disadvantages of both on-site and virtual conferences. Interestingly, most advantages also translated into drawbacks. For example, participants generally appreciated the increased accessibility of an online conference, but they disliked the reduced commitment from participants. Similarly, they were happy with the reduced travel, but they missed seeing new places and tasting new beers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;304&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v8Pg3mYaNxy_w8Ar1tEIHQ-dd8e69da._RyDQN3Q_Z1rV1ig.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It thus appears that a hybrid conference as a “somewhere-in-between” will not be able to meet the needs of all participants. Instead, it might be more effective to target different types of audiences with the on-site and online components: the on-site meeting will then be optimized for dedication, whereas the online counterpart will accommodate broad but occasional, perhaps even asynchronous, accessibility.&lt;/p&gt;
&lt;p&gt;While there are examples where hybrid conferences work very well (think TED), this puts an additional burden on the organizers, “as if you’re organizing two events instead of one”. Perhaps a more gradual transition would enable us to build up experience while keeping things manageable. We could start, for example, by streaming only the keynotes, and making recordings available after the event.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The COVID-19 pandemic triggered a sudden overhaul in our daily routines. Evidently, change is often triggered or accelerated by emergencies, even if the precursors might have been lingering around for some time already.&lt;/p&gt;
&lt;p&gt;The future science cafe was an opportunity to reflect on the status quo and take agency of where we are headed as a field. This year’s theme was mostly around remote collaboration in one way or another. But there are more meta-topics that would make for an interesting future science cafe. Think of open science, reviewing procedures, academic career paths, et cetera.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;335&quot; height=&quot;182&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UTFCxgBjf9H4C5jDRBaqCA-8631ad38.DgLZJmvj_10a7JC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The annual meeting of the EMS seems to be a good place for such contemplations, and we are thinking about making this a recurring event. So thanks to all participants, and hope to see you next year!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Imme Benedict, Arjan Droste, Hella Riede, and Aristofanis Tsiringakis for moderating the discussions and to Szilard Strenner (grafacity.eu) for the visual impression.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Tue, 21 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The 2021 (virtual) meeting of the &lt;a href=&quot;https://www.emetsoc.org/&quot;&gt;European Meteorological Society&lt;/a&gt; started off with the collaborative Future Science Cafe. Inspired by the rapid developments in remote collaboration forced upon us by the COVID-19 pandemic, we reflected on the sustainability of everyday academic practices, and imagined what a future world might look like.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;907&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_35Fq6kF4xD76Z2aHlSNsXA-3a846000.7RnXy5WL_29TclG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Visual summary of the future science cafe by Szilard Strenner (grafacity.eu)&lt;/p&gt;
&lt;p&gt;Some of the advantages and drawbacks were quite obvious. Advantages are for example, saving on travel and lower barriers for remote collaboration. The biggest disadvantages were experiences in the social spheres, with disturbed work-life balance and isolation. Notably, new colleagues suffered from a lack of proper introduction.&lt;/p&gt;
&lt;p&gt;Several new ideas and insights came up as well. For example, online lectures sometimes led to increased participation by students. And instead of hybrid conferences, perhaps it is more productive to consider hybrid audiences, since the interest of a remote audience is often not served by the traditional conference format and vice versa.&lt;/p&gt;
&lt;p&gt;The event was held in gather.town, where five whiteboards were set up in a virtual room. Each whiteboard was tied to a topic. In two rounds, participants gathered around the whiteboards and discussed the corresponding topics. Afterwards, the moderators wrote a short summary on each of the topics.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1248&quot; height=&quot;640&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_s3Tc_gqR9wuUKXPQegGcAQ-5e9c899c.CqYMTdk0_WVwoA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Layout of the virtual discussion space&lt;/p&gt;
&lt;h3 id=&quot;online-education&quot;&gt;Online education&lt;/h3&gt;
&lt;p&gt;For 1.5 years, education at universities has been mostly online, partly on-campus or in a hybrid format. In this session we reflected on the opportunities that arose due to this quick transformation, but also on the aspects that were really missed.&lt;/p&gt;
&lt;p&gt;A big benefit of online education is the accessibility for everyone. Students can log in from their parents’ place, home country, or student room. At Met Offices (such as DWD), digital education means that people do not have to travel all across the country, and can easily chime in for a particular session.&lt;/p&gt;
&lt;p&gt;It differs per teaching format if online alternatives are suitable. Lectures work pretty well; if students can pose questions in a chat, it can be even more interactive than in a classroom. Sharing screens is also very useful during practical sessions. However, we miss seeing the faces during classes. Are students bored? Can they follow you? This is what you would notice directly in a live classroom, but you do not see when everyone has their camera turned off and you are in presenting mode.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;436&quot; height=&quot;182&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__vGw0PjOBM0547M5rSgoYQ-adf481e9.DOhUkr9o_ZNmFI2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Teaching from home also revealed the large social component of on-campus education, which is difficult to create online. Going to university is about meeting your fellow students, having an informal chat with the teacher during a break to discuss which courses to follow next, or to ask one more question on the content. During tutorials, students like to check their answer with the neighbour to see if they are on the right track. While tools such as gather.town or spatial.chat can provide some of these informal coffee-moments, it remains a challenge to have informal chats with students in an online setting.&lt;/p&gt;
&lt;p&gt;How to move forward as teaching (in the Netherlands at least) is moving ‘back-to-normal’? As much online content is created in the past year, it would be a waste to not benefit from it. However, it is scary to put your material in the great-wide-open (YouTube), especially when you have been recording yourself in home-office settings etc. Nevertheless, the digital content can be used internally in a “flip the classroom” principle, where students study the content in their own time and come to campus for Q&amp;#x26;A sessions with the teacher, and to make exercises with fellow students. In this way you re-use the material from last year, and create the social activities on-campus.&lt;/p&gt;
&lt;h3 id=&quot;boosted-collaboration&quot;&gt;Boosted collaboration&lt;/h3&gt;
&lt;p&gt;The pandemic forced us into online collaboration. While everyone is happy to be able to meet in person again, (know-how of) online possibilities has increased a lot, and maybe it’s here to stay. In the boosted collaboration session, we discussed about the positive and negative aspects of the new online-working regime in terms of collaboration, work efficiency, and work-life balance.&lt;/p&gt;
&lt;p&gt;In terms of work environment collaboration, the ability to attend meetings online from different locations has increased meeting flexibility and allowed more people to participate in meetings. The lack of need for a physical meeting space also contributes to increased participation in meetings. In addition, since most of the people are now easily connected through online discussion/working software (i.e. slack), it is much easier to set up quick discussion groups.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;466&quot; height=&quot;224&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lrNKuRGqb2iIzqzRZ52VXQ-e28c55f4.Bp_2pvH9_18MhO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One of the participants noted that the online working environment has made it easier and faster to address problems and emergency situations while working from home, because people no longer need to spend the time to commute to the office to deal with the emergency. However, this flexibility can create issues with work-life balance, as people are more likely to work outside the normal working hours. This can result in increased work-related communication throughout the day, which can increase work-related stress. This effect is partly counteracted by the reduced time spend in commuting, which can increase work efficiency and reduce the stress and delays associated with commuting from home to the office and vice versa.&lt;/p&gt;
&lt;p&gt;As noted by all the participants the online working environments has created problems for newer colleagues, who do not have an existing collaboration network in place. They find it more difficult to find and communicate with other colleagues as they are often not in the office, where it is easier to spontaneously meet and discuss during coffee or lunch break. This can inhibit both the development of an early career scientist’s collaboration network and the knowledge transfer from the older more experienced colleagues to the younger ones.&lt;/p&gt;
&lt;p&gt;In general, it seems that the additional opportunities to collaborate and work online is a double-edged sword. The benefits are clear, but so are the drawbacks, which need to be addressed to allow the online collaboration opportunities to flourish.&lt;/p&gt;
&lt;h3 id=&quot;meteorology-vs-global-crisis&quot;&gt;Meteorology vs global crisis&lt;/h3&gt;
&lt;p&gt;Throughout the COVID-19 pandemic, epidemiologists, virologists, and vaccine developers have received both high esteem and lots of criticism. What can we, as meteorologists, learn from the pandemic? We discussed the role of meteorology in crisis response, and especially what our strong points are that we could share with other disciplines and governments.&lt;/p&gt;
&lt;p&gt;Meteorology is an old discipline — we have literally centuries of experience in measuring and researching the atmosphere. The comment was made that “exchange and cooperation are in our DNA”: from sharing crucial data over slow mediums such as telegraphs in earlier times, to the current rapid share of millions of data points and models through the internet. Exchange of data is normal and expected within meteorology, but might not be as natural for other disciplines (where there might be a certain economical competition for instance). For crisis response, timely sharing of information is crucial, like sharing satellite imagery to emergency services, or outcomes of a model for flooding problems, for instance. In a similar fashion, interdisciplinary is also an important aspect for crisis response that we have plenty of experience with: the current meteorological models started as pure atmospheres, then improved with ocean, biosphere, chemistry etc, all bringing in experts from those fields.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;406&quot; height=&quot;230&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-D8cF_Q_gkz4CyvbmmB0Bw-f35bcfd9.tfIGfFka_ZIM4MF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A drawback is that other disciplines (mostly outside of the environmental sciences) can often make use of third-party investments for innovations. Since there is not a whole lot of immediate profit to be gained in meteorology, it often takes a disaster to kickstart (national) investments in early warning systems or climate-proofing cities etc (think of the recent European floods). Perhaps such disasters are needed to kickstart cooperation between parties as well, have everyone around the same table, even though ideally we’d like to prevent situations like that.&lt;/p&gt;
&lt;p&gt;More cooperation with policy makers and urban planners is needed to prevent future (urban) disasters: the world is urbanizing and anything that happens in a city can impact thousands of people. Any new urban structuring should involve some form of climate expert to deal with expected climate change and reduce climate risks.&lt;/p&gt;
&lt;h3 id=&quot;new-office-concepts&quot;&gt;New office concepts&lt;/h3&gt;
&lt;p&gt;With the pandemic, home office work places became a standard to millions of office workers. The experience quickly revealed that a combination of working from home and working at the employer’s building is preferred by many. This reduces the space required in office buildings, making room for new office concepts and workflows. Skipping the commute also saves time and CO2.&lt;/p&gt;
&lt;p&gt;Participants suggested that a 50/50 distribution between office and home office is effective and comfortable. While some people value privacy in their office and a quiet workplace, the social function of office space was missed most in home office — and was only partly replaced by online coffee breaks, depending on the digital skills and flexibility of colleagues.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;280&quot; height=&quot;339&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_a50t-ybZ_6G4hCv1YB4kqQ-68de0091.DAGfM_MV_Z1Tv0rJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Most impressive, though, was the “lostness” of new colleagues not properly meeting their other colleagues — and not being properly introduced to them digitally instead. Executive personnel forgot that this introduction doesn’t happen naturally in the halls between the offices anymore. A virtual office twin like we had in gather-town or on similar platforms like spatial.chat could provide a place to hang out and be available for colleagues if necessary, without being in formal video conferences all the time.&lt;/p&gt;
&lt;p&gt;The new office concept at Deutscher Wetterdienst (DWD) was generally met with positive interest. It is optimized for a hybrid concept of office and home office, with bookable offices, and more and flexible meeting spaces (large kitchen, large and small offices, more meeting rooms in smaller sizes). While some people prefer their own classic office space, most people could imagine booking offices flexibly upon needs and stowing their personal things in a rolling office container.&lt;/p&gt;
&lt;h3 id=&quot;hybrid-conferences&quot;&gt;Hybrid conferences&lt;/h3&gt;
&lt;p&gt;After more than a year of virtual conferences, scientists are looking forward to meeting in person again. But we have also seen (and to some extent, grown accustomed to) the advantages of online meetings and conferences. How can we get the best of both worlds?&lt;/p&gt;
&lt;p&gt;We discussed advantages and disadvantages of both on-site and virtual conferences. Interestingly, most advantages also translated into drawbacks. For example, participants generally appreciated the increased accessibility of an online conference, but they disliked the reduced commitment from participants. Similarly, they were happy with the reduced travel, but they missed seeing new places and tasting new beers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;304&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v8Pg3mYaNxy_w8Ar1tEIHQ-dd8e69da._RyDQN3Q_Z1rV1ig.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It thus appears that a hybrid conference as a “somewhere-in-between” will not be able to meet the needs of all participants. Instead, it might be more effective to target different types of audiences with the on-site and online components: the on-site meeting will then be optimized for dedication, whereas the online counterpart will accommodate broad but occasional, perhaps even asynchronous, accessibility.&lt;/p&gt;
&lt;p&gt;While there are examples where hybrid conferences work very well (think TED), this puts an additional burden on the organizers, “as if you’re organizing two events instead of one”. Perhaps a more gradual transition would enable us to build up experience while keeping things manageable. We could start, for example, by streaming only the keynotes, and making recordings available after the event.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The COVID-19 pandemic triggered a sudden overhaul in our daily routines. Evidently, change is often triggered or accelerated by emergencies, even if the precursors might have been lingering around for some time already.&lt;/p&gt;
&lt;p&gt;The future science cafe was an opportunity to reflect on the status quo and take agency of where we are headed as a field. This year’s theme was mostly around remote collaboration in one way or another. But there are more meta-topics that would make for an interesting future science cafe. Think of open science, reviewing procedures, academic career paths, et cetera.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;335&quot; height=&quot;182&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UTFCxgBjf9H4C5jDRBaqCA-8631ad38.DgLZJmvj_10a7JC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The annual meeting of the EMS seems to be a good place for such contemplations, and we are thinking about making this a recurring event. So thanks to all participants, and hope to see you next year!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Imme Benedict, Arjan Droste, Hella Riede, and Aristofanis Tsiringakis for moderating the discussions and to Szilard Strenner (grafacity.eu) for the visual impression.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_35Fq6kF4xD76Z2aHlSNsXA-3a846000.7RnXy5WL.jpeg" medium="image"/><author>Peter Kalverla</author></item><item><title>Plotting gridded data on a web map: Python and/or Javascript?</title><link>https://blog2.esciencecenter.nl/posts/2021-09-20---plotting-gridded-data-on-a-web-map-python-andor-javascript</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-09-20---plotting-gridded-data-on-a-web-map-python-andor-javascript</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;But what if you want to plot your own data? While there are many resources on how to use existing tile or web-map services, I struggled to find out how to make my own. Eventually, I found a &lt;a href=&quot;https://www.azavea.com/blog/2018/08/06/generating-pyramided-tiles-from-a-geotiff-using-geotrellis/&quot;&gt;nice example&lt;/a&gt; using &lt;a href=&quot;https://geotrellis.readthedocs.io/en/latest/&quot;&gt;GeoTrellis&lt;/a&gt;, but by that time I had already concocted a half-baked solution in my beloved Python. More on that in a bit.&lt;/p&gt;
&lt;p&gt;Leaflet also has different kinds of layers. You can draw lines, markers, shapes, polygons, images, and even videos. Here’s how to draw a simple rectangle on a Leaflet map:&lt;/p&gt;
&lt;p&gt;var bounds = [[50, 0], [55, 5]]  // ymin xmin ymax xmax
L.rectangle(bounds, {color: “#ffffff”, weight: 1}).addTo(map);So if I could load my data into some that bounds array and write a function to determine the colours, that should work. Right?&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&quot;https://blog.scottlogic.com/2020/05/01/rendering-one-million-points-with-d3.html&quot;&gt;this blogpost&lt;/a&gt;, Leaflet should perform well up to about ten thousand data points. However, gridded data can easily get bigger. The snapshot of ERA5 data that I used for the first example already has over a million grid cells (0.25 by 0.25 degrees, global coverage). So it seems we’re hitting a dead end there as well… Or not?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://deck.gl/&quot;&gt;deck.gl&lt;/a&gt; is like Leaflet on steroids. It was designed to “visually explore large-scale datasets”. It leverages the processing power of your graphics card to do some impressive rendering magic. After using Leaflet, I found it quite easy to get up and running with deck.gl, and managed to produce this awesome visualization:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Plotting gridded data on a web map: Python and/or Javascript?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;612&quot; height=&quot;432&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-7102366f.CCo91M-J_WnkMk.webp&quot; srcset=&quot;&quot;&gt;
Rendering over a million grid cells using deck.glBut still, I had to cheat a bit. And still, it was slow. For the data… was big.&lt;/p&gt;
&lt;h2 id=&quot;incentives-for-a-hybrid-solution&quot;&gt;Incentives for a hybrid solution&lt;/h2&gt;
&lt;p&gt;The data I wanted to use came originally in netCDF format and while it seems possible* nowadays to parse that with Javascript, it’s not the oneliner I’m used to in Python. The same goes for the colour mapping. To save me some time, I decided to do some light preprocessing in Python.&lt;/p&gt;
&lt;p&gt;Next, let’s talk about data sizes. The size of the original netCDF data for one timestamp was about 4 MB. The size of the preprocessed data in JSON format was considerably larger: almost 50 MB. For climate scientists this is nothing, but for smoothly running a website that’s quite substantial… It might be worthwhile to explore which file formats work well for both languages.&lt;/p&gt;
&lt;p&gt;So what about the tile solutions from earlier? Could that save me some bandwidth and rendering time? And how hard could it be to make my own tiles in Python? As you could see from the first Leaflet example, it’s just a matter of creating a folder structure like &lt;code&gt;baseurl/{z}/{x}/{y}.png&lt;/code&gt;, where the tile numbering follows the slippy tile format explained &lt;a href=&quot;https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Plotting gridded data on a web map: Python and/or Javascript?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;224&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-c3fb61ab.CgVRjSqu_ZI443P.webp&quot; srcset=&quot;&quot;&gt;
Example tiles at zoom levels 0 (left), 1 (middles) and 2 (right).To draw a tile we basically have to determine the right colour for each pixel. I already mentioned that the tiles are 256x256 pixels. My sample data is 1440x721 grid cells. Therefore, to create the first tile that covers the globe, we need to condense, or &lt;em&gt;aggregate&lt;/em&gt;, the data. We have 5 to 6 grid cells per pixel in the &lt;em&gt;x&lt;/em&gt;-direction and about 3 in the &lt;em&gt;y&lt;/em&gt;-direction. The simplest way to aggregate them would be to take the mean of these ~15 grid cells. (At higher zoom levels, where we have more pixels than grid cells, we’d need to upsample, or *interpolate *instead). Then we’d have to map the values of temperature onto a colour scale. Finally, we’d draw the pixels on a canvas.&lt;/p&gt;
&lt;p&gt;There happens to be a Python library that is built to do exactly this: &lt;a href=&quot;https://datashader.org/&quot;&gt;Datashader&lt;/a&gt;. While it’s intended for use from within a Python session, there is no reason why you couldn’t use that library to render images upfront. The developers of the package also &lt;a href=&quot;https://github.com/holoviz/datashader/issues/246&quot;&gt;realized this&lt;/a&gt; and created an initial implementation to render tiles with a somewhat hidden &lt;a href=&quot;https://github.com/holoviz/datashader/blob/master/examples/tiling.ipynb&quot;&gt;example notebook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I adapted the example to my needs and started rendering some tiles. In terms of storage, the first 4 zoom levels (0 to 3) were all below 1 MB. Then it quickly went up from 2.4 MB to 6.8 MB to 22 MB for levels 4 through 6. Performance started to degrade at zoom level 6, perhaps because of the upsampling that was going on. At zoom level 7, my code crashed, though I’m sure it can still be optimized.&lt;/p&gt;
&lt;p&gt;Now it was time to show my awesome tile layer on a Leaflet map. I struggled a bit to get the projection right, but eventually, it worked like a charm (select the tile layer on the leaflet map &lt;a href=&quot;https://peter9192.github.io/webmaps/&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Plotting gridded data on a web map: Python and/or Javascript?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;688&quot; height=&quot;469&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-a8fb1070.BqhSHahB_gq65k.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://xkcd.com/2256&quot;&gt;https://xkcd.com/2256&lt;/a&gt;I was happy that my tile layer worked, but it also got me thinking: zoom level 0 seemed quite redundant: why would anyone want to show the whole globe on a tiny thumbnail? The tile layer only starts to be advantageous at the higher zoom levels. But do I really need that? Indeed, with the source data resolution of 0.25 degrees, there might not be much to gain beyond zoom level 3. Consequently, for a global dataset at this resolution, an image overlay might be a better, and easier, solution.&lt;/p&gt;
&lt;p&gt;After tinkering a bit with how to reproject and save the file, I managed to create an image with just as many pixels as I had grid cells, and project it onto my Leaflet map (select the image layer &lt;a href=&quot;https://peter9192.github.io/webmaps/&quot;&gt;here&lt;/a&gt;). The image size was under 400 KB and it rendered nicely onto the map. Maybe even too nicely: at higher zoom levels, Leaflet did a great job at smoothing the edges between the original pixels, and although this provided a nice looking image, I did not like it. For scientific applications, it is more honest to show the coarse pixels of the source data. In that sense, the polygon solution was much better.&lt;/p&gt;
&lt;h2 id=&quot;not-so-bad-after-all&quot;&gt;Not so bad after all?&lt;/h2&gt;
&lt;p&gt;So let’s do a quick resume. To plot data on a web map, we have several options. For relatively coarse datasets, creating an image overlay seems to be a good option, although you might lose the explicit granularity of the source data. Tile layers will be useful mostly when you go to a much higher resolution (whilst keeping a large domain). Both these options require pre-rendering of the images/tiles, which means that the colour bar will be fixed and the connection with the source data is lost.&lt;/p&gt;
&lt;p&gt;Alternatively, rendering the data client-side is also within reach, especially with tools like deck.gl. In my experiments, it required fetching and processing substantial amounts of data, but this can be amended. Similar to the pre-rendered raster tiles I’ve explored, &lt;a href=&quot;https://en.wikipedia.org/wiki/Vector_tiles&quot;&gt;vector tiles&lt;/a&gt; have become increasingly popular. This could be a good solution when you have (much) more pixels than grid cells, whereas raster tiles work well in the opposite situation. The preferred option is thus determined by the source data resolution, and the zoom levels you want to support.&lt;/p&gt;
&lt;p&gt;Finally, let’s look back at the very first figure I showed. It was made with the &lt;a href=&quot;https://hvplot.holoviz.org/&quot;&gt;hvPlot&lt;/a&gt; library, which is built on top of &lt;a href=&quot;https://holoviews.org/&quot;&gt;HoloViews&lt;/a&gt;, which in turn uses &lt;a href=&quot;https://docs.bokeh.org/en/latest/&quot;&gt;Bokeh&lt;/a&gt;. I also used &lt;a href=&quot;https://panel.holoviz.org/index.html&quot;&gt;Panel&lt;/a&gt; for exporting the file. Bokeh consists of two components: BokehJS for creating interactive visualizations with Javascript, and the Python library, which makes it easy to ‘define’ visualizations that are understood by the Javascript counterpart. Simply put, these &lt;em&gt;definitions&lt;/em&gt; are just listings of the different plot elements that constitute the visualization. When you export a visualization as a static file, all possible ‘states’ (in my case the four seasons) are written to the output file(s), alongside the definition. Depending on the plot type, the state may consist of some data, or perhaps an encoded image. At that point, BokehJS can read the definition and state data and reconstruct the visualization.&lt;/p&gt;
&lt;p&gt;It is a great solution if you are happy with the possibilities offered by Bokeh and the libraries that are built on top of it. Personally, I’m not so keen on the “you worry about the science, we worry about the implementation” attitude that some of the high-level visualization packages sometimes tend to preach. I think it’s important to have a basic understanding of what’s going on under the hood. And while the BokehJS library seems to be quite good at what it does, I’d like it even better when the exchange formats between Python and Javascript were more interoperable.&lt;/p&gt;
&lt;p&gt;Anyway, now that I’m starting to grasp the core principles and challenges, I’ve come to appreciate how far they have come, and I look forward to seeing how this exciting visualization landscape will develop in the near future. This exploration has been a valuable learning experience for me, and I hope it may help some of the readers as well.&lt;/p&gt;
&lt;p&gt;Happy mapping!&lt;/p&gt;</description><pubDate>Mon, 20 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;But what if you want to plot your own data? While there are many resources on how to use existing tile or web-map services, I struggled to find out how to make my own. Eventually, I found a &lt;a href=&quot;https://www.azavea.com/blog/2018/08/06/generating-pyramided-tiles-from-a-geotiff-using-geotrellis/&quot;&gt;nice example&lt;/a&gt; using &lt;a href=&quot;https://geotrellis.readthedocs.io/en/latest/&quot;&gt;GeoTrellis&lt;/a&gt;, but by that time I had already concocted a half-baked solution in my beloved Python. More on that in a bit.&lt;/p&gt;
&lt;p&gt;Leaflet also has different kinds of layers. You can draw lines, markers, shapes, polygons, images, and even videos. Here’s how to draw a simple rectangle on a Leaflet map:&lt;/p&gt;
&lt;p&gt;var bounds = [[50, 0], [55, 5]]  // ymin xmin ymax xmax
L.rectangle(bounds, {color: “#ffffff”, weight: 1}).addTo(map);So if I could load my data into some that bounds array and write a function to determine the colours, that should work. Right?&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&quot;https://blog.scottlogic.com/2020/05/01/rendering-one-million-points-with-d3.html&quot;&gt;this blogpost&lt;/a&gt;, Leaflet should perform well up to about ten thousand data points. However, gridded data can easily get bigger. The snapshot of ERA5 data that I used for the first example already has over a million grid cells (0.25 by 0.25 degrees, global coverage). So it seems we’re hitting a dead end there as well… Or not?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://deck.gl/&quot;&gt;deck.gl&lt;/a&gt; is like Leaflet on steroids. It was designed to “visually explore large-scale datasets”. It leverages the processing power of your graphics card to do some impressive rendering magic. After using Leaflet, I found it quite easy to get up and running with deck.gl, and managed to produce this awesome visualization:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Plotting gridded data on a web map: Python and/or Javascript?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;612&quot; height=&quot;432&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-7102366f.CCo91M-J_WnkMk.webp&quot; srcset=&quot;&quot;&gt;
Rendering over a million grid cells using deck.glBut still, I had to cheat a bit. And still, it was slow. For the data… was big.&lt;/p&gt;
&lt;h2 id=&quot;incentives-for-a-hybrid-solution&quot;&gt;Incentives for a hybrid solution&lt;/h2&gt;
&lt;p&gt;The data I wanted to use came originally in netCDF format and while it seems possible* nowadays to parse that with Javascript, it’s not the oneliner I’m used to in Python. The same goes for the colour mapping. To save me some time, I decided to do some light preprocessing in Python.&lt;/p&gt;
&lt;p&gt;Next, let’s talk about data sizes. The size of the original netCDF data for one timestamp was about 4 MB. The size of the preprocessed data in JSON format was considerably larger: almost 50 MB. For climate scientists this is nothing, but for smoothly running a website that’s quite substantial… It might be worthwhile to explore which file formats work well for both languages.&lt;/p&gt;
&lt;p&gt;So what about the tile solutions from earlier? Could that save me some bandwidth and rendering time? And how hard could it be to make my own tiles in Python? As you could see from the first Leaflet example, it’s just a matter of creating a folder structure like &lt;code&gt;baseurl/{z}/{x}/{y}.png&lt;/code&gt;, where the tile numbering follows the slippy tile format explained &lt;a href=&quot;https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Plotting gridded data on a web map: Python and/or Javascript?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;224&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-c3fb61ab.CgVRjSqu_ZI443P.webp&quot; srcset=&quot;&quot;&gt;
Example tiles at zoom levels 0 (left), 1 (middles) and 2 (right).To draw a tile we basically have to determine the right colour for each pixel. I already mentioned that the tiles are 256x256 pixels. My sample data is 1440x721 grid cells. Therefore, to create the first tile that covers the globe, we need to condense, or &lt;em&gt;aggregate&lt;/em&gt;, the data. We have 5 to 6 grid cells per pixel in the &lt;em&gt;x&lt;/em&gt;-direction and about 3 in the &lt;em&gt;y&lt;/em&gt;-direction. The simplest way to aggregate them would be to take the mean of these ~15 grid cells. (At higher zoom levels, where we have more pixels than grid cells, we’d need to upsample, or *interpolate *instead). Then we’d have to map the values of temperature onto a colour scale. Finally, we’d draw the pixels on a canvas.&lt;/p&gt;
&lt;p&gt;There happens to be a Python library that is built to do exactly this: &lt;a href=&quot;https://datashader.org/&quot;&gt;Datashader&lt;/a&gt;. While it’s intended for use from within a Python session, there is no reason why you couldn’t use that library to render images upfront. The developers of the package also &lt;a href=&quot;https://github.com/holoviz/datashader/issues/246&quot;&gt;realized this&lt;/a&gt; and created an initial implementation to render tiles with a somewhat hidden &lt;a href=&quot;https://github.com/holoviz/datashader/blob/master/examples/tiling.ipynb&quot;&gt;example notebook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I adapted the example to my needs and started rendering some tiles. In terms of storage, the first 4 zoom levels (0 to 3) were all below 1 MB. Then it quickly went up from 2.4 MB to 6.8 MB to 22 MB for levels 4 through 6. Performance started to degrade at zoom level 6, perhaps because of the upsampling that was going on. At zoom level 7, my code crashed, though I’m sure it can still be optimized.&lt;/p&gt;
&lt;p&gt;Now it was time to show my awesome tile layer on a Leaflet map. I struggled a bit to get the projection right, but eventually, it worked like a charm (select the tile layer on the leaflet map &lt;a href=&quot;https://peter9192.github.io/webmaps/&quot;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Plotting gridded data on a web map: Python and/or Javascript?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;688&quot; height=&quot;469&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-a8fb1070.BqhSHahB_gq65k.webp&quot; srcset=&quot;&quot;&gt;
&lt;a href=&quot;https://xkcd.com/2256&quot;&gt;https://xkcd.com/2256&lt;/a&gt;I was happy that my tile layer worked, but it also got me thinking: zoom level 0 seemed quite redundant: why would anyone want to show the whole globe on a tiny thumbnail? The tile layer only starts to be advantageous at the higher zoom levels. But do I really need that? Indeed, with the source data resolution of 0.25 degrees, there might not be much to gain beyond zoom level 3. Consequently, for a global dataset at this resolution, an image overlay might be a better, and easier, solution.&lt;/p&gt;
&lt;p&gt;After tinkering a bit with how to reproject and save the file, I managed to create an image with just as many pixels as I had grid cells, and project it onto my Leaflet map (select the image layer &lt;a href=&quot;https://peter9192.github.io/webmaps/&quot;&gt;here&lt;/a&gt;). The image size was under 400 KB and it rendered nicely onto the map. Maybe even too nicely: at higher zoom levels, Leaflet did a great job at smoothing the edges between the original pixels, and although this provided a nice looking image, I did not like it. For scientific applications, it is more honest to show the coarse pixels of the source data. In that sense, the polygon solution was much better.&lt;/p&gt;
&lt;h2 id=&quot;not-so-bad-after-all&quot;&gt;Not so bad after all?&lt;/h2&gt;
&lt;p&gt;So let’s do a quick resume. To plot data on a web map, we have several options. For relatively coarse datasets, creating an image overlay seems to be a good option, although you might lose the explicit granularity of the source data. Tile layers will be useful mostly when you go to a much higher resolution (whilst keeping a large domain). Both these options require pre-rendering of the images/tiles, which means that the colour bar will be fixed and the connection with the source data is lost.&lt;/p&gt;
&lt;p&gt;Alternatively, rendering the data client-side is also within reach, especially with tools like deck.gl. In my experiments, it required fetching and processing substantial amounts of data, but this can be amended. Similar to the pre-rendered raster tiles I’ve explored, &lt;a href=&quot;https://en.wikipedia.org/wiki/Vector_tiles&quot;&gt;vector tiles&lt;/a&gt; have become increasingly popular. This could be a good solution when you have (much) more pixels than grid cells, whereas raster tiles work well in the opposite situation. The preferred option is thus determined by the source data resolution, and the zoom levels you want to support.&lt;/p&gt;
&lt;p&gt;Finally, let’s look back at the very first figure I showed. It was made with the &lt;a href=&quot;https://hvplot.holoviz.org/&quot;&gt;hvPlot&lt;/a&gt; library, which is built on top of &lt;a href=&quot;https://holoviews.org/&quot;&gt;HoloViews&lt;/a&gt;, which in turn uses &lt;a href=&quot;https://docs.bokeh.org/en/latest/&quot;&gt;Bokeh&lt;/a&gt;. I also used &lt;a href=&quot;https://panel.holoviz.org/index.html&quot;&gt;Panel&lt;/a&gt; for exporting the file. Bokeh consists of two components: BokehJS for creating interactive visualizations with Javascript, and the Python library, which makes it easy to ‘define’ visualizations that are understood by the Javascript counterpart. Simply put, these &lt;em&gt;definitions&lt;/em&gt; are just listings of the different plot elements that constitute the visualization. When you export a visualization as a static file, all possible ‘states’ (in my case the four seasons) are written to the output file(s), alongside the definition. Depending on the plot type, the state may consist of some data, or perhaps an encoded image. At that point, BokehJS can read the definition and state data and reconstruct the visualization.&lt;/p&gt;
&lt;p&gt;It is a great solution if you are happy with the possibilities offered by Bokeh and the libraries that are built on top of it. Personally, I’m not so keen on the “you worry about the science, we worry about the implementation” attitude that some of the high-level visualization packages sometimes tend to preach. I think it’s important to have a basic understanding of what’s going on under the hood. And while the BokehJS library seems to be quite good at what it does, I’d like it even better when the exchange formats between Python and Javascript were more interoperable.&lt;/p&gt;
&lt;p&gt;Anyway, now that I’m starting to grasp the core principles and challenges, I’ve come to appreciate how far they have come, and I look forward to seeing how this exciting visualization landscape will develop in the near future. This exploration has been a valuable learning experience for me, and I hope it may help some of the readers as well.&lt;/p&gt;
&lt;p&gt;Happy mapping!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/plotting-gridded-data-on-a-web-map-pytho-7102366f.CCo91M-J.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Literate Programming in Science</title><link>https://blog2.esciencecenter.nl/posts/2021-07-07---literate-programming-in-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-07-07---literate-programming-in-science</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;2768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_3ke-o36ZPmah-PK4-a8e3aba4.Csxfd0Dk_1vb839.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Prateek Katyal on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;2-the-how&quot;&gt;2. The How&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is part 2 in a series on Literate Programming in Science. If you haven’t yet,&lt;/em&gt; &lt;a href=&quot;https://blog.esciencecenter.nl/literate-programming-in-science-1669094541a7&quot;&gt;&lt;em&gt;please read part 1 “The Why”&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Literate programming&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;/ˈlɪtəɹət ˈpɹəʊɡɹæmɪŋ/ (computing) Literate programming is a programming paradigm introduced by Donald Knuth in which a program is given as an explanation of the program logic in a natural language, such as English, interspersed with snippets of macros and traditional source code, from which a compilable source code can be generated.&lt;/em&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Literate_programming&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you’re reading this, then I hope I’ve convinced you (or maybe you didn’t need convincing) of the necessity of Literate Programming in Science. The next question should be: where do I start? I will discuss three methods of Literate Programming that you can use today, their upsides and downsides, what-have-you-not.&lt;/p&gt;
&lt;p&gt;First, I should explain some nomenclature surrounding the concept of Literate Programming. The idea is that you write documentation first, interspersed with code blocks that actually implement the described ideas. These code blocks can be named and referenced from other code blocks using a system of references called &lt;em&gt;Noweb&lt;/em&gt;. A special program is needed to extract all the code blocks from the markup and put them in the right order so that a well formed program code emerges on the other end: a process known as &lt;em&gt;tangling&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A literate form of “Hello, World” in C++ would look something like this:&lt;/p&gt;
&lt;h2 id=&quot;hello-world&quot;&gt;Hello World&lt;/h2&gt;
&lt;p&gt;This example is written in a style of &lt;em&gt;literate programming&lt;/em&gt; (Knuth 1984). The combined code-blocks in this example compose a compilable source code for “Hello World”. For didactic reasons we don’t always give the listing of an entire source file in one go. In stead, we use a system of references known as &lt;em&gt;noweb&lt;/em&gt; (Ramsey 1994).&lt;/p&gt;
&lt;p&gt;Inside source fragments you may encounter a line with &lt;code&gt;&amp;#x3C;&amp;#x3C;...&gt;&gt;&lt;/code&gt; marks like,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«hello_world.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#include &amp;#x3C;cstdlib&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#include &amp;#x3C;iostream&gt;&amp;#x3C;&amp;#x3C;example-main-function&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is then elsewhere specified. Order doesn’t matter,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Hello, World!&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;endl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we can reference the &lt;code&gt;&amp;#x3C;&amp;#x3C;print-message&gt;&gt;&lt;/code&gt; code block later on.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«example&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(int argc, char &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;argv) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &amp;#x3C;&amp;#x3C;print&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A definition can be appended with more code as follows (in this case, order does matter!):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; EXIT_SUCCESS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These blocks of code can be &lt;em&gt;tangled&lt;/em&gt; into source files, in this case a single &lt;code&gt;hello_world.cc&lt;/code&gt; would emerge.&lt;/p&gt;
&lt;p&gt;This “Hello World” shows just how you can combine the contents of code blocks to create a fully functional “Hello World” in C++. More examples of this type of literate programs can be found on the &lt;a href=&quot;https://entangled.github.io/examples&quot;&gt;Entangled website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Noweb method of literate programming is not the only way to mix documentation with code. Not all methods described here have all the features that you would expect from Knuth’s original invention. In fact the most popular incarnation of Literate Programming arguably is that of notebooks. We may judge each method by their ease of use, and if they fit the bill of generating publishable and reproducible scholarly products.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_E5I_DM8KaxUxkDNf-4dd728e6.D3u-ChMJ_WHtXW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NASA on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;notebooks-in-particular-jupyter&quot;&gt;Notebooks (in particular Jupyter)&lt;/h2&gt;
&lt;p&gt;The most common form of Literate Programming found in todays jungle of digitized science is the &lt;em&gt;notebook&lt;/em&gt;. Personally my first encounter with notebooks was with the use of Mathematica, which featured notebooks as early as 1988. Many commercial packages for data analytics and modelling featured notebook interfaces long before the rise of &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter notebooks&lt;/a&gt; in 2014. What makes Jupyter special is that it is an open source solution for many different languages (as long as someone took the effort of writing a Jupyter kernel for it).&lt;/p&gt;
&lt;h3 id=&quot;pros&quot;&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic evaluation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy interface&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy sharing&lt;/strong&gt; with MyBinder or related tools&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language agnostic (in theory)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cons&quot;&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No support for Noweb references or tangling&lt;/strong&gt;: the code is evaluated in any possible order, depending on user interaction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only really meant for end-of-line products&lt;/strong&gt;: it is not expected that you write a Python library in a Jupyter notebook that someone else can import. It can be done in the case of Python (&lt;a href=&quot;https://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Importing%20Notebooks.html&quot;&gt;see Jupyter docs&lt;/a&gt;), but just reading the documentation should instill a deep feeling that you really shouldn’t.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only works for evaluated languages&lt;/strong&gt;: because notebook interfaces are designed to be interactive, they are fundamentally limited to languages that provide a Read-Evaluate-Print loop (or REPL for short). Examples of languages that don’t have this are Java, Rust, Go (I would like to include C++ here, but there is Cling, the complexity of which is an argument against itself). In the case of Haskell we do have a REPL, but it doesn’t expose the full language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crappy text editor&lt;/strong&gt;: With Jupyter you’re stuck with the default inline text editor of Jupyter. If you use VSCode, you can edit notebooks directly from there, but the interface is still quite slow and buggy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard to debug&lt;/strong&gt;: The latest version of Jupyter has a debugger for Python, I’m not sure if this debugger translates well to other languages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No stable API&lt;/strong&gt;: This is not a principal argument, but a practical one. The Jupyter API changes often. As a consequence, the only kernel that can be expected to always work is the Python one. I’ve experienced frequent breaks when using Jupyter, even in the relatively common case of GNU R. For most other languages, sadly, chances are that you will have to experiment with downgrading Jupyter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stored in JSON&lt;/strong&gt;: the contents of the notebook are stored in JSON, even opening a notebook changes its contents. This is especially annoying when working with &lt;strong&gt;git&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of these downsides may lessen or disappear entirely as Jupyter improves. The first three however are rather fundamental to the method. That is no critique. I love working with Jupyter and use it every day. It just isn’t for everything.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VXW1HQh6uiOo2ftU-cef2e6ae.DJrS2SNb_ZjiOkz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Margarida Afonso on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;rmarkdown-and-knitr-with-rstudio&quot;&gt;RMarkdown and Knitr (with RStudio)&lt;/h2&gt;
&lt;p&gt;RMarkdown was designed as the Literate Programming solution for R, with a focus on reproducibility. As the name suggests, it is a dialect of the markdown language.&lt;/p&gt;
&lt;p&gt;Contrary to Jupyter, RMarkdown is more focused on creating high-quality documents than on interactivity, making it a perfect choice for writing vignettes, reports and even academic papers.&lt;/p&gt;
&lt;p&gt;RMarkdown is particularly easy to learn and to use from RStudio. Nowadays it supports several languages apart from R, such as Python or SQL.&lt;/p&gt;
&lt;h3 id=&quot;pros-1&quot;&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy to install:&lt;/strong&gt; (comes by default with RStudio)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic evaluation:&lt;/strong&gt; only if desired.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy interface&lt;/strong&gt;: RMarkdown is very accessible to new users through the RStudio interface, but it is possible to use it outside RStudio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy sharing:&lt;/strong&gt; with RPubs, MyBinder or related tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plain text:&lt;/strong&gt; Well defined plain-text format, in this case Markdown.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed order of evaluation:&lt;/strong&gt; The code is evaluated sequentially by default. Other than with Jupyter, where the order of execution depends on user interaction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language agnostic (in theory):&lt;/strong&gt; many languages are supported through the &lt;em&gt;Knitr engine&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Fancy functionalities are constantly added by the R community, such as caching for long calculations, support for different languages, cross-referencing, templates, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cons-1&quot;&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No support for Noweb references or tangling&lt;/strong&gt;: the code is evaluated in the order that you enter it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-of-line:&lt;/strong&gt; It is not expected that you write an R package in a RMarkdown file that someone else can import. Usually, the RMarkdown files are an addition to a package.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard to debug&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language centric:&lt;/strong&gt; The integration with languages other than R happens through R packages. Most of these packages are quite well designed and just work out-of-the-box, but for some of them you may need to invest learning how they work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just as Jupyter, RMarkdown is a great tool to get started with Literate Programming. It stops just shy of being able to create fully compilable files from the literate sources.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_1arvThu4tV8Y4Zuy-effb0a2b.CzqIefJ__1ILJbA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Brigitta Schneiter on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;emacs-org-mode&quot;&gt;Emacs org-mode&lt;/h2&gt;
&lt;p&gt;While &lt;a href=&quot;https://orgmode.org/&quot;&gt;Org-mode&lt;/a&gt; is not terribly well known, it offers one of the most complete solutions for Literate Programming that you can find. Me myself, I’m a born Vim user. Every now and then I take these editor excursions: VSCode lasted a week before I went back screaming for Vim. For this single feature of Org-mode I nearly switched to Emacs. I tried &lt;a href=&quot;https://spacemacs.org/&quot;&gt;SpaceMacs&lt;/a&gt; for about &lt;em&gt;half a year&lt;/em&gt; until reverting back to Vim. &lt;em&gt;That is how good Org-mode is (26x all of VSCode if you can count).&lt;/em&gt; Many adepts describe it as a life changer.&lt;/p&gt;
&lt;p&gt;In essence Org-mode is an editor mode that helps you edit nestings of unordered lists, it’s main use being for brainstorming and keeping todo lists. From these humble beginings sprouted a markup language that, entirely in the Emacs tradition, includes everything and the kitchen sink (did I mention the spreadsheet?). Today Org-mode could be considered a variant on other markup languages like Markdown and reStructured Text. What makes Org-mode special is the way you can edit and interact with it inside Emacs.&lt;/p&gt;
&lt;p&gt;One of the many features of Org-mode is that it supports code-blocks &lt;em&gt;with noweb references&lt;/em&gt;. These code-blocks can be evaluated inline (using one of many plugins available for Emacs) or tangled to runnable/compilable source files.&lt;/p&gt;
&lt;h3 id=&quot;pros-2&quot;&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Supports noweb and tangling.&lt;/li&gt;
&lt;li&gt;Well defined plain-text format.&lt;/li&gt;
&lt;li&gt;Export to nearly anything.&lt;/li&gt;
&lt;li&gt;Dynamic evaluation of code blocks.&lt;/li&gt;
&lt;li&gt;Completely language agnostic.&lt;/li&gt;
&lt;li&gt;Plain text markup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cons-2&quot;&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Only works as intended in &lt;strong&gt;Emacs.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Collaborators would have to use &lt;strong&gt;Emacs.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Debugging should be done from &lt;strong&gt;Emacs.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In its own way Emacs is awesome. If this fits the bill for you, by all means shape your life around it, join the church. I do believe however, that this is not something you can force onto someone else.&lt;/p&gt;
&lt;p&gt;What all the previous methods share is that they drive you into using a chosen set of tools, each with its own particular down sides. What I am aiming for is a method of Literate Programming that is feature complete and &lt;em&gt;minimally intrusive&lt;/em&gt;. Feature completeness is always a matter of personal taste, nevertheless I will give it a shot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deconstruct code using Noweb syntax, or something very close to it.&lt;/li&gt;
&lt;li&gt;Be completely language agnostic.&lt;/li&gt;
&lt;li&gt;Export to nearly everything.&lt;/li&gt;
&lt;li&gt;Use a plain-text markup format.&lt;/li&gt;
&lt;li&gt;Play nicely with existing methods for publishing on the web.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One thing I didn’t include in there is the feature of dynamic evaluation. Such a thing could be achieved in a generic way by implementing editor plug-ins on top of the &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server Protocol&lt;/a&gt; (using a code action of some kind). Implementing an Org-mode kind of interaction in this way would be a very interesting project onto itself, but not today.&lt;/p&gt;
&lt;p&gt;Instead, I introduce a new feature that none of the other methods have: the ability to work on tangled source code while keeping the original markup synchronized. This feature greatly improves the maintainability of the literate program while also opening up all the normal tools you’re used to work with: debuggers, linters, transmogrifiers, you name it. Let’s call this feature: &lt;strong&gt;live untangle mode&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-entangled-project&quot;&gt;The Entangled Project&lt;/h2&gt;
&lt;p&gt;I hope by now I have convinced you that A. Literate Programming is awesome and B. the current set of available tools are not sufficient. This is why I started &lt;a href=&quot;https://entangled.github.io/&quot;&gt;the Entangled project&lt;/a&gt;. The goals of the Entangled Project are three-fold:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Develop tools for Literate Programming&lt;/li&gt;
&lt;li&gt;Arrive at a set of best practices&lt;/li&gt;
&lt;li&gt;Communicate, teach and promote&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The push for these methods and best practices focusses on a system using &lt;em&gt;Markdown&lt;/em&gt; as the primary markup language. I believe Markdown offers the ideal combination of readability and flexibility to suit most needs, a stance that I previously defended in a blog post: &lt;a href=&quot;https://blog.esciencecenter.nl/why-all-youll-ever-need-is-markdown-dc604f0ab309&quot;&gt;Why all you’ll ever need is Markdown&lt;/a&gt;. This does not mean that the choice for Markdown is final; all of what we do carries over without problems to other formats.&lt;/p&gt;
&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;
&lt;p&gt;The primary tool we have developed is Entangled. This is a daemon that runs while you edit the markup files or the tangled sources. Entangled keeps the two in sync so that you only ever have one version of the code.&lt;/p&gt;
&lt;p&gt;Next to this core tool we have several experimental filters for &lt;a href=&quot;https://pandoc.org/&quot;&gt;Pandoc, the universal document converter.&lt;/a&gt; These filters can do several things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Annotate generated output with headings for the named code fragments.&lt;/li&gt;
&lt;li&gt;Evaluate code fragments by passing them through Jupyter.&lt;/li&gt;
&lt;li&gt;Inject Javascript code fragments into the HTML output for interactive elements (e.g. PlotLy).&lt;/li&gt;
&lt;li&gt;Generate Bootstrap UI elements, for example: foldable code blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The approach we take to Literate Programming has been battle tested using three different document converters: Pandoc, MkDocs and Docsify. Each generator works with a slightly different dialect of Markdown.&lt;/p&gt;
&lt;h3 id=&quot;future-plans&quot;&gt;Future plans&lt;/h3&gt;
&lt;p&gt;Entangled is ready to use, but it is not too user friendly yet. For one, we expect you to setup your own pipeline for building the document for public release. Most often this would be some static HTML generator using Pandoc or MkDocs. Alternatively you can use Docsify to serve a website directly from the Markdown sources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Getting started:&lt;/strong&gt; The problem for entry level users is that it may not be trivial to set these up. The current template for working with Pandoc requires Pandoc (duh), GNU Make, browser-sync, some form of inotify-wait, and of course, Entangled. We’d like to make it much easier to start working on your own projects, so we’d like to bring this set of requirements back to just Entangled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Templates:&lt;/strong&gt; We should provide easy to use starting templates for a set of popular document generators. The one currently still unmentioned being Sphinx. These templates should be initialized using an &lt;code&gt;entangled init&lt;/code&gt; sub-command.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single file mode&lt;/strong&gt;: The default operation of Entangled should be a single file mode (most probably &lt;code&gt;README.md&lt;/code&gt;), and work out of the box with no configuration. Imagine a Github repository with just a &lt;code&gt;README&lt;/code&gt; (and a &lt;code&gt;LICENSE&lt;/code&gt; and a &lt;code&gt;CITATION.cff&lt;/code&gt; and a &lt;code&gt;.editorconfig&lt;/code&gt; and a … oh you get the point!) and a Github Action tacked on to generate the Github.io pages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible code presentation:&lt;/strong&gt; in the publicized output code cells are currently static. At the very least Noweb references should be clickable. Other features could include: links to the tangled output, be able to view the code in expanded form.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Help is appreciated! Entangled is primarily developed in Haskell, though no skill in Haskell is required for example to create templates for working with Entangled. Pandoc filters can be developed in Python. In particular the filter for interacting with Jupyter could use some fresh ideas.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;About the author: I’m (among other things) the developer of&lt;/em&gt; &lt;a href=&quot;https://entangled.github.io/&quot;&gt;&lt;em&gt;Entangled, a Literate Programming framework and toolset&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. The main goal of this blog-post is to convince you that existing tools for Literate Programming are not yet ready to serve the needs of the broader scientific community.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Wed, 07 Jul 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;2768&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_3ke-o36ZPmah-PK4-a8e3aba4.Csxfd0Dk_1vb839.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Prateek Katyal on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;2-the-how&quot;&gt;2. The How&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is part 2 in a series on Literate Programming in Science. If you haven’t yet,&lt;/em&gt; &lt;a href=&quot;https://blog.esciencecenter.nl/literate-programming-in-science-1669094541a7&quot;&gt;&lt;em&gt;please read part 1 “The Why”&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Literate programming&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;/ˈlɪtəɹət ˈpɹəʊɡɹæmɪŋ/ (computing) Literate programming is a programming paradigm introduced by Donald Knuth in which a program is given as an explanation of the program logic in a natural language, such as English, interspersed with snippets of macros and traditional source code, from which a compilable source code can be generated.&lt;/em&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Literate_programming&quot;&gt;&lt;em&gt;Wikipedia&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you’re reading this, then I hope I’ve convinced you (or maybe you didn’t need convincing) of the necessity of Literate Programming in Science. The next question should be: where do I start? I will discuss three methods of Literate Programming that you can use today, their upsides and downsides, what-have-you-not.&lt;/p&gt;
&lt;p&gt;First, I should explain some nomenclature surrounding the concept of Literate Programming. The idea is that you write documentation first, interspersed with code blocks that actually implement the described ideas. These code blocks can be named and referenced from other code blocks using a system of references called &lt;em&gt;Noweb&lt;/em&gt;. A special program is needed to extract all the code blocks from the markup and put them in the right order so that a well formed program code emerges on the other end: a process known as &lt;em&gt;tangling&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A literate form of “Hello, World” in C++ would look something like this:&lt;/p&gt;
&lt;h2 id=&quot;hello-world&quot;&gt;Hello World&lt;/h2&gt;
&lt;p&gt;This example is written in a style of &lt;em&gt;literate programming&lt;/em&gt; (Knuth 1984). The combined code-blocks in this example compose a compilable source code for “Hello World”. For didactic reasons we don’t always give the listing of an entire source file in one go. In stead, we use a system of references known as &lt;em&gt;noweb&lt;/em&gt; (Ramsey 1994).&lt;/p&gt;
&lt;p&gt;Inside source fragments you may encounter a line with &lt;code&gt;&amp;#x3C;&amp;#x3C;...&gt;&gt;&lt;/code&gt; marks like,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«hello_world.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#include &amp;#x3C;cstdlib&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#include &amp;#x3C;iostream&gt;&amp;#x3C;&amp;#x3C;example-main-function&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which is then elsewhere specified. Order doesn’t matter,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Hello, World!&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;endl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So we can reference the &lt;code&gt;&amp;#x3C;&amp;#x3C;print-message&gt;&gt;&lt;/code&gt; code block later on.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«example&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(int argc, char &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;**&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;argv) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &amp;#x3C;&amp;#x3C;print&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A definition can be appended with more code as follows (in this case, order does matter!):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;«&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;message»&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; EXIT_SUCCESS&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;@&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These blocks of code can be &lt;em&gt;tangled&lt;/em&gt; into source files, in this case a single &lt;code&gt;hello_world.cc&lt;/code&gt; would emerge.&lt;/p&gt;
&lt;p&gt;This “Hello World” shows just how you can combine the contents of code blocks to create a fully functional “Hello World” in C++. More examples of this type of literate programs can be found on the &lt;a href=&quot;https://entangled.github.io/examples&quot;&gt;Entangled website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Noweb method of literate programming is not the only way to mix documentation with code. Not all methods described here have all the features that you would expect from Knuth’s original invention. In fact the most popular incarnation of Literate Programming arguably is that of notebooks. We may judge each method by their ease of use, and if they fit the bill of generating publishable and reproducible scholarly products.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_E5I_DM8KaxUxkDNf-4dd728e6.D3u-ChMJ_WHtXW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NASA on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;notebooks-in-particular-jupyter&quot;&gt;Notebooks (in particular Jupyter)&lt;/h2&gt;
&lt;p&gt;The most common form of Literate Programming found in todays jungle of digitized science is the &lt;em&gt;notebook&lt;/em&gt;. Personally my first encounter with notebooks was with the use of Mathematica, which featured notebooks as early as 1988. Many commercial packages for data analytics and modelling featured notebook interfaces long before the rise of &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter notebooks&lt;/a&gt; in 2014. What makes Jupyter special is that it is an open source solution for many different languages (as long as someone took the effort of writing a Jupyter kernel for it).&lt;/p&gt;
&lt;h3 id=&quot;pros&quot;&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic evaluation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy interface&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy sharing&lt;/strong&gt; with MyBinder or related tools&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language agnostic (in theory)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cons&quot;&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No support for Noweb references or tangling&lt;/strong&gt;: the code is evaluated in any possible order, depending on user interaction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only really meant for end-of-line products&lt;/strong&gt;: it is not expected that you write a Python library in a Jupyter notebook that someone else can import. It can be done in the case of Python (&lt;a href=&quot;https://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Importing%20Notebooks.html&quot;&gt;see Jupyter docs&lt;/a&gt;), but just reading the documentation should instill a deep feeling that you really shouldn’t.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only works for evaluated languages&lt;/strong&gt;: because notebook interfaces are designed to be interactive, they are fundamentally limited to languages that provide a Read-Evaluate-Print loop (or REPL for short). Examples of languages that don’t have this are Java, Rust, Go (I would like to include C++ here, but there is Cling, the complexity of which is an argument against itself). In the case of Haskell we do have a REPL, but it doesn’t expose the full language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crappy text editor&lt;/strong&gt;: With Jupyter you’re stuck with the default inline text editor of Jupyter. If you use VSCode, you can edit notebooks directly from there, but the interface is still quite slow and buggy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard to debug&lt;/strong&gt;: The latest version of Jupyter has a debugger for Python, I’m not sure if this debugger translates well to other languages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No stable API&lt;/strong&gt;: This is not a principal argument, but a practical one. The Jupyter API changes often. As a consequence, the only kernel that can be expected to always work is the Python one. I’ve experienced frequent breaks when using Jupyter, even in the relatively common case of GNU R. For most other languages, sadly, chances are that you will have to experiment with downgrading Jupyter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stored in JSON&lt;/strong&gt;: the contents of the notebook are stored in JSON, even opening a notebook changes its contents. This is especially annoying when working with &lt;strong&gt;git&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of these downsides may lessen or disappear entirely as Jupyter improves. The first three however are rather fundamental to the method. That is no critique. I love working with Jupyter and use it every day. It just isn’t for everything.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VXW1HQh6uiOo2ftU-cef2e6ae.DJrS2SNb_ZjiOkz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Margarida Afonso on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;rmarkdown-and-knitr-with-rstudio&quot;&gt;RMarkdown and Knitr (with RStudio)&lt;/h2&gt;
&lt;p&gt;RMarkdown was designed as the Literate Programming solution for R, with a focus on reproducibility. As the name suggests, it is a dialect of the markdown language.&lt;/p&gt;
&lt;p&gt;Contrary to Jupyter, RMarkdown is more focused on creating high-quality documents than on interactivity, making it a perfect choice for writing vignettes, reports and even academic papers.&lt;/p&gt;
&lt;p&gt;RMarkdown is particularly easy to learn and to use from RStudio. Nowadays it supports several languages apart from R, such as Python or SQL.&lt;/p&gt;
&lt;h3 id=&quot;pros-1&quot;&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy to install:&lt;/strong&gt; (comes by default with RStudio)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic evaluation:&lt;/strong&gt; only if desired.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy interface&lt;/strong&gt;: RMarkdown is very accessible to new users through the RStudio interface, but it is possible to use it outside RStudio.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Easy sharing:&lt;/strong&gt; with RPubs, MyBinder or related tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plain text:&lt;/strong&gt; Well defined plain-text format, in this case Markdown.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fixed order of evaluation:&lt;/strong&gt; The code is evaluated sequentially by default. Other than with Jupyter, where the order of execution depends on user interaction.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language agnostic (in theory):&lt;/strong&gt; many languages are supported through the &lt;em&gt;Knitr engine&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Fancy functionalities are constantly added by the R community, such as caching for long calculations, support for different languages, cross-referencing, templates, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cons-1&quot;&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No support for Noweb references or tangling&lt;/strong&gt;: the code is evaluated in the order that you enter it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;End-of-line:&lt;/strong&gt; It is not expected that you write an R package in a RMarkdown file that someone else can import. Usually, the RMarkdown files are an addition to a package.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard to debug&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language centric:&lt;/strong&gt; The integration with languages other than R happens through R packages. Most of these packages are quite well designed and just work out-of-the-box, but for some of them you may need to invest learning how they work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just as Jupyter, RMarkdown is a great tool to get started with Literate Programming. It stops just shy of being able to create fully compilable files from the literate sources.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_1arvThu4tV8Y4Zuy-effb0a2b.CzqIefJ__1ILJbA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Brigitta Schneiter on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;emacs-org-mode&quot;&gt;Emacs org-mode&lt;/h2&gt;
&lt;p&gt;While &lt;a href=&quot;https://orgmode.org/&quot;&gt;Org-mode&lt;/a&gt; is not terribly well known, it offers one of the most complete solutions for Literate Programming that you can find. Me myself, I’m a born Vim user. Every now and then I take these editor excursions: VSCode lasted a week before I went back screaming for Vim. For this single feature of Org-mode I nearly switched to Emacs. I tried &lt;a href=&quot;https://spacemacs.org/&quot;&gt;SpaceMacs&lt;/a&gt; for about &lt;em&gt;half a year&lt;/em&gt; until reverting back to Vim. &lt;em&gt;That is how good Org-mode is (26x all of VSCode if you can count).&lt;/em&gt; Many adepts describe it as a life changer.&lt;/p&gt;
&lt;p&gt;In essence Org-mode is an editor mode that helps you edit nestings of unordered lists, it’s main use being for brainstorming and keeping todo lists. From these humble beginings sprouted a markup language that, entirely in the Emacs tradition, includes everything and the kitchen sink (did I mention the spreadsheet?). Today Org-mode could be considered a variant on other markup languages like Markdown and reStructured Text. What makes Org-mode special is the way you can edit and interact with it inside Emacs.&lt;/p&gt;
&lt;p&gt;One of the many features of Org-mode is that it supports code-blocks &lt;em&gt;with noweb references&lt;/em&gt;. These code-blocks can be evaluated inline (using one of many plugins available for Emacs) or tangled to runnable/compilable source files.&lt;/p&gt;
&lt;h3 id=&quot;pros-2&quot;&gt;Pros:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Supports noweb and tangling.&lt;/li&gt;
&lt;li&gt;Well defined plain-text format.&lt;/li&gt;
&lt;li&gt;Export to nearly anything.&lt;/li&gt;
&lt;li&gt;Dynamic evaluation of code blocks.&lt;/li&gt;
&lt;li&gt;Completely language agnostic.&lt;/li&gt;
&lt;li&gt;Plain text markup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cons-2&quot;&gt;Cons:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Only works as intended in &lt;strong&gt;Emacs.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Collaborators would have to use &lt;strong&gt;Emacs.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Debugging should be done from &lt;strong&gt;Emacs.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In its own way Emacs is awesome. If this fits the bill for you, by all means shape your life around it, join the church. I do believe however, that this is not something you can force onto someone else.&lt;/p&gt;
&lt;p&gt;What all the previous methods share is that they drive you into using a chosen set of tools, each with its own particular down sides. What I am aiming for is a method of Literate Programming that is feature complete and &lt;em&gt;minimally intrusive&lt;/em&gt;. Feature completeness is always a matter of personal taste, nevertheless I will give it a shot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deconstruct code using Noweb syntax, or something very close to it.&lt;/li&gt;
&lt;li&gt;Be completely language agnostic.&lt;/li&gt;
&lt;li&gt;Export to nearly everything.&lt;/li&gt;
&lt;li&gt;Use a plain-text markup format.&lt;/li&gt;
&lt;li&gt;Play nicely with existing methods for publishing on the web.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One thing I didn’t include in there is the feature of dynamic evaluation. Such a thing could be achieved in a generic way by implementing editor plug-ins on top of the &lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server Protocol&lt;/a&gt; (using a code action of some kind). Implementing an Org-mode kind of interaction in this way would be a very interesting project onto itself, but not today.&lt;/p&gt;
&lt;p&gt;Instead, I introduce a new feature that none of the other methods have: the ability to work on tangled source code while keeping the original markup synchronized. This feature greatly improves the maintainability of the literate program while also opening up all the normal tools you’re used to work with: debuggers, linters, transmogrifiers, you name it. Let’s call this feature: &lt;strong&gt;live untangle mode&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-entangled-project&quot;&gt;The Entangled Project&lt;/h2&gt;
&lt;p&gt;I hope by now I have convinced you that A. Literate Programming is awesome and B. the current set of available tools are not sufficient. This is why I started &lt;a href=&quot;https://entangled.github.io/&quot;&gt;the Entangled project&lt;/a&gt;. The goals of the Entangled Project are three-fold:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Develop tools for Literate Programming&lt;/li&gt;
&lt;li&gt;Arrive at a set of best practices&lt;/li&gt;
&lt;li&gt;Communicate, teach and promote&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The push for these methods and best practices focusses on a system using &lt;em&gt;Markdown&lt;/em&gt; as the primary markup language. I believe Markdown offers the ideal combination of readability and flexibility to suit most needs, a stance that I previously defended in a blog post: &lt;a href=&quot;https://blog.esciencecenter.nl/why-all-youll-ever-need-is-markdown-dc604f0ab309&quot;&gt;Why all you’ll ever need is Markdown&lt;/a&gt;. This does not mean that the choice for Markdown is final; all of what we do carries over without problems to other formats.&lt;/p&gt;
&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;
&lt;p&gt;The primary tool we have developed is Entangled. This is a daemon that runs while you edit the markup files or the tangled sources. Entangled keeps the two in sync so that you only ever have one version of the code.&lt;/p&gt;
&lt;p&gt;Next to this core tool we have several experimental filters for &lt;a href=&quot;https://pandoc.org/&quot;&gt;Pandoc, the universal document converter.&lt;/a&gt; These filters can do several things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Annotate generated output with headings for the named code fragments.&lt;/li&gt;
&lt;li&gt;Evaluate code fragments by passing them through Jupyter.&lt;/li&gt;
&lt;li&gt;Inject Javascript code fragments into the HTML output for interactive elements (e.g. PlotLy).&lt;/li&gt;
&lt;li&gt;Generate Bootstrap UI elements, for example: foldable code blocks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The approach we take to Literate Programming has been battle tested using three different document converters: Pandoc, MkDocs and Docsify. Each generator works with a slightly different dialect of Markdown.&lt;/p&gt;
&lt;h3 id=&quot;future-plans&quot;&gt;Future plans&lt;/h3&gt;
&lt;p&gt;Entangled is ready to use, but it is not too user friendly yet. For one, we expect you to setup your own pipeline for building the document for public release. Most often this would be some static HTML generator using Pandoc or MkDocs. Alternatively you can use Docsify to serve a website directly from the Markdown sources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Getting started:&lt;/strong&gt; The problem for entry level users is that it may not be trivial to set these up. The current template for working with Pandoc requires Pandoc (duh), GNU Make, browser-sync, some form of inotify-wait, and of course, Entangled. We’d like to make it much easier to start working on your own projects, so we’d like to bring this set of requirements back to just Entangled.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Templates:&lt;/strong&gt; We should provide easy to use starting templates for a set of popular document generators. The one currently still unmentioned being Sphinx. These templates should be initialized using an &lt;code&gt;entangled init&lt;/code&gt; sub-command.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single file mode&lt;/strong&gt;: The default operation of Entangled should be a single file mode (most probably &lt;code&gt;README.md&lt;/code&gt;), and work out of the box with no configuration. Imagine a Github repository with just a &lt;code&gt;README&lt;/code&gt; (and a &lt;code&gt;LICENSE&lt;/code&gt; and a &lt;code&gt;CITATION.cff&lt;/code&gt; and a &lt;code&gt;.editorconfig&lt;/code&gt; and a … oh you get the point!) and a Github Action tacked on to generate the Github.io pages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible code presentation:&lt;/strong&gt; in the publicized output code cells are currently static. At the very least Noweb references should be clickable. Other features could include: links to the tangled output, be able to view the code in expanded form.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Help is appreciated! Entangled is primarily developed in Haskell, though no skill in Haskell is required for example to create templates for working with Entangled. Pandoc filters can be developed in Python. In particular the filter for interacting with Jupyter could use some fresh ideas.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;About the author: I’m (among other things) the developer of&lt;/em&gt; &lt;a href=&quot;https://entangled.github.io/&quot;&gt;&lt;em&gt;Entangled, a Literate Programming framework and toolset&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. The main goal of this blog-post is to convince you that existing tools for Literate Programming are not yet ready to serve the needs of the broader scientific community.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_E5I_DM8KaxUxkDNf-4dd728e6.D3u-ChMJ.webp" medium="image"/><author>Johan Hidding</author></item><item><title>Visual Storytelling for data science</title><link>https://blog2.esciencecenter.nl/posts/2021-06-17---visual-storytelling-for-data-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-06-17---visual-storytelling-for-data-science</guid><description>&lt;p&gt;][Maarten van Meersbergen]·Jun 7, 2021&lt;/p&gt;
&lt;p&gt;When conducting research, the data collected can in itself be exciting and meaningful, but when it is presented as spreadsheets or bullet points it can be too boring or difficult to understand for the intended audience. Telling a visual story with data is not trivial however, depending on the level of expertise of your readers, you should choose your storyline structure well.&lt;/p&gt;
&lt;p&gt;The excellent paper &lt;a href=&quot;https://ieeexplore.ieee.org/document/5613452&quot;&gt;Narrative Visualization: Telling Stories with Data&lt;/a&gt; by Edward Segel and Jeffrey Heer provides some good insights on this. The main takeaway from this paper I’d like to share is this:&lt;/p&gt;
&lt;p&gt;Author-driven** VS &lt;strong&gt;reader-driven&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Consider if you want to tell a ‘fixed’ story, or if you want the user to discover new stories based on the data you are providing. If telling a fixed story is what you want, an interactive slideshow would be a good option. Interactively ‘playing’ with the data on a slide-by-slide basis could build the reader’s trust in the author’s analysis, but the author’s conclusions are leading here.&lt;/p&gt;
&lt;p&gt;Interactive slideshow — Martini glass structure — Drill down story, images from &lt;a href=&quot;https://ieeexplore.ieee.org/document/5613452&quot;&gt;Narrative Visualization: Telling Stories with Data&lt;/a&gt; by Edward Segel and Jeffrey HeerIn a more reader-driven discovery scenario, more interaction is definitely needed, and a martini-glass-structure is likely a good option. Provide a ‘narrow’ authored storyline at first to explain a possible interaction with the data for tutorial purposes, and then open up options to let the user discover new stories on their own. This allows the user to learn about the possibilities without getting overwhelmed, but gives them the freedom to discover their own stories.&lt;/p&gt;
&lt;p&gt;Depending on your intended audience, a drill-down story structure could also be an interesting option. You provide a theme for all of the stories you present, but the user can choose which one they are interested in at their leisure. If your intended audience has enough expertise in both the subject matter and the interactive methods to display your data, letting them examine all of the interactive options for themselves from the start can be beneficial. Providing multiple starting points like this can allow for variations in user’s interests, which could then provide an inlet into other stories they would normally be less interested in.&lt;/p&gt;
&lt;h2 id=&quot;escience-application-of-visual-storytelling&quot;&gt;eScience application of Visual Storytelling&lt;/h2&gt;
&lt;p&gt;At the eScience center, we are actively working on visual storytelling applications for scientific purposes. We have three recent examples:&lt;/p&gt;
&lt;h3 id=&quot;climate-science&quot;&gt;Climate Science&lt;/h3&gt;
&lt;p&gt;In the European H2020 funded &lt;a href=&quot;https://climatestorylines.eu/&quot;&gt;RECEIPT&lt;/a&gt; (REmote Climate Effects and their Impact on European sustainability, Policy and Trade) project, we use storytelling as a framework for scientific discovery, modeling and communication. Many complex interactions between climate change in remote (non-EU) areas of the world and their impact on the EU cannot be easily communicated to policy makers and the public. Yet, a drought in South America or a flood in Asia can have major impacts on the European economy, or on the food supply that reaches our tables. The storytelling application we are developing allows the RECEIPT scientists to create storylines that link map locations and map-based data (displayed with &lt;a href=&quot;https://github.com/TerriaJS/terriajs&quot;&gt;TerriaJS&lt;/a&gt;) with text, images and custom graphs (created with &lt;a href=&quot;https://vega.github.io/&quot;&gt;Vega&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the RECEIPT climate impact story application, we are using the &lt;strong&gt;drill-down-story&lt;/strong&gt; structure. We Provide the common theme of climate changes in remote areas with impact on the EU, but we are letting the user decide what areas of the globe and/or what sectors they are most interested in, be that Agriculture, Finance, International Cooperation, Manufacturing or Coastal Infrastructure. This should provide an in* for many different users, hopefully educating many potential users about the possible impacts of climate change.&lt;/p&gt;
&lt;p&gt;A screenshot from the RECEIPT prototype visual storytelling interface.&lt;/p&gt;
&lt;h3 id=&quot;archeology-and-art-history&quot;&gt;Archeology and Art History&lt;/h3&gt;
&lt;p&gt;In the Via Appia: Revisited project, we are developing a storytelling application for 3d pointclouds (using &lt;a href=&quot;https://github.com/potree/potree&quot;&gt;potree.js)&lt;/a&gt;. The goals of the project are to show the history of art and the (virtual) archeological reconstruction of monuments on the &lt;em&gt;Via Appia Antica&lt;/em&gt;, an ancient Roman highway near Rome itself.&lt;/p&gt;
&lt;p&gt;We will make two versions of this application with different storyline structures. The first instance will be a museum exhibit, where users will interact with physical *forward &lt;em&gt;and&lt;/em&gt; back *buttons to interact with the application. We’ve chosen the &lt;strong&gt;interactive slideshow&lt;/strong&gt; approach for the story structure to simplify the user interface and make sure nothing can go wrong, as well as to allow our authors (the researchers and artists responsible for the exhibit) to carefully craft the narratives.&lt;/p&gt;
&lt;p&gt;The second instance of the application will be a public website, where users from the web can explore the Via Appia on their own. To guide the users towards interesting discoveries, we will adopt the &lt;strong&gt;martini-glass structure&lt;/strong&gt; here. First, we will offer the same storylines as in the museum exhibit, but after these storylines have finished, we open up the interactivity and will let users explore the site on their own.&lt;/p&gt;
&lt;p&gt;An screenshot of the Via Appia: Revisited (early alpha) application&lt;/p&gt;
&lt;h3 id=&quot;medical-imaging&quot;&gt;Medical Imaging&lt;/h3&gt;
&lt;p&gt;Vistories / CLUE — Gapminder visualizationAnother application area for visual storytelling we explored is medical imaging. The goal of this project was to see if we could improve the communication and support the building of trust between medical experts using Visual Storytelling techniques.&lt;/p&gt;
&lt;p&gt;Our starting point was &lt;a href=&quot;https://gapminder.caleydoapp.org/#clue_graph=clue_gapminder0&amp;#x26;clue_state=30&amp;#x26;clue=P&amp;#x26;clue_slide=41&quot;&gt;Vistories / CLUE&lt;/a&gt;, a library that uses interaction provenance as a basis for the authoring of Visual Storylines. The idea was that there could be an opportunity to increase the level of trust between a decision maker (the doctor planning treatment) and an expert doing analysis (a radiologist in the lab) by allowing the analysing expert to author a report directly from the tools used to analyse the images, with preservation of the links back to the data. This could then allow the decision maker to directly access the original analysis, and even directly try out alternate hypotheses or measurements. In this application, the &lt;strong&gt;martini-glass structure&lt;/strong&gt; is also used to guide the users at first, but allow more freedom afterwards.&lt;/p&gt;
&lt;p&gt;In the sister-blog to this one, we’d like to tell you more about the use of *provenance *for these (and other) purposes. Please read on &lt;a href=&quot;https://blog2.esciencecenter.nl/konmari-for-science-tidying-up-provenance-aabed5da593&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;Combining data, narratives and visuals can bring powerful messages forward in a way that fact, numbers and data alone can not. Visual stories allow us to be more inclusive, to connect better to our audience, and most importantly, to be more &lt;strong&gt;memorable&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At the eScience Center, we do really like to be remembered by both the scientists that we work with, and by their intended audience as well. Visual storytelling is one of the ways in which we try to achieve this.&lt;/p&gt;</description><pubDate>Thu, 17 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;][Maarten van Meersbergen]·Jun 7, 2021&lt;/p&gt;
&lt;p&gt;When conducting research, the data collected can in itself be exciting and meaningful, but when it is presented as spreadsheets or bullet points it can be too boring or difficult to understand for the intended audience. Telling a visual story with data is not trivial however, depending on the level of expertise of your readers, you should choose your storyline structure well.&lt;/p&gt;
&lt;p&gt;The excellent paper &lt;a href=&quot;https://ieeexplore.ieee.org/document/5613452&quot;&gt;Narrative Visualization: Telling Stories with Data&lt;/a&gt; by Edward Segel and Jeffrey Heer provides some good insights on this. The main takeaway from this paper I’d like to share is this:&lt;/p&gt;
&lt;p&gt;Author-driven** VS &lt;strong&gt;reader-driven&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Consider if you want to tell a ‘fixed’ story, or if you want the user to discover new stories based on the data you are providing. If telling a fixed story is what you want, an interactive slideshow would be a good option. Interactively ‘playing’ with the data on a slide-by-slide basis could build the reader’s trust in the author’s analysis, but the author’s conclusions are leading here.&lt;/p&gt;
&lt;p&gt;Interactive slideshow — Martini glass structure — Drill down story, images from &lt;a href=&quot;https://ieeexplore.ieee.org/document/5613452&quot;&gt;Narrative Visualization: Telling Stories with Data&lt;/a&gt; by Edward Segel and Jeffrey HeerIn a more reader-driven discovery scenario, more interaction is definitely needed, and a martini-glass-structure is likely a good option. Provide a ‘narrow’ authored storyline at first to explain a possible interaction with the data for tutorial purposes, and then open up options to let the user discover new stories on their own. This allows the user to learn about the possibilities without getting overwhelmed, but gives them the freedom to discover their own stories.&lt;/p&gt;
&lt;p&gt;Depending on your intended audience, a drill-down story structure could also be an interesting option. You provide a theme for all of the stories you present, but the user can choose which one they are interested in at their leisure. If your intended audience has enough expertise in both the subject matter and the interactive methods to display your data, letting them examine all of the interactive options for themselves from the start can be beneficial. Providing multiple starting points like this can allow for variations in user’s interests, which could then provide an inlet into other stories they would normally be less interested in.&lt;/p&gt;
&lt;h2 id=&quot;escience-application-of-visual-storytelling&quot;&gt;eScience application of Visual Storytelling&lt;/h2&gt;
&lt;p&gt;At the eScience center, we are actively working on visual storytelling applications for scientific purposes. We have three recent examples:&lt;/p&gt;
&lt;h3 id=&quot;climate-science&quot;&gt;Climate Science&lt;/h3&gt;
&lt;p&gt;In the European H2020 funded &lt;a href=&quot;https://climatestorylines.eu/&quot;&gt;RECEIPT&lt;/a&gt; (REmote Climate Effects and their Impact on European sustainability, Policy and Trade) project, we use storytelling as a framework for scientific discovery, modeling and communication. Many complex interactions between climate change in remote (non-EU) areas of the world and their impact on the EU cannot be easily communicated to policy makers and the public. Yet, a drought in South America or a flood in Asia can have major impacts on the European economy, or on the food supply that reaches our tables. The storytelling application we are developing allows the RECEIPT scientists to create storylines that link map locations and map-based data (displayed with &lt;a href=&quot;https://github.com/TerriaJS/terriajs&quot;&gt;TerriaJS&lt;/a&gt;) with text, images and custom graphs (created with &lt;a href=&quot;https://vega.github.io/&quot;&gt;Vega&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the RECEIPT climate impact story application, we are using the &lt;strong&gt;drill-down-story&lt;/strong&gt; structure. We Provide the common theme of climate changes in remote areas with impact on the EU, but we are letting the user decide what areas of the globe and/or what sectors they are most interested in, be that Agriculture, Finance, International Cooperation, Manufacturing or Coastal Infrastructure. This should provide an in* for many different users, hopefully educating many potential users about the possible impacts of climate change.&lt;/p&gt;
&lt;p&gt;A screenshot from the RECEIPT prototype visual storytelling interface.&lt;/p&gt;
&lt;h3 id=&quot;archeology-and-art-history&quot;&gt;Archeology and Art History&lt;/h3&gt;
&lt;p&gt;In the Via Appia: Revisited project, we are developing a storytelling application for 3d pointclouds (using &lt;a href=&quot;https://github.com/potree/potree&quot;&gt;potree.js)&lt;/a&gt;. The goals of the project are to show the history of art and the (virtual) archeological reconstruction of monuments on the &lt;em&gt;Via Appia Antica&lt;/em&gt;, an ancient Roman highway near Rome itself.&lt;/p&gt;
&lt;p&gt;We will make two versions of this application with different storyline structures. The first instance will be a museum exhibit, where users will interact with physical *forward &lt;em&gt;and&lt;/em&gt; back *buttons to interact with the application. We’ve chosen the &lt;strong&gt;interactive slideshow&lt;/strong&gt; approach for the story structure to simplify the user interface and make sure nothing can go wrong, as well as to allow our authors (the researchers and artists responsible for the exhibit) to carefully craft the narratives.&lt;/p&gt;
&lt;p&gt;The second instance of the application will be a public website, where users from the web can explore the Via Appia on their own. To guide the users towards interesting discoveries, we will adopt the &lt;strong&gt;martini-glass structure&lt;/strong&gt; here. First, we will offer the same storylines as in the museum exhibit, but after these storylines have finished, we open up the interactivity and will let users explore the site on their own.&lt;/p&gt;
&lt;p&gt;An screenshot of the Via Appia: Revisited (early alpha) application&lt;/p&gt;
&lt;h3 id=&quot;medical-imaging&quot;&gt;Medical Imaging&lt;/h3&gt;
&lt;p&gt;Vistories / CLUE — Gapminder visualizationAnother application area for visual storytelling we explored is medical imaging. The goal of this project was to see if we could improve the communication and support the building of trust between medical experts using Visual Storytelling techniques.&lt;/p&gt;
&lt;p&gt;Our starting point was &lt;a href=&quot;https://gapminder.caleydoapp.org/#clue_graph=clue_gapminder0&amp;#x26;clue_state=30&amp;#x26;clue=P&amp;#x26;clue_slide=41&quot;&gt;Vistories / CLUE&lt;/a&gt;, a library that uses interaction provenance as a basis for the authoring of Visual Storylines. The idea was that there could be an opportunity to increase the level of trust between a decision maker (the doctor planning treatment) and an expert doing analysis (a radiologist in the lab) by allowing the analysing expert to author a report directly from the tools used to analyse the images, with preservation of the links back to the data. This could then allow the decision maker to directly access the original analysis, and even directly try out alternate hypotheses or measurements. In this application, the &lt;strong&gt;martini-glass structure&lt;/strong&gt; is also used to guide the users at first, but allow more freedom afterwards.&lt;/p&gt;
&lt;p&gt;In the sister-blog to this one, we’d like to tell you more about the use of *provenance *for these (and other) purposes. Please read on &lt;a href=&quot;https://blog2.esciencecenter.nl/konmari-for-science-tidying-up-provenance-aabed5da593&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h2&gt;
&lt;p&gt;Combining data, narratives and visuals can bring powerful messages forward in a way that fact, numbers and data alone can not. Visual stories allow us to be more inclusive, to connect better to our audience, and most importantly, to be more &lt;strong&gt;memorable&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At the eScience Center, we do really like to be remembered by both the scientists that we work with, and by their intended audience as well. Visual storytelling is one of the ways in which we try to achieve this.&lt;/p&gt;</content:encoded><author>Maarten van Meersbergen</author></item><item><title>#KonMari for Science? Tidying up Provenance…</title><link>https://blog2.esciencecenter.nl/posts/2021-06-14---konmari-for-science-tidying-up-provenance</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-06-14---konmari-for-science-tidying-up-provenance</guid><description>&lt;p&gt;The term provenance mostly originates from the art world, where it aids in authenticating historical objects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The primary purpose of tracing the provenance of an object or entity is normally to provide contextual and circumstantial evidence for its original production or discovery, by establishing, as far as practicable, its later history, especially the sequences of its formal ownership, custody and places of storage. The practice has a particular &lt;strong&gt;value&lt;/strong&gt; in helping authenticate objects.” (&lt;a href=&quot;https://en.wikipedia.org/wiki/Provenance&quot;&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The potential of provenance tracking as-standard has been identified by people far outside the art world, particularly by scientists. After all, tracing the source and transformations that led to a particular piece of data has clear implications for the reproduction of scientific results that sits at the heart of the scientific method. While the experimentalist’s trusty lab book has been the primary means of recording such information, the increasing use of computers in data generation and analysis has provided a natural drive towards more automated means of keeping track.&lt;/p&gt;
&lt;p&gt;This is great, because if keeping track of the provenance can be automated, we can record everything, right? Well, maybe not everything, but a lot indeed. For example, the provenance in a Jupyter Notebook (&lt;a href=&quot;https://www.db-thueringen.de/receive/dbt_mods_00040396&quot;&gt;ProvBook&lt;/a&gt;), the provenance in visual exploration (&lt;a href=&quot;https://onlinelibrary.wiley.com/doi/pdf/10.1111/cgf.12925?casa_token=Tmhtt4kxbLAAAAAA%3AXp0U4C7KCfCScGrGX_gE_2kuxyOSiHZrKqNrUV2XnjSGzF6uaLnx90zTEO_sznL-28CLNhBa3HB4CoG9jA&quot;&gt;CLUE&lt;/a&gt;), and workflow provenance (&lt;a href=&quot;https://direct.mit.edu/dint/article/2/1-2/108/10003/FAIR-Computational-Workflows&quot;&gt;FAIR Computational Workflows&lt;/a&gt;). However, provenance is always stored for a purpose, even if the purpose is that it might be useful later on. Quite similar actually to collecting things at home.&lt;/p&gt;
&lt;p&gt;Your house might be filled with stuff that you regularly use, sometimes use, think is beautiful, has emotional value, might come in handy someday, or just haven’t had the time to throw out yet. The thing is, if you collect too much stuff at home you run the risk of not knowing what you have in your home anymore or where you stored it. By the time you need the thing that might come in handy someday, you cannot seem to find it or it turns out to be so outdated that you need to buy a new one.&lt;/p&gt;
&lt;p&gt;Something similar might happen with saving data and provenance. Saving data does not necessarily mean that it will be re-used later on. The more we save, the less overview we have of what is really important or valuable. This overview could be provided by using machine learning to dig through the data, but this is not magic either. Exhaust data can feel like a messy attic, there might be something valuable there, but machine learning requires the tedious work of &lt;a href=&quot;https://towardsdatascience.com/how-to-work-with-someone-elses-data-f33485d79ed4&quot;&gt;cleaning and processing the data&lt;/a&gt;, before you might get something out of it.&lt;/p&gt;
&lt;p&gt;In this blog we share some lessons learned about provenance in science and philosophize on how &lt;a href=&quot;https://konmari.com/&quot;&gt;Marie Kondo&lt;/a&gt;, a world-renowned tidying expert, could teach us some lessons that might be valuable for science as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;921&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pdCYToZHSFGsbRDku6oONA-366217b0.BoHx5c6u_ppoKs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Finding something valuable in here will take some time… (Photo by Cristina Gottardi on Unsplash)&lt;/p&gt;
&lt;p&gt;Some people have the natural tendency to tidy up things, whereas others feel like children whose parents tell them to tidy up their rooms, while they actually want to go play outside.&lt;/p&gt;
&lt;p&gt;A way to tidy up automatically tracked provenance is by providing tools that enable the presentation of provenance for easy human assessment. An example of this is &lt;a href=&quot;https://github.com/Sheeba-Samuel/ProvBook&quot;&gt;ProvBook&lt;/a&gt;, which can automatically track the provenance in a &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter Notebook&lt;/a&gt; and enables sharing and easy viewing of the cell history in a notebook (saved in the &lt;a href=&quot;https://www.db-thueringen.de/receive/dbt_mods_00040396&quot;&gt;REPRODUCE-ME ontology&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;provbook-provenance-of-the-notebook&quot;&gt;&lt;a href=&quot;https://figshare.com/articles/media/ProvBook_Provenance_of_the_Notebook/6401096?source=post_page-----aabed5da593---------------------------------------&quot;&gt;ProvBook: Provenance of the Notebook&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;provbook-provenance-of-the-notebookthis-is-the-demo-video-for-the-introduction-of-provbook-provbook-is-an-extension&quot;&gt;ProvBook: Provenance of the Notebook.This is the demo video for the introduction of ProvBook. ProvBook is an extension…&lt;/h3&gt;
&lt;p&gt;figshare.com&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://onlinelibrary.wiley.com/doi/pdf/10.1111/cgf.12925?casa_token=swxhYSB8GwwAAAAA%3A8uLR0LZORrq2haxpBS3kcMY-JEGNDmGKes4wRaqkoURjD641X9WpVuj-UoMKMLJvbBYiAs0akKr9amnj&quot;&gt;Gratzl et al&lt;/a&gt;. take this idea of presenting provenance tracking one step further for &lt;a href=&quot;https://blog.esciencecenter.nl/visual-storytelling-for-data-science-2f9ef8a27474&quot;&gt;visual story telling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1020&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lX4tPi4pqtcp1IgRKr-aKw-6003612e.CiwTPtVM_18XAzi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you like, you can try it out here.&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;exploration mode&lt;/strong&gt;, for example while exploring data in a visualization tool, the provenance (user actions) is automatically tracked. Then in the &lt;strong&gt;authoring mode&lt;/strong&gt;, the provenance is presented to the person who performed the exploration, who is given the option to create a visual story from it. This story can then be used to communicate to others how you gained insight while exploring the visualization, by using the &lt;strong&gt;presentation mode&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1276&quot; height=&quot;693&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uMeyOX5M5jKIVLppjpZgAA-d894935d.DcUUqQsn_ZMWCwc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From Visual Exploration to Storytelling and Back Again (S. Gratzl et al, 2016)&lt;/p&gt;
&lt;p&gt;From the presentation mode you can switch back to the exploration mode and start a new branch of explorations from the last or any of the previous time points in the tracked provenance. Theoretically this sounds great, but in practice it is quite hard to make a tool that presents the automatically tracked provenance in an easy and efficient human readable format. So the question is whether the value outweighs the work that needs to be done either by the person viewing the exploration or by the person creating the visual story.&lt;/p&gt;
&lt;p&gt;In terms of tidying up provenance, the realm of computational workflows deserves a lot of credit as well, where concerted efforts in standardization produced the now ubiquitous &lt;a href=&quot;https://www.w3.org/TR/prov-overview/&quot;&gt;W3C PROV model&lt;/a&gt; and its family of ontologies. A key development in this field is the strict separation of the recorded workflow execution (&lt;em&gt;retrospective provenance&lt;/em&gt;) from the workflow specification (&lt;em&gt;prospective provenance&lt;/em&gt;). The prospective provenance is the high level description of the scientific procedure, whereas the retrospective provenance is the ‘exhaust’ collection of all fine-grained execution details we mentioned earlier. The creation of prospective provenance can be viewed as an attempt to distill the scientifically crucial and useful “story” out, leaving the remaining residue (retrospective provenance) that is more specific and cluttered.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1054&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YvOryy1NoYPq361GOK7aVg-908d75fb.T-e17BEG_ZV4pFz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Prospective versus retrospective provenance? (Photos by Bernard Hermant and Sammy Williams on Unsplash )&lt;/p&gt;
&lt;p&gt;But where do you store all this provenance once you have it? It could of course just lie around on your hard drive or local cluster but if you want to participate in open science then it would be good to publish it. In the semantic web/linked data space there are a number of ways available, such as packaging it up in a &lt;a href=&quot;https://www.researchobject.org/ro-crate/&quot;&gt;Research Object Crate&lt;/a&gt; and publishing it e.g. to the &lt;a href=&quot;https://workflowhub.eu/&quot;&gt;workflowhub registry&lt;/a&gt;, or by publishing the RDF description of your workflow as one or more &lt;a href=&quot;https://blog.esciencecenter.nl/nano-publish-your-research-with-python-b81aa54eb1a2&quot;&gt;nanopublications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are great efforts, but what if you are one of those people that would rather play outside then tidy up your room? Funding agencies can of course play the role of the parent, demanding that research objects and provenance is being saved for possible re-use, adding another checkbox to the long list of boxes that researchers already need to check. The question is, does this really work? Or do we end up with something that seems neat on the outside, but is more like children stuffing their toys anywhere in boxes in their rooms, just to make it look tidy? While underneath the surface, the boxes are a colorful mixture of all sorts of toys in which it is hard to find that specific toy that they must have later on…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-RQR9OMVtltNMGBAQHS0ng-f2dd9525.C2UIrrR5_Z2fxqa2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Photo by Nareeta Martin on Unsplash)&lt;/p&gt;
&lt;p&gt;In her book “Spark Joy”, &lt;a href=&quot;https://konmari.com/&quot;&gt;Marie Kondo&lt;/a&gt; mentions that most people tidy up by moving stuff from one room to another, occasionally throwing some things away. This does not seem to lead anywhere, since there is no system behind it. Her method is much more thorough and requires people to make choices. There is no gray area, you either keep something and cherish it or throw it away. The trick is to focus on the things you would like to keep, the rest can go. The way you decide on what to keep is to learn what sparks joy inside you. You go through everything you collected in your house, based on categories, ordered in a way that was designed to slowly teach you what sparks joy inside you.&lt;/p&gt;
&lt;p&gt;What is key here, is that for people following this method, tidying up changes from a painful process of saying goodbye, to an inner journey discovering who they are, what they like and what fits them. This does not only provide an inner drive to tidy up their house, but changes their mindset with respect to &lt;a href=&quot;https://ntnuopen.ntnu.no/ntnu-xmlui/handle/11250/2754612&quot;&gt;future decisions on what to buy&lt;/a&gt;. Knowing who they are and having overview in their home, they think twice before buying something new, because they cherish what they have in their home. In a way, it provides a sense of direction and relieves them from the fear of missing out.&lt;/p&gt;
&lt;p&gt;Is there a lesson to learn here for science? Well, maybe there is.&lt;/p&gt;
&lt;p&gt;First of all, in the past couple of decennia, the focus in science has been more on quantity then on quality, pushed by funding agencies counting the number of publications as a metric for good science. As a result, a lot of publications were written and scientific literature to date is like a home so full of stuff that even scientists themselves have trouble keeping the overview and determining the current state-of-the-art in human knowledge. Is the solution then changing the metrics? Or adding more metrics? Or will this mostly lead to a different form of &lt;a href=&quot;https://www.investopedia.com/terms/c/consumerism.asp&quot;&gt;consumerism&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;868&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NMKBcvriZFShx8COTneP_A-f118c2a3.DvwD_1WH_2NXB4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Goodhart’s Law Explained ( Source )&lt;/p&gt;
&lt;p&gt;Maybe a more thorough approach is required, making clear choices on what to keep and get rid of the rest. But who needs to make this decision and based on what?&lt;/p&gt;
&lt;p&gt;What the #KonMari method does, is teach people how to make choices that are in line with their “inner joy”, so people themselves are able to make the choices that fit best. In translating the work of Kondo, another phrase was considered as the central question. Instead of “does it spark joy?”, the phrase “does it speak to your heart?” was considered as a translation for &lt;em&gt;tokimeku&lt;/em&gt;, which can be understood as “how does it move the &lt;em&gt;kokoro&lt;/em&gt; (heart / mind)?” (&lt;a href=&quot;https://spectrajournal.org/articles/10.21061/spectra.v7i2.146/&quot;&gt;Tokimeku: The Poetics of Marie Kondo’s KonMari Method&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TT22KUEpnXuvE_hwJ6g9TQ-7ca18d90.DEhd5cDI_Z1TPTyP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Photo by Aziz Acharki on Unsplash)&lt;/p&gt;
&lt;p&gt;Well, this is not something we can use in science, because science is all about reasoning and has nothing to do with the heart or mind… Yes, that is one way to look at it, but if you have read the book “ &lt;a href=&quot;https://www.goodreads.com/book/show/599317.Hare_Brain_Tortoise_Mind&quot;&gt;Hare brain, Tortoise Mind&lt;/a&gt; ”, you might want to reconsider this. The quick thinking hare brain is what we would use for reasoning, whereas the tortoise mind could be described as intuition, the inner drive, sudden inspiration, or a spark of creativity. Both are important, but if you think about it, most of the big leaps in science came from people with an inner drive, following their intuition, not seldom against the main stream in academia.&lt;/p&gt;
&lt;p&gt;So, to recap, what can we learn from all of this with respect to provenance? Maybe, that we should be careful that saving or publishing data and provenance does not become another box to check for already overloaded researchers. Maybe, the less is more approach of Marie Kondo could spark a little joy in the lives of researchers, and free up some time to learn how to use their tortoise mind. Provenance should be saved if there is value in saving it, and if we save it, we should cherish it for human knowledge, communicate it clearly and make sure people can use it. Either for reproducibility purposes or communicating findings or insights, such as in visual story telling. What is required is a mindset change from &lt;a href=&quot;https://www.investopedia.com/terms/c/consumerism.asp&quot;&gt;consumerism&lt;/a&gt; to value (that which moves the &lt;em&gt;kokoro)&lt;/em&gt; for science, and methods and tools that aid this.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1321&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iWIvBdVdJayjhRx4NlXEUw-d2394d7f.SzZBKfMd_17zwWx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Photo by Fahrul Azmi on Unsplash)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With thanks to Jiri Kosinka, Carlos Martinez-Ortiz, and Lourens Veen.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Mon, 14 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The term provenance mostly originates from the art world, where it aids in authenticating historical objects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The primary purpose of tracing the provenance of an object or entity is normally to provide contextual and circumstantial evidence for its original production or discovery, by establishing, as far as practicable, its later history, especially the sequences of its formal ownership, custody and places of storage. The practice has a particular &lt;strong&gt;value&lt;/strong&gt; in helping authenticate objects.” (&lt;a href=&quot;https://en.wikipedia.org/wiki/Provenance&quot;&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The potential of provenance tracking as-standard has been identified by people far outside the art world, particularly by scientists. After all, tracing the source and transformations that led to a particular piece of data has clear implications for the reproduction of scientific results that sits at the heart of the scientific method. While the experimentalist’s trusty lab book has been the primary means of recording such information, the increasing use of computers in data generation and analysis has provided a natural drive towards more automated means of keeping track.&lt;/p&gt;
&lt;p&gt;This is great, because if keeping track of the provenance can be automated, we can record everything, right? Well, maybe not everything, but a lot indeed. For example, the provenance in a Jupyter Notebook (&lt;a href=&quot;https://www.db-thueringen.de/receive/dbt_mods_00040396&quot;&gt;ProvBook&lt;/a&gt;), the provenance in visual exploration (&lt;a href=&quot;https://onlinelibrary.wiley.com/doi/pdf/10.1111/cgf.12925?casa_token=Tmhtt4kxbLAAAAAA%3AXp0U4C7KCfCScGrGX_gE_2kuxyOSiHZrKqNrUV2XnjSGzF6uaLnx90zTEO_sznL-28CLNhBa3HB4CoG9jA&quot;&gt;CLUE&lt;/a&gt;), and workflow provenance (&lt;a href=&quot;https://direct.mit.edu/dint/article/2/1-2/108/10003/FAIR-Computational-Workflows&quot;&gt;FAIR Computational Workflows&lt;/a&gt;). However, provenance is always stored for a purpose, even if the purpose is that it might be useful later on. Quite similar actually to collecting things at home.&lt;/p&gt;
&lt;p&gt;Your house might be filled with stuff that you regularly use, sometimes use, think is beautiful, has emotional value, might come in handy someday, or just haven’t had the time to throw out yet. The thing is, if you collect too much stuff at home you run the risk of not knowing what you have in your home anymore or where you stored it. By the time you need the thing that might come in handy someday, you cannot seem to find it or it turns out to be so outdated that you need to buy a new one.&lt;/p&gt;
&lt;p&gt;Something similar might happen with saving data and provenance. Saving data does not necessarily mean that it will be re-used later on. The more we save, the less overview we have of what is really important or valuable. This overview could be provided by using machine learning to dig through the data, but this is not magic either. Exhaust data can feel like a messy attic, there might be something valuable there, but machine learning requires the tedious work of &lt;a href=&quot;https://towardsdatascience.com/how-to-work-with-someone-elses-data-f33485d79ed4&quot;&gt;cleaning and processing the data&lt;/a&gt;, before you might get something out of it.&lt;/p&gt;
&lt;p&gt;In this blog we share some lessons learned about provenance in science and philosophize on how &lt;a href=&quot;https://konmari.com/&quot;&gt;Marie Kondo&lt;/a&gt;, a world-renowned tidying expert, could teach us some lessons that might be valuable for science as well.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;921&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pdCYToZHSFGsbRDku6oONA-366217b0.BoHx5c6u_ppoKs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Finding something valuable in here will take some time… (Photo by Cristina Gottardi on Unsplash)&lt;/p&gt;
&lt;p&gt;Some people have the natural tendency to tidy up things, whereas others feel like children whose parents tell them to tidy up their rooms, while they actually want to go play outside.&lt;/p&gt;
&lt;p&gt;A way to tidy up automatically tracked provenance is by providing tools that enable the presentation of provenance for easy human assessment. An example of this is &lt;a href=&quot;https://github.com/Sheeba-Samuel/ProvBook&quot;&gt;ProvBook&lt;/a&gt;, which can automatically track the provenance in a &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter Notebook&lt;/a&gt; and enables sharing and easy viewing of the cell history in a notebook (saved in the &lt;a href=&quot;https://www.db-thueringen.de/receive/dbt_mods_00040396&quot;&gt;REPRODUCE-ME ontology&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;provbook-provenance-of-the-notebook&quot;&gt;&lt;a href=&quot;https://figshare.com/articles/media/ProvBook_Provenance_of_the_Notebook/6401096?source=post_page-----aabed5da593---------------------------------------&quot;&gt;ProvBook: Provenance of the Notebook&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;provbook-provenance-of-the-notebookthis-is-the-demo-video-for-the-introduction-of-provbook-provbook-is-an-extension&quot;&gt;ProvBook: Provenance of the Notebook.This is the demo video for the introduction of ProvBook. ProvBook is an extension…&lt;/h3&gt;
&lt;p&gt;figshare.com&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://onlinelibrary.wiley.com/doi/pdf/10.1111/cgf.12925?casa_token=swxhYSB8GwwAAAAA%3A8uLR0LZORrq2haxpBS3kcMY-JEGNDmGKes4wRaqkoURjD641X9WpVuj-UoMKMLJvbBYiAs0akKr9amnj&quot;&gt;Gratzl et al&lt;/a&gt;. take this idea of presenting provenance tracking one step further for &lt;a href=&quot;https://blog.esciencecenter.nl/visual-storytelling-for-data-science-2f9ef8a27474&quot;&gt;visual story telling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1020&quot; height=&quot;563&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lX4tPi4pqtcp1IgRKr-aKw-6003612e.CiwTPtVM_18XAzi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you like, you can try it out here.&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;exploration mode&lt;/strong&gt;, for example while exploring data in a visualization tool, the provenance (user actions) is automatically tracked. Then in the &lt;strong&gt;authoring mode&lt;/strong&gt;, the provenance is presented to the person who performed the exploration, who is given the option to create a visual story from it. This story can then be used to communicate to others how you gained insight while exploring the visualization, by using the &lt;strong&gt;presentation mode&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1276&quot; height=&quot;693&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uMeyOX5M5jKIVLppjpZgAA-d894935d.DcUUqQsn_ZMWCwc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From Visual Exploration to Storytelling and Back Again (S. Gratzl et al, 2016)&lt;/p&gt;
&lt;p&gt;From the presentation mode you can switch back to the exploration mode and start a new branch of explorations from the last or any of the previous time points in the tracked provenance. Theoretically this sounds great, but in practice it is quite hard to make a tool that presents the automatically tracked provenance in an easy and efficient human readable format. So the question is whether the value outweighs the work that needs to be done either by the person viewing the exploration or by the person creating the visual story.&lt;/p&gt;
&lt;p&gt;In terms of tidying up provenance, the realm of computational workflows deserves a lot of credit as well, where concerted efforts in standardization produced the now ubiquitous &lt;a href=&quot;https://www.w3.org/TR/prov-overview/&quot;&gt;W3C PROV model&lt;/a&gt; and its family of ontologies. A key development in this field is the strict separation of the recorded workflow execution (&lt;em&gt;retrospective provenance&lt;/em&gt;) from the workflow specification (&lt;em&gt;prospective provenance&lt;/em&gt;). The prospective provenance is the high level description of the scientific procedure, whereas the retrospective provenance is the ‘exhaust’ collection of all fine-grained execution details we mentioned earlier. The creation of prospective provenance can be viewed as an attempt to distill the scientifically crucial and useful “story” out, leaving the remaining residue (retrospective provenance) that is more specific and cluttered.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1054&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YvOryy1NoYPq361GOK7aVg-908d75fb.T-e17BEG_ZV4pFz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Prospective versus retrospective provenance? (Photos by Bernard Hermant and Sammy Williams on Unsplash )&lt;/p&gt;
&lt;p&gt;But where do you store all this provenance once you have it? It could of course just lie around on your hard drive or local cluster but if you want to participate in open science then it would be good to publish it. In the semantic web/linked data space there are a number of ways available, such as packaging it up in a &lt;a href=&quot;https://www.researchobject.org/ro-crate/&quot;&gt;Research Object Crate&lt;/a&gt; and publishing it e.g. to the &lt;a href=&quot;https://workflowhub.eu/&quot;&gt;workflowhub registry&lt;/a&gt;, or by publishing the RDF description of your workflow as one or more &lt;a href=&quot;https://blog.esciencecenter.nl/nano-publish-your-research-with-python-b81aa54eb1a2&quot;&gt;nanopublications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are great efforts, but what if you are one of those people that would rather play outside then tidy up your room? Funding agencies can of course play the role of the parent, demanding that research objects and provenance is being saved for possible re-use, adding another checkbox to the long list of boxes that researchers already need to check. The question is, does this really work? Or do we end up with something that seems neat on the outside, but is more like children stuffing their toys anywhere in boxes in their rooms, just to make it look tidy? While underneath the surface, the boxes are a colorful mixture of all sorts of toys in which it is hard to find that specific toy that they must have later on…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-RQR9OMVtltNMGBAQHS0ng-f2dd9525.C2UIrrR5_Z2fxqa2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Photo by Nareeta Martin on Unsplash)&lt;/p&gt;
&lt;p&gt;In her book “Spark Joy”, &lt;a href=&quot;https://konmari.com/&quot;&gt;Marie Kondo&lt;/a&gt; mentions that most people tidy up by moving stuff from one room to another, occasionally throwing some things away. This does not seem to lead anywhere, since there is no system behind it. Her method is much more thorough and requires people to make choices. There is no gray area, you either keep something and cherish it or throw it away. The trick is to focus on the things you would like to keep, the rest can go. The way you decide on what to keep is to learn what sparks joy inside you. You go through everything you collected in your house, based on categories, ordered in a way that was designed to slowly teach you what sparks joy inside you.&lt;/p&gt;
&lt;p&gt;What is key here, is that for people following this method, tidying up changes from a painful process of saying goodbye, to an inner journey discovering who they are, what they like and what fits them. This does not only provide an inner drive to tidy up their house, but changes their mindset with respect to &lt;a href=&quot;https://ntnuopen.ntnu.no/ntnu-xmlui/handle/11250/2754612&quot;&gt;future decisions on what to buy&lt;/a&gt;. Knowing who they are and having overview in their home, they think twice before buying something new, because they cherish what they have in their home. In a way, it provides a sense of direction and relieves them from the fear of missing out.&lt;/p&gt;
&lt;p&gt;Is there a lesson to learn here for science? Well, maybe there is.&lt;/p&gt;
&lt;p&gt;First of all, in the past couple of decennia, the focus in science has been more on quantity then on quality, pushed by funding agencies counting the number of publications as a metric for good science. As a result, a lot of publications were written and scientific literature to date is like a home so full of stuff that even scientists themselves have trouble keeping the overview and determining the current state-of-the-art in human knowledge. Is the solution then changing the metrics? Or adding more metrics? Or will this mostly lead to a different form of &lt;a href=&quot;https://www.investopedia.com/terms/c/consumerism.asp&quot;&gt;consumerism&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;868&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NMKBcvriZFShx8COTneP_A-f118c2a3.DvwD_1WH_2NXB4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Goodhart’s Law Explained ( Source )&lt;/p&gt;
&lt;p&gt;Maybe a more thorough approach is required, making clear choices on what to keep and get rid of the rest. But who needs to make this decision and based on what?&lt;/p&gt;
&lt;p&gt;What the #KonMari method does, is teach people how to make choices that are in line with their “inner joy”, so people themselves are able to make the choices that fit best. In translating the work of Kondo, another phrase was considered as the central question. Instead of “does it spark joy?”, the phrase “does it speak to your heart?” was considered as a translation for &lt;em&gt;tokimeku&lt;/em&gt;, which can be understood as “how does it move the &lt;em&gt;kokoro&lt;/em&gt; (heart / mind)?” (&lt;a href=&quot;https://spectrajournal.org/articles/10.21061/spectra.v7i2.146/&quot;&gt;Tokimeku: The Poetics of Marie Kondo’s KonMari Method&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TT22KUEpnXuvE_hwJ6g9TQ-7ca18d90.DEhd5cDI_Z1TPTyP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Photo by Aziz Acharki on Unsplash)&lt;/p&gt;
&lt;p&gt;Well, this is not something we can use in science, because science is all about reasoning and has nothing to do with the heart or mind… Yes, that is one way to look at it, but if you have read the book “ &lt;a href=&quot;https://www.goodreads.com/book/show/599317.Hare_Brain_Tortoise_Mind&quot;&gt;Hare brain, Tortoise Mind&lt;/a&gt; ”, you might want to reconsider this. The quick thinking hare brain is what we would use for reasoning, whereas the tortoise mind could be described as intuition, the inner drive, sudden inspiration, or a spark of creativity. Both are important, but if you think about it, most of the big leaps in science came from people with an inner drive, following their intuition, not seldom against the main stream in academia.&lt;/p&gt;
&lt;p&gt;So, to recap, what can we learn from all of this with respect to provenance? Maybe, that we should be careful that saving or publishing data and provenance does not become another box to check for already overloaded researchers. Maybe, the less is more approach of Marie Kondo could spark a little joy in the lives of researchers, and free up some time to learn how to use their tortoise mind. Provenance should be saved if there is value in saving it, and if we save it, we should cherish it for human knowledge, communicate it clearly and make sure people can use it. Either for reproducibility purposes or communicating findings or insights, such as in visual story telling. What is required is a mindset change from &lt;a href=&quot;https://www.investopedia.com/terms/c/consumerism.asp&quot;&gt;consumerism&lt;/a&gt; to value (that which moves the &lt;em&gt;kokoro)&lt;/em&gt; for science, and methods and tools that aid this.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1321&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iWIvBdVdJayjhRx4NlXEUw-d2394d7f.SzZBKfMd_17zwWx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Photo by Fahrul Azmi on Unsplash)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With thanks to Jiri Kosinka, Carlos Martinez-Ortiz, and Lourens Veen.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_pdCYToZHSFGsbRDku6oONA-366217b0.BoHx5c6u.jpeg" medium="image"/><author>Adriënne Mendrik</author></item><item><title>(Nano)Publish your research with Python</title><link>https://blog2.esciencecenter.nl/posts/2021-05-31---nanopublish-your-research-with-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-05-31---nanopublish-your-research-with-python</guid><description>&lt;h2 id=&quot;using-nanopub-a-high-level-user-friendly-python-interface-to-the-nanopublication-network&quot;&gt;Using nanopub, a high-level, user-friendly python interface to the nanopublication network&lt;/h2&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;For example, if you want to e.g. search for all nanopublications containing the text Picoides*:&lt;/p&gt;
&lt;p&gt;which returns two results both pointing to the example nanopublication we just discussed:&lt;/p&gt;
&lt;p&gt;{‘np’: ‘&lt;a href=&quot;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA&amp;#x27;&quot;&gt;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA’&lt;/a&gt;, ‘description’: ‘Inter-species interaction of Picoides villosus with Ips’, ‘date’: ‘2020-12-24T10:51:43.931Z’}
{‘np’: ‘&lt;a href=&quot;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA&amp;#x27;&quot;&gt;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA’&lt;/a&gt;, ‘description’: ‘Picoides villosus’, ‘date’: ‘2020-12-24T10:51:43.931Z’}You can then fetch a specific nanopublication directly using its URI:&lt;/p&gt;
&lt;p&gt;This snippet will fetch the nanopublication we discussed earlier, about the interaction of the bird and the beetle, and print the contents of its assertion. Of course, you are not limited to simple text searches. The library has several search methods, including finding nanopubs with a given triple pattern — you can find detailed documentation &lt;a href=&quot;https://nanopub.readthedocs.io/en/latest/searching.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;hold-on-i-want-to-publish-nanopublications-of-my-own&quot;&gt;Hold on, I want to publish Nanopublications of my own!&lt;/h2&gt;
&lt;p&gt;To publish to the nanopub server you need to set up your profile. This allows the nanopub server to identify you. Run the following interactive command (on the command line):&lt;/p&gt;
&lt;p&gt;setup_nanopub_profileIt will add and store RSA keys to sign your nanopublications, publish a nanopublication with your name and ORCID iD to declare that you are using using these RSA keys, and store your ORCID iD to automatically add as author to the provenance of any nanopublication you will publish using this library.&lt;/p&gt;
&lt;p&gt;You can then publish a quick claim:&lt;/p&gt;
&lt;p&gt;Published to &lt;a href=&quot;http://purl.org/np/RA47eJP2UBJCWuJ324c6Qw0OwtCb8wCrprwSk39am7xck&quot;&gt;http://purl.org/np/RA47eJP2UBJCWuJ324c6Qw0OwtCb8wCrprwSk39am7xck&lt;/a&gt;View the resulting nanopublication &lt;a href=&quot;http://purl.org/np/RA47eJP2UBJCWuJ324c6Qw0OwtCb8wCrprwSk39am7xck&quot;&gt;here&lt;/a&gt;. Note that the URI of your nanopublication is a signed hash of its contents, making its authorship verifiable and enforcing its immutability — known as a &lt;a href=&quot;https://doi.org/10.1007/978-3-319-07443-6_27&quot;&gt;trusty URI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Or, to leverage the true power of semantic technologies, you can build your own RDF graph of triples and publish that:&lt;/p&gt;
&lt;p&gt;The above builds a graph containing a single triple that states (essentially) the concept pointed to by &lt;code&gt;www.example.org/timbernerslee&lt;/code&gt;is of type Person. We use the &lt;a href=&quot;https://github.com/RDFLib/rdflib&quot;&gt;rdflib&lt;/a&gt; library to build the graph, but this is already a dependency of nanopub. A Publication object is then created, using that graph as its assertion, and finally published using the NanopubClient as before. The code produces the following output:&lt;/p&gt;
&lt;p&gt;Published to &lt;a href=&quot;http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ&quot;&gt;http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ&lt;/a&gt;You can view the resulting nanopublication &lt;a href=&quot;http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;outlook&quot;&gt;Outlook&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;nanopub&lt;/code&gt; makes interacting with nanopublications quite intuitive for those with sufficient RDF and python skills. For all others we foresee tools built around &lt;code&gt;nanopub&lt;/code&gt; that make it intuitive for domain-experts (but not RDF-experts) to make use of the nanopublication network.&lt;/p&gt;
&lt;p&gt;There are a couple of those already in the making:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nanotate-tool/nanotate&quot;&gt;nanotate&lt;/a&gt;: Create nanopublications from annotations in PDF-files made with &lt;a href=&quot;https://web.hypothes.is/&quot;&gt;hypothes.is&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fair-workflows/fairworkflows&quot;&gt;fairworkflows&lt;/a&gt;: Support the construction, manipulation and publishing of FAIR scientific workflows using semantic technologies. This is developed as part of the wider &lt;a href=&quot;https://www.esciencecenter.nl/projects/fair-is-as-fair-does/&quot;&gt;FAIR is as FAIR does&lt;/a&gt; project at the eScience Center.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The python &lt;code&gt;nanopub&lt;/code&gt; library provides a high-level, user-friendly python interface for the nanopub server, making it easy to publish and search small scientific publications. We created this library to bring nanopublishing to python users and we’re keen to help people make use of it.&lt;/p&gt;
&lt;p&gt;Consider how &lt;a href=&quot;http://nanopub.org/wordpress/&quot;&gt;nanopublications&lt;/a&gt; might fit in with your field, and feel free to &lt;a href=&quot;https://github.com/fair-workflows/nanopub&quot;&gt;try the library out&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;The quality of this text was greatly improved by the suggestions of &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;, Tobias Kuhn, &lt;a href=&quot;https://orcid.org/0000-0003-1711-7961&quot;&gt;Arnold Kuzniar&lt;/a&gt;, Lars Ridder, &lt;a href=&quot;https://medium.com/@pab.rod&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt;, and &lt;a href=&quot;https://medium.com/@s.verhoeven&quot;&gt;Stefan Verhoeven&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Mon, 31 May 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;using-nanopub-a-high-level-user-friendly-python-interface-to-the-nanopublication-network&quot;&gt;Using nanopub, a high-level, user-friendly python interface to the nanopublication network&lt;/h2&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;For example, if you want to e.g. search for all nanopublications containing the text Picoides*:&lt;/p&gt;
&lt;p&gt;which returns two results both pointing to the example nanopublication we just discussed:&lt;/p&gt;
&lt;p&gt;{‘np’: ‘&lt;a href=&quot;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA&amp;#x27;&quot;&gt;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA’&lt;/a&gt;, ‘description’: ‘Inter-species interaction of Picoides villosus with Ips’, ‘date’: ‘2020-12-24T10:51:43.931Z’}
{‘np’: ‘&lt;a href=&quot;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA&amp;#x27;&quot;&gt;http://purl.org/np/RAMzGwLotMRSQTHRCS15B6hvuYSyEupGnxZaFU3EmcItA’&lt;/a&gt;, ‘description’: ‘Picoides villosus’, ‘date’: ‘2020-12-24T10:51:43.931Z’}You can then fetch a specific nanopublication directly using its URI:&lt;/p&gt;
&lt;p&gt;This snippet will fetch the nanopublication we discussed earlier, about the interaction of the bird and the beetle, and print the contents of its assertion. Of course, you are not limited to simple text searches. The library has several search methods, including finding nanopubs with a given triple pattern — you can find detailed documentation &lt;a href=&quot;https://nanopub.readthedocs.io/en/latest/searching.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;hold-on-i-want-to-publish-nanopublications-of-my-own&quot;&gt;Hold on, I want to publish Nanopublications of my own!&lt;/h2&gt;
&lt;p&gt;To publish to the nanopub server you need to set up your profile. This allows the nanopub server to identify you. Run the following interactive command (on the command line):&lt;/p&gt;
&lt;p&gt;setup_nanopub_profileIt will add and store RSA keys to sign your nanopublications, publish a nanopublication with your name and ORCID iD to declare that you are using using these RSA keys, and store your ORCID iD to automatically add as author to the provenance of any nanopublication you will publish using this library.&lt;/p&gt;
&lt;p&gt;You can then publish a quick claim:&lt;/p&gt;
&lt;p&gt;Published to &lt;a href=&quot;http://purl.org/np/RA47eJP2UBJCWuJ324c6Qw0OwtCb8wCrprwSk39am7xck&quot;&gt;http://purl.org/np/RA47eJP2UBJCWuJ324c6Qw0OwtCb8wCrprwSk39am7xck&lt;/a&gt;View the resulting nanopublication &lt;a href=&quot;http://purl.org/np/RA47eJP2UBJCWuJ324c6Qw0OwtCb8wCrprwSk39am7xck&quot;&gt;here&lt;/a&gt;. Note that the URI of your nanopublication is a signed hash of its contents, making its authorship verifiable and enforcing its immutability — known as a &lt;a href=&quot;https://doi.org/10.1007/978-3-319-07443-6_27&quot;&gt;trusty URI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Or, to leverage the true power of semantic technologies, you can build your own RDF graph of triples and publish that:&lt;/p&gt;
&lt;p&gt;The above builds a graph containing a single triple that states (essentially) the concept pointed to by &lt;code&gt;www.example.org/timbernerslee&lt;/code&gt;is of type Person. We use the &lt;a href=&quot;https://github.com/RDFLib/rdflib&quot;&gt;rdflib&lt;/a&gt; library to build the graph, but this is already a dependency of nanopub. A Publication object is then created, using that graph as its assertion, and finally published using the NanopubClient as before. The code produces the following output:&lt;/p&gt;
&lt;p&gt;Published to &lt;a href=&quot;http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ&quot;&gt;http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ&lt;/a&gt;You can view the resulting nanopublication &lt;a href=&quot;http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;outlook&quot;&gt;Outlook&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;nanopub&lt;/code&gt; makes interacting with nanopublications quite intuitive for those with sufficient RDF and python skills. For all others we foresee tools built around &lt;code&gt;nanopub&lt;/code&gt; that make it intuitive for domain-experts (but not RDF-experts) to make use of the nanopublication network.&lt;/p&gt;
&lt;p&gt;There are a couple of those already in the making:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nanotate-tool/nanotate&quot;&gt;nanotate&lt;/a&gt;: Create nanopublications from annotations in PDF-files made with &lt;a href=&quot;https://web.hypothes.is/&quot;&gt;hypothes.is&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/fair-workflows/fairworkflows&quot;&gt;fairworkflows&lt;/a&gt;: Support the construction, manipulation and publishing of FAIR scientific workflows using semantic technologies. This is developed as part of the wider &lt;a href=&quot;https://www.esciencecenter.nl/projects/fair-is-as-fair-does/&quot;&gt;FAIR is as FAIR does&lt;/a&gt; project at the eScience Center.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The python &lt;code&gt;nanopub&lt;/code&gt; library provides a high-level, user-friendly python interface for the nanopub server, making it easy to publish and search small scientific publications. We created this library to bring nanopublishing to python users and we’re keen to help people make use of it.&lt;/p&gt;
&lt;p&gt;Consider how &lt;a href=&quot;http://nanopub.org/wordpress/&quot;&gt;nanopublications&lt;/a&gt; might fit in with your field, and feel free to &lt;a href=&quot;https://github.com/fair-workflows/nanopub&quot;&gt;try the library out&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;acknowledgements&quot;&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;The quality of this text was greatly improved by the suggestions of &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;, Tobias Kuhn, &lt;a href=&quot;https://orcid.org/0000-0003-1711-7961&quot;&gt;Arnold Kuzniar&lt;/a&gt;, Lars Ridder, &lt;a href=&quot;https://medium.com/@pab.rod&quot;&gt;Pablo Rodríguez-Sánchez&lt;/a&gt;, and &lt;a href=&quot;https://medium.com/@s.verhoeven&quot;&gt;Stefan Verhoeven&lt;/a&gt;.&lt;/p&gt;</content:encoded><author>Robin Richardson</author></item><item><title>Lesson development blitz</title><link>https://blog2.esciencecenter.nl/posts/2021-05-11---lesson-development-blitz</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-05-11---lesson-development-blitz</guid><description>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Testing lessons**&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;Lesson development blitz&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;220&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lesson-development-blitz-8f0c1255.47MG0Sfm_ZbfnD9.webp&quot; srcset=&quot;&quot;&gt;
designed by freepik &lt;a href=&quot;https://stories.freepik.com/&quot;&gt;https://stories.freepik.com/&lt;/a&gt;The coordinator asks some of the researchers in the community to use the tutorial and to report any issues or bugs. It is also recommended to organize training activities using the tutorial and gather feedback from participants. The outputs of the evaluation are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a list of issues and bugs.&lt;/li&gt;
&lt;li&gt;whether the tutorial needs polishing (go to step 4) or is ready for a release (go to step 6).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;6. Release​&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lesson development blitz&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;236&quot; height=&quot;227&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lesson-development-blitz-99c8f53f.Daq9_2xG_2qddg.webp&quot; srcset=&quot;&quot;&gt;
designed by freepik &lt;a href=&quot;https://stories.freepik.com/&quot;&gt;https://stories.freepik.com/&lt;/a&gt;The tutorial is released on GitHub in a beta version and published on Zenodo. With this version, the lessons can be used for broader teaching and contributions.&lt;/p&gt;
&lt;h2 id=&quot;at-the-end-of-the-blitz-&quot;&gt;At the end of the blitz …&lt;/h2&gt;
&lt;p&gt;Our development blitz took about one week and the ESMValTool tutorial was released in Beta-version.&lt;/p&gt;
&lt;p&gt;Like every procedure, a development blitz has some pros and cons. A development blitz increases focus​, creates satisfaction and good feeling​, helps communication​, and spreads best practices in the community. However, it may lead to disappointment​, needs lots of commitment​ and slows down decision making​.&lt;/p&gt;
&lt;h2 id=&quot;interesting-readings&quot;&gt;Interesting readings:&lt;/h2&gt;
&lt;p&gt;The Carpentries Curriculum Development Handbook provides guides on designing and developing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;different parts of a tutorial, see &lt;a href=&quot;https://carpentries.github.io/curriculum-development/our-curriculum-structure.html#episodes&quot;&gt;episodes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;objectives and scope, see &lt;a href=&quot;https://carpentries.github.io/curriculum-development/developing-content.html&quot;&gt;developing content&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;development and release stages, see &lt;a href=&quot;https://carpentries.github.io/curriculum-development/the-lesson-life-cycle.html&quot;&gt;lesson life-cycle&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here, some blog posts about blitz planning that might be of interest:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@Future__Friendly/conducting-a-blitz-sprint-19f563bfc9ba&quot;&gt;Conducting a blitz sprint​&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.luxoft.com/blog/sprokhorenko/blitz-planning/&quot;&gt;Blitz planning​&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;acknowledgment&quot;&gt;Acknowledgment&lt;/h2&gt;
&lt;p&gt;Thanks to [Carlos Martinez-Ortiz], [Felipe], [Pablo Rodríguez-Sánchez] and [Tom Bakker] for their feedback.&lt;/p&gt;</description><pubDate>Tue, 11 May 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Testing lessons**&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;Lesson development blitz&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;220&quot; height=&quot;195&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lesson-development-blitz-8f0c1255.47MG0Sfm_ZbfnD9.webp&quot; srcset=&quot;&quot;&gt;
designed by freepik &lt;a href=&quot;https://stories.freepik.com/&quot;&gt;https://stories.freepik.com/&lt;/a&gt;The coordinator asks some of the researchers in the community to use the tutorial and to report any issues or bugs. It is also recommended to organize training activities using the tutorial and gather feedback from participants. The outputs of the evaluation are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a list of issues and bugs.&lt;/li&gt;
&lt;li&gt;whether the tutorial needs polishing (go to step 4) or is ready for a release (go to step 6).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;6. Release​&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Lesson development blitz&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;236&quot; height=&quot;227&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/lesson-development-blitz-99c8f53f.Daq9_2xG_2qddg.webp&quot; srcset=&quot;&quot;&gt;
designed by freepik &lt;a href=&quot;https://stories.freepik.com/&quot;&gt;https://stories.freepik.com/&lt;/a&gt;The tutorial is released on GitHub in a beta version and published on Zenodo. With this version, the lessons can be used for broader teaching and contributions.&lt;/p&gt;
&lt;h2 id=&quot;at-the-end-of-the-blitz-&quot;&gt;At the end of the blitz …&lt;/h2&gt;
&lt;p&gt;Our development blitz took about one week and the ESMValTool tutorial was released in Beta-version.&lt;/p&gt;
&lt;p&gt;Like every procedure, a development blitz has some pros and cons. A development blitz increases focus​, creates satisfaction and good feeling​, helps communication​, and spreads best practices in the community. However, it may lead to disappointment​, needs lots of commitment​ and slows down decision making​.&lt;/p&gt;
&lt;h2 id=&quot;interesting-readings&quot;&gt;Interesting readings:&lt;/h2&gt;
&lt;p&gt;The Carpentries Curriculum Development Handbook provides guides on designing and developing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;different parts of a tutorial, see &lt;a href=&quot;https://carpentries.github.io/curriculum-development/our-curriculum-structure.html#episodes&quot;&gt;episodes&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;objectives and scope, see &lt;a href=&quot;https://carpentries.github.io/curriculum-development/developing-content.html&quot;&gt;developing content&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;development and release stages, see &lt;a href=&quot;https://carpentries.github.io/curriculum-development/the-lesson-life-cycle.html&quot;&gt;lesson life-cycle&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here, some blog posts about blitz planning that might be of interest:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@Future__Friendly/conducting-a-blitz-sprint-19f563bfc9ba&quot;&gt;Conducting a blitz sprint​&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.luxoft.com/blog/sprokhorenko/blitz-planning/&quot;&gt;Blitz planning​&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;acknowledgment&quot;&gt;Acknowledgment&lt;/h2&gt;
&lt;p&gt;Thanks to [Carlos Martinez-Ortiz], [Felipe], [Pablo Rodríguez-Sánchez] and [Tom Bakker] for their feedback.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/lesson-development-blitz-99c8f53f.Daq9_2xG.png" medium="image"/><author>Fakhereh (Sarah) Alidoost</author></item><item><title>Using Rust for Scientific Numerical applications: Learning from Past Experiences</title><link>https://blog2.esciencecenter.nl/posts/2021-04-14---using-rust-for-scientific-numerical-applications-learning-fr</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-04-14---using-rust-for-scientific-numerical-applications-learning-fr</guid><description>&lt;p&gt;Every experienced programmer knows that both their productivity depends on the abstraction level of the language. The fewer lines of code you write, the fewer bugs you introduce.* However, an increase in abstraction often results in a higher runtime cost (code that needs to run extremely fast is often &lt;em&gt;very&lt;/em&gt; ugly). Rust &lt;a href=&quot;https://carette.xyz/posts/zero_cost_abstraction/&quot;&gt;zero-cost abstraction&lt;/a&gt; allows you to write more concise code by using a higher level abstraction without additional computing cost at runtime. *Rust *&lt;a href=&quot;https://doc.rust-lang.org/book/ch13-02-iterators.html&quot;&gt;&lt;em&gt;iterators&lt;/em&gt;&lt;/a&gt; are a great example of the power of Rust zero cost abstraction. &lt;em&gt;It is fair to mention that zero-cost abstraction is also central in C++.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How much effort is required to maintain the code?**&lt;/p&gt;
&lt;p&gt;If you have ever worked in a medium to large size C/Fortran code base, you certainly know how incredibly difficult and frustrating it can be to maintain it. A recurrent complaint among the programmers in these languages is the dreadful bugs related to unsafe memory management that can take days to trace and reproduce. Fortran programmers are famously known for having &lt;a href=&quot;https://nalgebra.org/&quot;&gt;segmentation faults&lt;/a&gt; for breakfast.&lt;/p&gt;
&lt;p&gt;The Rust type system stands out for its capabilities to rule out memory errors at runtime. The Rust &lt;a href=&quot;https://blog.logrocket.com/introducing-the-rust-borrow-checker/&quot;&gt;borrow checker&lt;/a&gt; is the killer feature that helps to eliminate all those memory bugs while still offering lightning-fast speed.&lt;/p&gt;
&lt;p&gt;Also, as mentioned previously, Rust’s zero cost abstraction allows you to keep a lean code base that is easier to maintain.&lt;/p&gt;
&lt;p&gt;***Note for C++ developer: ***&lt;em&gt;smart pointers partly alleviate the memory management issues, but the borrow checker can help you to extend the safety guarantees to multithreading code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How much effort is required to test the code and write documentation?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Writing documentation in C/C++/Fortran involved bringing a third-party tool like &lt;a href=&quot;https://www.doxygen.nl/index.html&quot;&gt;Doxygen&lt;/a&gt; that we need to install and add to our CMake zoo. Also, we need to learn this tool’s special syntax to write documentation and then pray that the documentation builds.&lt;/p&gt;
&lt;p&gt;Software documentation is essential for scientific code due to the volatile nature of scientific research. *Scientific software without documentation is not legacy code but dead code. *Given the high barrier imposed by traditional languages to write documentation, it is expected that most scientific software is stillborn due to the impossibility to understand what has been done, even by experts in the same field (or sometimes even by the person who wrote it).&lt;/p&gt;
&lt;p&gt;Documenting a Rust project only requires that you write the documentation in markdown inside the source code as shown in &lt;a href=&quot;https://github.com/felipeZ/eigenvalues/blob/master/src/lib.rs&quot;&gt;this example&lt;/a&gt;. Then you just need to run the &lt;code&gt;cargo doc&lt;/code&gt; command and that is it!&lt;/p&gt;
&lt;p&gt;Testing in C/C++/Fortran has a similar fate, they required third-party frameworks that need to be installed and added to CMake. Fortran is particularly painful for testing due to the lack of a standard testing framework, forcing programmers to maintain a bunch of scripts to call the binaries, parse the output, and check the results.&lt;/p&gt;
&lt;p&gt;Rust has a built-in system to test your code, with no third-party libraries. You can have &lt;a href=&quot;https://doc.rust-lang.org/nightly/rust-by-example/testing/unit_testing.html&quot;&gt;unit tests&lt;/a&gt; to check the functionality of a given module at a time, but also &lt;a href=&quot;https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html&quot;&gt;integration tests&lt;/a&gt; to check the public interface of your code. You can even run and test the &lt;a href=&quot;https://doc.rust-lang.org/rustdoc/documentation-tests.html&quot;&gt;examples in the documentation&lt;/a&gt;! In summary, writing and running tests is as effortless as you can get it.&lt;/p&gt;
&lt;p&gt;Lowering the barrier to write tests and documentation is an undervalued feature of Rust. I bet that we all agree that code without tests and documentation is short of useless.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I parallelize the application?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Using Rust for Scientific Numerical applications: Learning from Past Experiences&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;349&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/using-rust-for-scientific-numerical-appl-ab3f6590.Dl0JlQpe_2uet5c.webp&quot; srcset=&quot;&quot;&gt;
Image: courtesy of &lt;a href=&quot;https://www.instagram.com/qiadraws/&quot;&gt;Chiara Caratelli&lt;/a&gt;&lt;em&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/em&gt;*:* &lt;em&gt;due to my ignorance of the latest Rust developments on multi-node computing (&lt;/em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Message_Passing_Interface&quot;&gt;&lt;em&gt;MPI&lt;/em&gt;&lt;/a&gt;&lt;em&gt;) and GPU integration, I am going to blatantly ignore those two subjects.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Scientific simulations like weather prediction, protein binding, fluid dynamics, etc*.* are computationally intensive but often parallelizable (at least on paper!). It goes without saying that we want to make use of all cores available in a given machine. The standard approach is to use something like &lt;a href=&quot;https://www.openmp.org/&quot;&gt;OpenMP&lt;/a&gt; that consists of runtime libraries, compiler directives, &lt;em&gt;etc&lt;/em&gt;. to support shared-memory multithreading programming.&lt;/p&gt;
&lt;p&gt;A quite dreaded moment for scientific software developers is when the serial implementation is working and a new parallel version must be implemented. Seriously, parallel implementation in C/C+/Fortran means that all your &lt;a href=&quot;https://en.wikipedia.org/wiki/There_are_known_knowns&quot;&gt;unknown unknowns&lt;/a&gt; about unsafe memory management suddenly uncover all the obnoxious bugs that you didn’t know about until now, and that you need to track for endless hours.&lt;/p&gt;
&lt;p&gt;As a remedy for all that frustration and wasted time, Rust offers a novel approach coined as &lt;a href=&quot;https://doc.rust-lang.org/book/ch16-00-concurrency.html&quot;&gt;fearless concurrency&lt;/a&gt;. This concept refers to the possibility of writing parallel applications that are free of subtle bugs and can be refactored without introducing new bugs.&lt;/p&gt;
&lt;p&gt;But how does Rust achieve this marvelous formula? It turns out that the Rust type system and &lt;a href=&quot;https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html&quot;&gt;ownership system&lt;/a&gt; keep track of what is safe to share across threads, refusing to compile illegal concurrent memory transactions that would have resulted in runtime issues. So, the Rust compiler happily raises compilation errors whenever you are trying to use memory in an unsafe way instead of unleashing Godzilla in the middle of your simulation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Using Rust for Scientific Numerical applications: Learning from Past Experiences&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/using-rust-for-scientific-numerical-appl-622b6b49.DO8qr1Y8_Z1Mo3P.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@markuswinkler?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Markus Winkler&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since Rust is a system programming language, rather than choosing a single parallelism model, it allows multiple low level models like message-passing, share-state, &lt;em&gt;etc&lt;/em&gt;. The good news is that we don’t need to use the primitives ourselves, instead, we can use the community-provided libraries like &lt;a href=&quot;https://github.com/rayon-rs/rayon&quot;&gt;Rayon&lt;/a&gt; that build on top of those primitives. &lt;a href=&quot;https://github.com/rayon-rs/rayon&quot;&gt;Rayon&lt;/a&gt; offers powerful functionality like &lt;a href=&quot;https://docs.rs/rayon/1.5.0/rayon/iter/index.html&quot;&gt;parallel iterators&lt;/a&gt; that allow us to execute operations on the elements of an &lt;a href=&quot;https://doc.rust-lang.org/book/ch13-02-iterators.html&quot;&gt;iterator&lt;/a&gt; in parallel, with minimal changes in the source code.&lt;/p&gt;
&lt;p&gt;What is even better, you can use libraries like &lt;a href=&quot;https://github.com/rust-ndarray/ndarray&quot;&gt;ndarray&lt;/a&gt; that has a Numpy-style API to manipulate arrays, while simultaneously offering features like an interface to &lt;a href=&quot;https://github.com/rayon-rs/rayon&quot;&gt;Rayon&lt;/a&gt; to run your array operations in parallel.&lt;/p&gt;
&lt;h2 id=&quot;the-challenges-of-using-rust-for-scientific-applications&quot;&gt;The Challenges of using Rust for scientific applications&lt;/h2&gt;
&lt;p&gt;Rust is a promising language for scientific applications but there are several challenges that need to be overcome before the language can gain significant traction by the scientific community.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rust is a low-level language with many powerful features&lt;/strong&gt;. In other words, actually you do not learn Rust during a Saturday afternoon while drinking mojitos. It takes significant effort and time before you can start writing with confidence. Fortunately the Rust community is very open and welcoming and there are always people willing to help. Besides, the compiler has the most informative error messages that I have seen in any programming language. In short, the learning curve is steeper than Python, but you will have a single memory-safe language to rule them all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;There may be some functionality that is still missing or unstable&lt;/strong&gt;. The Rust ecosystem is growing rapidly and more people are coming out with great libraries. The community is always happy to help you to come up with a solution for your missing functionality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interoperability with C/C++&lt;/strong&gt;. We certainly do not want to rewrite everything from scratch, therefore we would like to reuse as much code as we can from C/C++. For the Rust community, smooth interoperability with C/C++ is a top priority.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;any-further-thoughts&quot;&gt;Any further thoughts?&lt;/h2&gt;
&lt;p&gt;I hope that I could give you an idea about using Rust for scientific software applications. Comments and thoughts are appreciated.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgement&quot;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;Thanks to Chiara Caratelli from providing the great drawings. Also my special thanks to [Florian Huber], [Carlos Martinez-Ortiz,] [Patrick Bos] and Tom Bakker for their help editing the text.&lt;/p&gt;</description><pubDate>Wed, 14 Apr 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every experienced programmer knows that both their productivity depends on the abstraction level of the language. The fewer lines of code you write, the fewer bugs you introduce.* However, an increase in abstraction often results in a higher runtime cost (code that needs to run extremely fast is often &lt;em&gt;very&lt;/em&gt; ugly). Rust &lt;a href=&quot;https://carette.xyz/posts/zero_cost_abstraction/&quot;&gt;zero-cost abstraction&lt;/a&gt; allows you to write more concise code by using a higher level abstraction without additional computing cost at runtime. *Rust *&lt;a href=&quot;https://doc.rust-lang.org/book/ch13-02-iterators.html&quot;&gt;&lt;em&gt;iterators&lt;/em&gt;&lt;/a&gt; are a great example of the power of Rust zero cost abstraction. &lt;em&gt;It is fair to mention that zero-cost abstraction is also central in C++.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How much effort is required to maintain the code?**&lt;/p&gt;
&lt;p&gt;If you have ever worked in a medium to large size C/Fortran code base, you certainly know how incredibly difficult and frustrating it can be to maintain it. A recurrent complaint among the programmers in these languages is the dreadful bugs related to unsafe memory management that can take days to trace and reproduce. Fortran programmers are famously known for having &lt;a href=&quot;https://nalgebra.org/&quot;&gt;segmentation faults&lt;/a&gt; for breakfast.&lt;/p&gt;
&lt;p&gt;The Rust type system stands out for its capabilities to rule out memory errors at runtime. The Rust &lt;a href=&quot;https://blog.logrocket.com/introducing-the-rust-borrow-checker/&quot;&gt;borrow checker&lt;/a&gt; is the killer feature that helps to eliminate all those memory bugs while still offering lightning-fast speed.&lt;/p&gt;
&lt;p&gt;Also, as mentioned previously, Rust’s zero cost abstraction allows you to keep a lean code base that is easier to maintain.&lt;/p&gt;
&lt;p&gt;***Note for C++ developer: ***&lt;em&gt;smart pointers partly alleviate the memory management issues, but the borrow checker can help you to extend the safety guarantees to multithreading code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How much effort is required to test the code and write documentation?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Writing documentation in C/C++/Fortran involved bringing a third-party tool like &lt;a href=&quot;https://www.doxygen.nl/index.html&quot;&gt;Doxygen&lt;/a&gt; that we need to install and add to our CMake zoo. Also, we need to learn this tool’s special syntax to write documentation and then pray that the documentation builds.&lt;/p&gt;
&lt;p&gt;Software documentation is essential for scientific code due to the volatile nature of scientific research. *Scientific software without documentation is not legacy code but dead code. *Given the high barrier imposed by traditional languages to write documentation, it is expected that most scientific software is stillborn due to the impossibility to understand what has been done, even by experts in the same field (or sometimes even by the person who wrote it).&lt;/p&gt;
&lt;p&gt;Documenting a Rust project only requires that you write the documentation in markdown inside the source code as shown in &lt;a href=&quot;https://github.com/felipeZ/eigenvalues/blob/master/src/lib.rs&quot;&gt;this example&lt;/a&gt;. Then you just need to run the &lt;code&gt;cargo doc&lt;/code&gt; command and that is it!&lt;/p&gt;
&lt;p&gt;Testing in C/C++/Fortran has a similar fate, they required third-party frameworks that need to be installed and added to CMake. Fortran is particularly painful for testing due to the lack of a standard testing framework, forcing programmers to maintain a bunch of scripts to call the binaries, parse the output, and check the results.&lt;/p&gt;
&lt;p&gt;Rust has a built-in system to test your code, with no third-party libraries. You can have &lt;a href=&quot;https://doc.rust-lang.org/nightly/rust-by-example/testing/unit_testing.html&quot;&gt;unit tests&lt;/a&gt; to check the functionality of a given module at a time, but also &lt;a href=&quot;https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html&quot;&gt;integration tests&lt;/a&gt; to check the public interface of your code. You can even run and test the &lt;a href=&quot;https://doc.rust-lang.org/rustdoc/documentation-tests.html&quot;&gt;examples in the documentation&lt;/a&gt;! In summary, writing and running tests is as effortless as you can get it.&lt;/p&gt;
&lt;p&gt;Lowering the barrier to write tests and documentation is an undervalued feature of Rust. I bet that we all agree that code without tests and documentation is short of useless.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do I parallelize the application?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Using Rust for Scientific Numerical applications: Learning from Past Experiences&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;349&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/using-rust-for-scientific-numerical-appl-ab3f6590.Dl0JlQpe_2uet5c.webp&quot; srcset=&quot;&quot;&gt;
Image: courtesy of &lt;a href=&quot;https://www.instagram.com/qiadraws/&quot;&gt;Chiara Caratelli&lt;/a&gt;&lt;em&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;/em&gt;*:* &lt;em&gt;due to my ignorance of the latest Rust developments on multi-node computing (&lt;/em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Message_Passing_Interface&quot;&gt;&lt;em&gt;MPI&lt;/em&gt;&lt;/a&gt;&lt;em&gt;) and GPU integration, I am going to blatantly ignore those two subjects.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Scientific simulations like weather prediction, protein binding, fluid dynamics, etc*.* are computationally intensive but often parallelizable (at least on paper!). It goes without saying that we want to make use of all cores available in a given machine. The standard approach is to use something like &lt;a href=&quot;https://www.openmp.org/&quot;&gt;OpenMP&lt;/a&gt; that consists of runtime libraries, compiler directives, &lt;em&gt;etc&lt;/em&gt;. to support shared-memory multithreading programming.&lt;/p&gt;
&lt;p&gt;A quite dreaded moment for scientific software developers is when the serial implementation is working and a new parallel version must be implemented. Seriously, parallel implementation in C/C+/Fortran means that all your &lt;a href=&quot;https://en.wikipedia.org/wiki/There_are_known_knowns&quot;&gt;unknown unknowns&lt;/a&gt; about unsafe memory management suddenly uncover all the obnoxious bugs that you didn’t know about until now, and that you need to track for endless hours.&lt;/p&gt;
&lt;p&gt;As a remedy for all that frustration and wasted time, Rust offers a novel approach coined as &lt;a href=&quot;https://doc.rust-lang.org/book/ch16-00-concurrency.html&quot;&gt;fearless concurrency&lt;/a&gt;. This concept refers to the possibility of writing parallel applications that are free of subtle bugs and can be refactored without introducing new bugs.&lt;/p&gt;
&lt;p&gt;But how does Rust achieve this marvelous formula? It turns out that the Rust type system and &lt;a href=&quot;https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html&quot;&gt;ownership system&lt;/a&gt; keep track of what is safe to share across threads, refusing to compile illegal concurrent memory transactions that would have resulted in runtime issues. So, the Rust compiler happily raises compilation errors whenever you are trying to use memory in an unsafe way instead of unleashing Godzilla in the middle of your simulation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Using Rust for Scientific Numerical applications: Learning from Past Experiences&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/using-rust-for-scientific-numerical-appl-622b6b49.DO8qr1Y8_Z1Mo3P.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@markuswinkler?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Markus Winkler&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Since Rust is a system programming language, rather than choosing a single parallelism model, it allows multiple low level models like message-passing, share-state, &lt;em&gt;etc&lt;/em&gt;. The good news is that we don’t need to use the primitives ourselves, instead, we can use the community-provided libraries like &lt;a href=&quot;https://github.com/rayon-rs/rayon&quot;&gt;Rayon&lt;/a&gt; that build on top of those primitives. &lt;a href=&quot;https://github.com/rayon-rs/rayon&quot;&gt;Rayon&lt;/a&gt; offers powerful functionality like &lt;a href=&quot;https://docs.rs/rayon/1.5.0/rayon/iter/index.html&quot;&gt;parallel iterators&lt;/a&gt; that allow us to execute operations on the elements of an &lt;a href=&quot;https://doc.rust-lang.org/book/ch13-02-iterators.html&quot;&gt;iterator&lt;/a&gt; in parallel, with minimal changes in the source code.&lt;/p&gt;
&lt;p&gt;What is even better, you can use libraries like &lt;a href=&quot;https://github.com/rust-ndarray/ndarray&quot;&gt;ndarray&lt;/a&gt; that has a Numpy-style API to manipulate arrays, while simultaneously offering features like an interface to &lt;a href=&quot;https://github.com/rayon-rs/rayon&quot;&gt;Rayon&lt;/a&gt; to run your array operations in parallel.&lt;/p&gt;
&lt;h2 id=&quot;the-challenges-of-using-rust-for-scientific-applications&quot;&gt;The Challenges of using Rust for scientific applications&lt;/h2&gt;
&lt;p&gt;Rust is a promising language for scientific applications but there are several challenges that need to be overcome before the language can gain significant traction by the scientific community.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rust is a low-level language with many powerful features&lt;/strong&gt;. In other words, actually you do not learn Rust during a Saturday afternoon while drinking mojitos. It takes significant effort and time before you can start writing with confidence. Fortunately the Rust community is very open and welcoming and there are always people willing to help. Besides, the compiler has the most informative error messages that I have seen in any programming language. In short, the learning curve is steeper than Python, but you will have a single memory-safe language to rule them all.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;There may be some functionality that is still missing or unstable&lt;/strong&gt;. The Rust ecosystem is growing rapidly and more people are coming out with great libraries. The community is always happy to help you to come up with a solution for your missing functionality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interoperability with C/C++&lt;/strong&gt;. We certainly do not want to rewrite everything from scratch, therefore we would like to reuse as much code as we can from C/C++. For the Rust community, smooth interoperability with C/C++ is a top priority.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;any-further-thoughts&quot;&gt;Any further thoughts?&lt;/h2&gt;
&lt;p&gt;I hope that I could give you an idea about using Rust for scientific software applications. Comments and thoughts are appreciated.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgement&quot;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;Thanks to Chiara Caratelli from providing the great drawings. Also my special thanks to [Florian Huber], [Carlos Martinez-Ortiz,] [Patrick Bos] and Tom Bakker for their help editing the text.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/using-rust-for-scientific-numerical-appl-ab3f6590.Dl0JlQpe.png" medium="image"/><author>Felipe</author></item><item><title>Can mathematical models predict the future?</title><link>https://blog2.esciencecenter.nl/posts/2021-03-18---can-mathematical-models-predict-the-future</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-03-18---can-mathematical-models-predict-the-future</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4000&quot; height=&quot;6000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_nCQRZRSdypw2jmuH-8bc780bd.7sAvCYMP_xxG8i.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by John Moeses Bauan on Unsplash&lt;/p&gt;
&lt;p&gt;Let me start right away with a question: do you think that the future can be predicted? When formulated like this, this question makes us think of crystal balls, palm reading, fortune tellers, … and ultimately invites us to answer with a loud and clear: &lt;em&gt;“no”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nevertheless, every day we read things like &lt;em&gt;“the average mean temperature will rise 0.5 ⁰C worldwide in the next ten years”&lt;/em&gt;, or &lt;em&gt;“the contagion curve of COVID-19 will start to flatten in the next 3 days”.&lt;/em&gt; And we read themwithout raising a single eyebrow. Indeed, these sentences evoke in us feelings of rigor and expert knowledge. But, are they not predictions about the future?&lt;/p&gt;
&lt;p&gt;If we dive into the foundations of this kind of forecasts, chances are that they had been obtained using mathematical models. Most likely, they will have error bars attached to them, and provide numerous caveats that, somehow, subtract some strength from the conclusions.&lt;/p&gt;
&lt;p&gt;Mathematical models are getting more attention than ever. The COVID-19 pandemic made them jump from the inner pages of specialized journals to the front pages of press and TV news. For audience and format reasons, the necessary details to understand the reach and limitations of these models are rarely mentioned. This may lead to a wrong impression about their power.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-mathematical-model&quot;&gt;What is a mathematical model?&lt;/h2&gt;
&lt;p&gt;==A model is a description of a phenomenon under study. A mathematical model just uses mathematical language in this description.==&lt;/p&gt;
&lt;p&gt;It sounds almost like a tongue-twister, but is actually anything but exotic. Even more, it is very likely you have worked with mathematical models before. Particularly in school. Do you remember those problems about compound interest? Or those about the movement of a projectile in physics class? Did your teachers not ask you to calculate the future evolution of a bank account or the time and place of the projectile’s impact?&lt;/p&gt;
&lt;p&gt;Contrary to what is often thought, mathematical models do not answer the question &lt;em&gt;“What will happen?”&lt;/em&gt;, but to a subtly different one: &lt;em&gt;“What would happen if…?”&lt;/em&gt;. This constitutes, simultaneously, the strength and the weakness of mathematical modeling.&lt;/p&gt;
&lt;p&gt;Let me illustrate my point with the example of a body in free fall. Perhaps you remember your own skepticism when, in school, your physics teacher told you that a feather and a cannonball free-falling from the same height touch the ground at the very same moment.&lt;/p&gt;
&lt;p&gt;Sounds strange, but it is rigorously true. In fact, it is so rigorously true, that if we just drop the word &lt;em&gt;“free”&lt;/em&gt; from &lt;em&gt;“free-falling”&lt;/em&gt;, the statement is not true anymore. Free falls require the absence of an atmosphere, and thus do not happen often in our daily life. Still skeptical? Check the video below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=KDp1tiUsZw8&quot;&gt;https://www.youtube.com/watch?v=KDp1tiUsZw8&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we try to apply the model of free-fall to the fall of an everyday object, we’ll soon see that its prediction fails miserably. We just used an inadequate model, because the free-fall model answers a question we don’t need to answer: &lt;em&gt;“what would happen if I let this object fall in the absence of an atmosphere?”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When we mathematicians build our models, we often start with a very simple one, and we keep adding features to it while we need them. When do we stop, then? When the model is sufficiently good. That is, when we are happy about the light it sheds onto the phenomenon under study.&lt;/p&gt;
&lt;p&gt;If we are interested in understanding the fall of a feather, the above-mentioned free-fall model will certainly not make us happy. If we add some drag terms to the model, accounting for the presence of an atmosphere, the results will be much better (although still not perfect, because there will always be small discrepancies between the predictions and the experiment).&lt;/p&gt;
&lt;p&gt;All models, no exception, are more or less sophisticated approximations of reality. But they are never perfect. Unfortunately, it is not always easy to quantify the precision of a mathematical model. As a consequence, it is also hard to communicate its limitations to a general audience.&lt;/p&gt;
&lt;h2 id=&quot;why-do-we-use-them&quot;&gt;Why do we use them?&lt;/h2&gt;
&lt;p&gt;If all mathematical models are approximations, why do we use them? There is a simple answer to this: we use them because they are useful. Models’ capacity of answering the question: &lt;em&gt;“What would happen if…”&lt;/em&gt;, makes them an excellent substitute for scientific experiments.&lt;/p&gt;
&lt;p&gt;In science, the experiment is the highest authority, but sometimes we have no choice but to not perform them. We either use a computational/mathematical model, or we are stuck. Some examples of this situation are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unfeasible experiments: such as studying a black hole on site.&lt;/li&gt;
&lt;li&gt;Costly or very hard experiments: such as studying plankton populations, a problem whose scale in space and time is, literally, oceanic and of the order of decades.&lt;/li&gt;
&lt;li&gt;Destructive or dangerous experiments: such as studying the effects of a earthquake on a city.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Models are also very useful to obtain visualizations that, otherwise, will be difficult or impossible to obtain experimentally. Think for instance of the movement of the wind around a turbine, with the pressure painted as color.&lt;/p&gt;
&lt;p&gt;Models also help us understanding. Even models with a very humble predictive power can be very useful to understand complex problems. For instance, thanks to a &lt;a href=&quot;https://blog.esciencecenter.nl/a-mathematician-in-quarantine-4555cfbf9f60&quot;&gt;very simple model of epidemic propagation&lt;/a&gt; from the 1920s we know that there are thresholds where the contagion becomes explosive. The model is useless if we want to know where exactly that threshold is, but it provides the very idea that such a threshold exists.&lt;/p&gt;
&lt;h2 id=&quot;mathematicians-cannot-predict-the-future&quot;&gt;Mathematicians cannot predict the future&lt;/h2&gt;
&lt;p&gt;Our initial question was: can the future be forecasted? No sensible person will ever answer &lt;em&gt;“yes, of course, always”&lt;/em&gt;. I hope to have convinced you that mathematicians, who most of the time are also sensible persons, neither will answer so.&lt;/p&gt;
&lt;p&gt;Science is, by its own nature, a fundamentally incomplete enterprise. This is true whether we use letters or formulas to write it. Mathematical models have to be consumed with no less than the same healthy skepticism we use with the weather forecast.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The quality of this text was greatly improved by the suggestions of &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@lourensveen&quot;&gt;Lourens Veen&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@f.huber&quot;&gt;Florian Huber&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is an adapted translation from an article the same author published in&lt;/em&gt; &lt;a href=&quot;https://theconversation.com/&quot;&gt;&lt;em&gt;The Conversation&lt;/em&gt;&lt;/a&gt; &lt;em&gt;under a Creative Commons license. If you can (and want to) read Spanish, visit the&lt;/em&gt; &lt;a href=&quot;https://theconversation.com/los-modelos-matematicos-no-predicen-el-futuro-pero-ayudan-a-entenderlo-147299&quot;&gt;&lt;em&gt;original article&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 18 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4000&quot; height=&quot;6000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_nCQRZRSdypw2jmuH-8bc780bd.7sAvCYMP_xxG8i.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by John Moeses Bauan on Unsplash&lt;/p&gt;
&lt;p&gt;Let me start right away with a question: do you think that the future can be predicted? When formulated like this, this question makes us think of crystal balls, palm reading, fortune tellers, … and ultimately invites us to answer with a loud and clear: &lt;em&gt;“no”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Nevertheless, every day we read things like &lt;em&gt;“the average mean temperature will rise 0.5 ⁰C worldwide in the next ten years”&lt;/em&gt;, or &lt;em&gt;“the contagion curve of COVID-19 will start to flatten in the next 3 days”.&lt;/em&gt; And we read themwithout raising a single eyebrow. Indeed, these sentences evoke in us feelings of rigor and expert knowledge. But, are they not predictions about the future?&lt;/p&gt;
&lt;p&gt;If we dive into the foundations of this kind of forecasts, chances are that they had been obtained using mathematical models. Most likely, they will have error bars attached to them, and provide numerous caveats that, somehow, subtract some strength from the conclusions.&lt;/p&gt;
&lt;p&gt;Mathematical models are getting more attention than ever. The COVID-19 pandemic made them jump from the inner pages of specialized journals to the front pages of press and TV news. For audience and format reasons, the necessary details to understand the reach and limitations of these models are rarely mentioned. This may lead to a wrong impression about their power.&lt;/p&gt;
&lt;h2 id=&quot;what-is-a-mathematical-model&quot;&gt;What is a mathematical model?&lt;/h2&gt;
&lt;p&gt;==A model is a description of a phenomenon under study. A mathematical model just uses mathematical language in this description.==&lt;/p&gt;
&lt;p&gt;It sounds almost like a tongue-twister, but is actually anything but exotic. Even more, it is very likely you have worked with mathematical models before. Particularly in school. Do you remember those problems about compound interest? Or those about the movement of a projectile in physics class? Did your teachers not ask you to calculate the future evolution of a bank account or the time and place of the projectile’s impact?&lt;/p&gt;
&lt;p&gt;Contrary to what is often thought, mathematical models do not answer the question &lt;em&gt;“What will happen?”&lt;/em&gt;, but to a subtly different one: &lt;em&gt;“What would happen if…?”&lt;/em&gt;. This constitutes, simultaneously, the strength and the weakness of mathematical modeling.&lt;/p&gt;
&lt;p&gt;Let me illustrate my point with the example of a body in free fall. Perhaps you remember your own skepticism when, in school, your physics teacher told you that a feather and a cannonball free-falling from the same height touch the ground at the very same moment.&lt;/p&gt;
&lt;p&gt;Sounds strange, but it is rigorously true. In fact, it is so rigorously true, that if we just drop the word &lt;em&gt;“free”&lt;/em&gt; from &lt;em&gt;“free-falling”&lt;/em&gt;, the statement is not true anymore. Free falls require the absence of an atmosphere, and thus do not happen often in our daily life. Still skeptical? Check the video below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=KDp1tiUsZw8&quot;&gt;https://www.youtube.com/watch?v=KDp1tiUsZw8&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we try to apply the model of free-fall to the fall of an everyday object, we’ll soon see that its prediction fails miserably. We just used an inadequate model, because the free-fall model answers a question we don’t need to answer: &lt;em&gt;“what would happen if I let this object fall in the absence of an atmosphere?”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When we mathematicians build our models, we often start with a very simple one, and we keep adding features to it while we need them. When do we stop, then? When the model is sufficiently good. That is, when we are happy about the light it sheds onto the phenomenon under study.&lt;/p&gt;
&lt;p&gt;If we are interested in understanding the fall of a feather, the above-mentioned free-fall model will certainly not make us happy. If we add some drag terms to the model, accounting for the presence of an atmosphere, the results will be much better (although still not perfect, because there will always be small discrepancies between the predictions and the experiment).&lt;/p&gt;
&lt;p&gt;All models, no exception, are more or less sophisticated approximations of reality. But they are never perfect. Unfortunately, it is not always easy to quantify the precision of a mathematical model. As a consequence, it is also hard to communicate its limitations to a general audience.&lt;/p&gt;
&lt;h2 id=&quot;why-do-we-use-them&quot;&gt;Why do we use them?&lt;/h2&gt;
&lt;p&gt;If all mathematical models are approximations, why do we use them? There is a simple answer to this: we use them because they are useful. Models’ capacity of answering the question: &lt;em&gt;“What would happen if…”&lt;/em&gt;, makes them an excellent substitute for scientific experiments.&lt;/p&gt;
&lt;p&gt;In science, the experiment is the highest authority, but sometimes we have no choice but to not perform them. We either use a computational/mathematical model, or we are stuck. Some examples of this situation are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unfeasible experiments: such as studying a black hole on site.&lt;/li&gt;
&lt;li&gt;Costly or very hard experiments: such as studying plankton populations, a problem whose scale in space and time is, literally, oceanic and of the order of decades.&lt;/li&gt;
&lt;li&gt;Destructive or dangerous experiments: such as studying the effects of a earthquake on a city.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Models are also very useful to obtain visualizations that, otherwise, will be difficult or impossible to obtain experimentally. Think for instance of the movement of the wind around a turbine, with the pressure painted as color.&lt;/p&gt;
&lt;p&gt;Models also help us understanding. Even models with a very humble predictive power can be very useful to understand complex problems. For instance, thanks to a &lt;a href=&quot;https://blog.esciencecenter.nl/a-mathematician-in-quarantine-4555cfbf9f60&quot;&gt;very simple model of epidemic propagation&lt;/a&gt; from the 1920s we know that there are thresholds where the contagion becomes explosive. The model is useless if we want to know where exactly that threshold is, but it provides the very idea that such a threshold exists.&lt;/p&gt;
&lt;h2 id=&quot;mathematicians-cannot-predict-the-future&quot;&gt;Mathematicians cannot predict the future&lt;/h2&gt;
&lt;p&gt;Our initial question was: can the future be forecasted? No sensible person will ever answer &lt;em&gt;“yes, of course, always”&lt;/em&gt;. I hope to have convinced you that mathematicians, who most of the time are also sensible persons, neither will answer so.&lt;/p&gt;
&lt;p&gt;Science is, by its own nature, a fundamentally incomplete enterprise. This is true whether we use letters or formulas to write it. Mathematical models have to be consumed with no less than the same healthy skepticism we use with the weather forecast.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The quality of this text was greatly improved by the suggestions of &lt;a href=&quot;https://egpbos.medium.com/&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@lourensveen&quot;&gt;Lourens Veen&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@f.huber&quot;&gt;Florian Huber&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This article is an adapted translation from an article the same author published in&lt;/em&gt; &lt;a href=&quot;https://theconversation.com/&quot;&gt;&lt;em&gt;The Conversation&lt;/em&gt;&lt;/a&gt; &lt;em&gt;under a Creative Commons license. If you can (and want to) read Spanish, visit the&lt;/em&gt; &lt;a href=&quot;https://theconversation.com/los-modelos-matematicos-no-predicen-el-futuro-pero-ayudan-a-entenderlo-147299&quot;&gt;&lt;em&gt;original article&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_nCQRZRSdypw2jmuH-8bc780bd.7sAvCYMP.webp" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Automate chores with GitHub Actions</title><link>https://blog2.esciencecenter.nl/posts/2021-03-05---automate-chores-with-github-actions</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-03-05---automate-chores-with-github-actions</guid><description>&lt;h2 id=&quot;how-i-keep-my-heroku-web-apps-data-up-to-date-automatically&quot;&gt;How I keep my Heroku web-app’s data up-to-date automatically&lt;/h2&gt;
&lt;p&gt;Scientists, open source developers, and basically probably most people, have to deal with one common obstacle in life: lack of funds to do all the stuff.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;593&quot; height=&quot;421&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_JECSe723rgCyyHyK-48ff0ae8.CC1T0dJb_1nkBT7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In particular in science and open source software, we cannot be bothered to maintain the stuff we left behind (at least, not on the boss’s time). It’s a never-ending quest towards novelty. People just tend to be more forthcoming in the wallet area when fancy new features or knowledge are promised.&lt;/p&gt;
&lt;p&gt;This is why it is vital that we automate the crap out of everything we humanly can, especially if what we built is some kind of service.&lt;/p&gt;
&lt;p&gt;A few months ago, I launched a small web-app called &lt;a href=&quot;http://coalitiewijzer.herokuapp.com/&quot;&gt;Coalitiewijzer&lt;/a&gt;. It uses data from &lt;a href=&quot;https://peilingwijzer.tomlouwerse.nl/&quot;&gt;Peilingwijzer&lt;/a&gt; (which combines major political polls into one) that is updated in irregular intervals. So you guessed it: we’re going to automate the ingestion of that data into the Coalitiewijzer.&lt;/p&gt;
&lt;p&gt;In this short post, I’ll show you how I did this using GitHub Actions. GitHub Actions is a Continuous Integration (CI) provider that (obviously) integrates well with GitHub. If you want to know more about CI in general, I recommend checking out our &lt;a href=&quot;https://guide.esciencecenter.nl/#/best_practices/testing&quot;&gt;Guide&lt;/a&gt;. I’ll assume some working knowledge on this and also on Git, GitHub and GitHub Actions themselves. &lt;a href=&quot;https://blog.esciencecenter.nl/coalition-polls-for-the-people-with-coalitiewijzer-68bca83b95e7&quot;&gt;For more background info about the app itself, check out my other blog post&lt;/a&gt;. This article is basically an add-on to that one. To sum up this article, we’ll look at four steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up a basic GitHub Actions &lt;strong&gt;workflow that runs daily&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Update the data and commit to your Git repo&lt;/li&gt;
&lt;li&gt;Push this from a GitHub Actions runner back to the GitHub repo&lt;/li&gt;
&lt;li&gt;Deploy your app from GitHub Actions to Heroku&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you just want to take a shortcut straight to the code: &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/f9c2712/.github/workflows/update.yml&quot;&gt;here is the current GitHub Actions workflow file I wrote&lt;/a&gt;. For those who like to read poor prose instead: read on!&lt;/p&gt;
&lt;h2 id=&quot;daily-running-workflow&quot;&gt;Daily running workflow&lt;/h2&gt;
&lt;p&gt;To start a new GitHub Actions workflow file, GitHub offers a convenient “New workflow” button under the Actions tab in your repo. You can also copy-paste the basic example in the &lt;a href=&quot;https://docs.github.com/en/actions/quickstart&quot;&gt;Actions Quickstart guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These basic workflows typically only trigger on a push to your GitHub repo, as specified by the &lt;code&gt;on: push&lt;/code&gt; line. We’ll want to change that into something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;on:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  schedule:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; cron:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &apos;0 17 * * *&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 17:00 UTC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  workflow_dispatch:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The weird string between single quotes is &lt;a href=&quot;https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events&quot;&gt;cron syntax, which is explained in the docs&lt;/a&gt;. It allows you to specify at which times you want the workflow to run, in this case at 17:00. The timezone is UTC, keep that in mind.&lt;/p&gt;
&lt;p&gt;The last line is actually unrelated, but quite useful nonetheless. It allows you to manually start the workflow from the Actions page, which I found to be essential wihle testing my workflow.&lt;/p&gt;
&lt;h2 id=&quot;updating-the-data&quot;&gt;Updating the data&lt;/h2&gt;
&lt;p&gt;My app uses data from &lt;a href=&quot;https://peilingwijzer.tomlouwerse.nl/&quot;&gt;Peilingwijzer,&lt;/a&gt; which I preprocess for use in my app and then store in a pickle file. For details on this, see the &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/update_numbers.py&quot;&gt;update script on GitHub,&lt;/a&gt; or check out the &lt;a href=&quot;https://blog.esciencecenter.nl/coalition-polls-for-the-people-with-coalitiewijzer-68bca83b95e7&quot;&gt;blog post about the app&lt;/a&gt;. The pickle file has to be committed to the repo and then I can deploy to Heroku with the new data.&lt;/p&gt;
&lt;p&gt;This can all be done with a shell script that looks roughly like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#!/usr/bin/env sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;e                    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# make the script end on errors&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python update_numbers.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;py&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # download new data and dump to files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git add [the updated files]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git commit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;updated data&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Python script does the actual data downloading and mangling and dumps the results into files that the web-app uses. These are then committed to the repo.&lt;/p&gt;
&lt;p&gt;To run this script (in particular the &lt;code&gt;git commit&lt;/code&gt;), you do need to configure the git client on the GitHub Actions runner. You can do this with a workflow step at any time before running the commit command. Add this to your workflow job in the yml file:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; name:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; configure git user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  run:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;local user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;${{ github.actor }}@users.noreply.github.com&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;local user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;${{ github.actor }}&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This commits under your own GitHub user name (or, in general, the username of the one that triggers the workflow to run), so it’ll identify the commits to be yours. It won’t do certification unless you also somehow configure that (perhaps using GitHub secrets, see the Heroku section below). You can fill in any name you want, though, so you could also put something like “Actions bot”.&lt;/p&gt;
&lt;h2 id=&quot;push-back-to-your-github-repo&quot;&gt;Push back to your GitHub repo&lt;/h2&gt;
&lt;p&gt;One of the beauties of GitHub Actions is the great availability of … well, Actions. These are pre-baked recipes for steps that you can very conveniently plug and play. To be precise, you can add such a step to your job, which is part of your Actions pipeline.&lt;/p&gt;
&lt;p&gt;For the next step, I needed to push the commit made above into the GitHub repo from within the GitHub (Actions) infrastructure itself. I was a bit anxious about whether I would find an Action which allowed me to do this. It feels like a potential security leak. Luckily, it turns out &lt;a href=&quot;https://github.com/marketplace/actions/github-push#example-workflow-file&quot;&gt;there is already an Action for this very task&lt;/a&gt;. Hurray! The &lt;a href=&quot;https://github.com/ad-m/github-push-action&quot;&gt;Action’s source&lt;/a&gt; can easily be checked if you’re worried about security.&lt;/p&gt;
&lt;p&gt;Just add the following step to your job after running the update script:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; name:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  uses:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ad&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;github&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;action@v0.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    github_token:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ${{ secrets.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    branch:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ${{ github.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this to work, one more step is necessary. You also need to add two options to your checkout step (at least, this is what I figure from the &lt;a href=&quot;https://github.com/marketplace/actions/github-push#usage&quot;&gt;Action docs&lt;/a&gt;):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; uses:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; actions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;checkout@v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    persist&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;credentials:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    fetch&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;depth:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
&lt;h2 id=&quot;deploying-to-heroku&quot;&gt;Deploying to Heroku&lt;/h2&gt;
&lt;p&gt;Finally, after the data has been updated in the Git repo, the Coalitiewijzer app can be deployed back onto Heroku (which runs &lt;a href=&quot;http://coalitiewijzer.herokuapp.com/&quot;&gt;the app, live here&lt;/a&gt;). Heroku deployment can be done by just pushing your repo directly to the Heroku servers. Really convenient!&lt;/p&gt;
&lt;p&gt;So, since this is again just a git push, albeit to a different repo, this should not be a problem. And, indeed, a &lt;a href=&quot;https://github.com/marketplace/actions/deploy-to-heroku&quot;&gt;Deploy to Heroku Action already exists&lt;/a&gt; for this very purpose!&lt;/p&gt;
&lt;p&gt;To make this work, you need to add your Heroku API key &lt;a href=&quot;https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository&quot;&gt;to your GitHub repo’s secrets (instructions here)&lt;/a&gt;. You can find the Heroku API key in your &lt;a href=&quot;https://dashboard.heroku.com/account&quot;&gt;Heroku account&lt;/a&gt;. Call it &lt;code&gt;HEROKU_API_KEY&lt;/code&gt; if you want the snippet below to work.&lt;/p&gt;
&lt;p&gt;After that, you just add the action to your workflow job, like described in the action’s documentation (replace the boldfaced parts):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; uses:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; akhileshns&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;heroku&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;deploy@v3.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10.9&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # This is the action&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      heroku_api_key:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ${{secrets.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HEROKU_API_KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      heroku_app_name:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; your_app_name_on_heroku&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      heroku_email:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; your@email.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;address&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Be careful with this key, because it gives access to your full Heroku account.&lt;/p&gt;
&lt;p&gt;And that’s it! From now on, your updates will be pushed back to the GitHub repo and deployed on Heroku.&lt;/p&gt;
&lt;p&gt;Of course, this is just one of many things you could automate using GitHub Actions. The combination with running actual servers on Heroku for free is icing on the cake. Of course, if you want more performance, more MBs, more connections, etcetera, you can pay them for that. But for low profile web-apps, the free package is really a great deal.&lt;/p&gt;
&lt;p&gt;Let me know if you have any comments or questions. I’m happy to help!&lt;/p&gt;</description><pubDate>Fri, 05 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;how-i-keep-my-heroku-web-apps-data-up-to-date-automatically&quot;&gt;How I keep my Heroku web-app’s data up-to-date automatically&lt;/h2&gt;
&lt;p&gt;Scientists, open source developers, and basically probably most people, have to deal with one common obstacle in life: lack of funds to do all the stuff.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;593&quot; height=&quot;421&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_JECSe723rgCyyHyK-48ff0ae8.CC1T0dJb_1nkBT7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In particular in science and open source software, we cannot be bothered to maintain the stuff we left behind (at least, not on the boss’s time). It’s a never-ending quest towards novelty. People just tend to be more forthcoming in the wallet area when fancy new features or knowledge are promised.&lt;/p&gt;
&lt;p&gt;This is why it is vital that we automate the crap out of everything we humanly can, especially if what we built is some kind of service.&lt;/p&gt;
&lt;p&gt;A few months ago, I launched a small web-app called &lt;a href=&quot;http://coalitiewijzer.herokuapp.com/&quot;&gt;Coalitiewijzer&lt;/a&gt;. It uses data from &lt;a href=&quot;https://peilingwijzer.tomlouwerse.nl/&quot;&gt;Peilingwijzer&lt;/a&gt; (which combines major political polls into one) that is updated in irregular intervals. So you guessed it: we’re going to automate the ingestion of that data into the Coalitiewijzer.&lt;/p&gt;
&lt;p&gt;In this short post, I’ll show you how I did this using GitHub Actions. GitHub Actions is a Continuous Integration (CI) provider that (obviously) integrates well with GitHub. If you want to know more about CI in general, I recommend checking out our &lt;a href=&quot;https://guide.esciencecenter.nl/#/best_practices/testing&quot;&gt;Guide&lt;/a&gt;. I’ll assume some working knowledge on this and also on Git, GitHub and GitHub Actions themselves. &lt;a href=&quot;https://blog.esciencecenter.nl/coalition-polls-for-the-people-with-coalitiewijzer-68bca83b95e7&quot;&gt;For more background info about the app itself, check out my other blog post&lt;/a&gt;. This article is basically an add-on to that one. To sum up this article, we’ll look at four steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up a basic GitHub Actions &lt;strong&gt;workflow that runs daily&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Update the data and commit to your Git repo&lt;/li&gt;
&lt;li&gt;Push this from a GitHub Actions runner back to the GitHub repo&lt;/li&gt;
&lt;li&gt;Deploy your app from GitHub Actions to Heroku&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you just want to take a shortcut straight to the code: &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/f9c2712/.github/workflows/update.yml&quot;&gt;here is the current GitHub Actions workflow file I wrote&lt;/a&gt;. For those who like to read poor prose instead: read on!&lt;/p&gt;
&lt;h2 id=&quot;daily-running-workflow&quot;&gt;Daily running workflow&lt;/h2&gt;
&lt;p&gt;To start a new GitHub Actions workflow file, GitHub offers a convenient “New workflow” button under the Actions tab in your repo. You can also copy-paste the basic example in the &lt;a href=&quot;https://docs.github.com/en/actions/quickstart&quot;&gt;Actions Quickstart guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These basic workflows typically only trigger on a push to your GitHub repo, as specified by the &lt;code&gt;on: push&lt;/code&gt; line. We’ll want to change that into something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;on:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  schedule:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; cron:&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;  &apos;0 17 * * *&apos;&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # 17:00 UTC&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  workflow_dispatch:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The weird string between single quotes is &lt;a href=&quot;https://docs.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events&quot;&gt;cron syntax, which is explained in the docs&lt;/a&gt;. It allows you to specify at which times you want the workflow to run, in this case at 17:00. The timezone is UTC, keep that in mind.&lt;/p&gt;
&lt;p&gt;The last line is actually unrelated, but quite useful nonetheless. It allows you to manually start the workflow from the Actions page, which I found to be essential wihle testing my workflow.&lt;/p&gt;
&lt;h2 id=&quot;updating-the-data&quot;&gt;Updating the data&lt;/h2&gt;
&lt;p&gt;My app uses data from &lt;a href=&quot;https://peilingwijzer.tomlouwerse.nl/&quot;&gt;Peilingwijzer,&lt;/a&gt; which I preprocess for use in my app and then store in a pickle file. For details on this, see the &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/update_numbers.py&quot;&gt;update script on GitHub,&lt;/a&gt; or check out the &lt;a href=&quot;https://blog.esciencecenter.nl/coalition-polls-for-the-people-with-coalitiewijzer-68bca83b95e7&quot;&gt;blog post about the app&lt;/a&gt;. The pickle file has to be committed to the repo and then I can deploy to Heroku with the new data.&lt;/p&gt;
&lt;p&gt;This can all be done with a shell script that looks roughly like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#!/usr/bin/env sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;set &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;e                    &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# make the script end on errors&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python update_numbers.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;py&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # download new data and dump to files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git add [the updated files]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;git commit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;updated data&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Python script does the actual data downloading and mangling and dumps the results into files that the web-app uses. These are then committed to the repo.&lt;/p&gt;
&lt;p&gt;To run this script (in particular the &lt;code&gt;git commit&lt;/code&gt;), you do need to configure the git client on the GitHub Actions runner. You can do this with a workflow step at any time before running the commit command. Add this to your workflow job in the yml file:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; name:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; configure git user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  run:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;local user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;${{ github.actor }}@users.noreply.github.com&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    git config &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;local user.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;${{ github.actor }}&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This commits under your own GitHub user name (or, in general, the username of the one that triggers the workflow to run), so it’ll identify the commits to be yours. It won’t do certification unless you also somehow configure that (perhaps using GitHub secrets, see the Heroku section below). You can fill in any name you want, though, so you could also put something like “Actions bot”.&lt;/p&gt;
&lt;h2 id=&quot;push-back-to-your-github-repo&quot;&gt;Push back to your GitHub repo&lt;/h2&gt;
&lt;p&gt;One of the beauties of GitHub Actions is the great availability of … well, Actions. These are pre-baked recipes for steps that you can very conveniently plug and play. To be precise, you can add such a step to your job, which is part of your Actions pipeline.&lt;/p&gt;
&lt;p&gt;For the next step, I needed to push the commit made above into the GitHub repo from within the GitHub (Actions) infrastructure itself. I was a bit anxious about whether I would find an Action which allowed me to do this. It feels like a potential security leak. Luckily, it turns out &lt;a href=&quot;https://github.com/marketplace/actions/github-push#example-workflow-file&quot;&gt;there is already an Action for this very task&lt;/a&gt;. Hurray! The &lt;a href=&quot;https://github.com/ad-m/github-push-action&quot;&gt;Action’s source&lt;/a&gt; can easily be checked if you’re worried about security.&lt;/p&gt;
&lt;p&gt;Just add the following step to your job after running the update script:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; name:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Push&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  uses:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ad&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;github&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;action@v0.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;6.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    github_token:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ${{ secrets.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;    branch:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ${{ github.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ref&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this to work, one more step is necessary. You also need to add two options to your checkout step (at least, this is what I figure from the &lt;a href=&quot;https://github.com/marketplace/actions/github-push#usage&quot;&gt;Action docs&lt;/a&gt;):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; uses:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; actions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;checkout@v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    persist&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;credentials:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    fetch&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;depth:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
&lt;h2 id=&quot;deploying-to-heroku&quot;&gt;Deploying to Heroku&lt;/h2&gt;
&lt;p&gt;Finally, after the data has been updated in the Git repo, the Coalitiewijzer app can be deployed back onto Heroku (which runs &lt;a href=&quot;http://coalitiewijzer.herokuapp.com/&quot;&gt;the app, live here&lt;/a&gt;). Heroku deployment can be done by just pushing your repo directly to the Heroku servers. Really convenient!&lt;/p&gt;
&lt;p&gt;So, since this is again just a git push, albeit to a different repo, this should not be a problem. And, indeed, a &lt;a href=&quot;https://github.com/marketplace/actions/deploy-to-heroku&quot;&gt;Deploy to Heroku Action already exists&lt;/a&gt; for this very purpose!&lt;/p&gt;
&lt;p&gt;To make this work, you need to add your Heroku API key &lt;a href=&quot;https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository&quot;&gt;to your GitHub repo’s secrets (instructions here)&lt;/a&gt;. You can find the Heroku API key in your &lt;a href=&quot;https://dashboard.heroku.com/account&quot;&gt;Heroku account&lt;/a&gt;. Call it &lt;code&gt;HEROKU_API_KEY&lt;/code&gt; if you want the snippet below to work.&lt;/p&gt;
&lt;p&gt;After that, you just add the action to your workflow job, like described in the action’s documentation (replace the boldfaced parts):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; uses:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; akhileshns&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;heroku&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;deploy@v3.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10.9&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt; # This is the action&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      heroku_api_key:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ${{secrets.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HEROKU_API_KEY&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      heroku_app_name:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; your_app_name_on_heroku&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      heroku_email:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; your@email.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;address&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Be careful with this key, because it gives access to your full Heroku account.&lt;/p&gt;
&lt;p&gt;And that’s it! From now on, your updates will be pushed back to the GitHub repo and deployed on Heroku.&lt;/p&gt;
&lt;p&gt;Of course, this is just one of many things you could automate using GitHub Actions. The combination with running actual servers on Heroku for free is icing on the cake. Of course, if you want more performance, more MBs, more connections, etcetera, you can pay them for that. But for low profile web-apps, the free package is really a great deal.&lt;/p&gt;
&lt;p&gt;Let me know if you have any comments or questions. I’m happy to help!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_JECSe723rgCyyHyK-48ff0ae8.CC1T0dJb.jpg" medium="image"/><author>Patrick Bos</author></item><item><title>A Quick and Dirty Pytest Cookbook</title><link>https://blog2.esciencecenter.nl/posts/2021-02-22---a-quick-and-dirty-pytest-cookbook</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-02-22---a-quick-and-dirty-pytest-cookbook</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;As an alternative to the above snippet, you can install and run the &lt;a href=&quot;https://pypi.org/project/pytest-mypy-plugins/&quot;&gt;pytest-mypy-plugins&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;testing-the-documentation&quot;&gt;Testing the documentation&lt;/h2&gt;
&lt;p&gt;Testing the documentation is a must have. The following snippet shows how you can do so:&lt;/p&gt;
&lt;h2 id=&quot;testing-async-code&quot;&gt;Testing async code&lt;/h2&gt;
&lt;p&gt;If you do web applications or something similar you probably have run into Python &lt;a href=&quot;https://docs.python.org/3/library/asyncio.html&quot;&gt;asyncio&lt;/a&gt;. If you try to run async code using normal pytest code, chances are that you wouldn’t notice that there are no tests running at all. Async code is lazy and requires that you run it inside an async block*, otherwise nothing interesting happens. The following snippet shows how to invoke async code in Pytest:&lt;/p&gt;
&lt;p&gt;For more details about testing asynchronous code in python check &lt;a href=&quot;https://github.com/pytest-dev/pytest-asyncio&quot;&gt;pytest-asyncio&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;running-tests-in-parallel&quot;&gt;Running tests in parallel&lt;/h2&gt;
&lt;p&gt;If you, like me, have the tendency to procrastinate while waiting for the test suite to finish executing, then a good way to reduce the procrastination time is to run the tests in parallel.&lt;/p&gt;
&lt;p&gt;For running your tests in parallel, you just need to install the &lt;a href=&quot;https://github.com/browsertron/pytest-parallel&quot;&gt;pytest-parallel&lt;/a&gt; library that not only allows you to run your tests in parallel but also in a thread-safe manner, using commands as simple as:&lt;/p&gt;
&lt;p&gt;pytest —workers 2&lt;/p&gt;
&lt;h2 id=&quot;running-a-test-with-multiple-parameters&quot;&gt;Running a test with multiple parameters&lt;/h2&gt;
&lt;p&gt;Imaging that you have a simulation that receives some parameters as input and gives you back some numerical output. You can use &lt;a href=&quot;https://docs.pytest.org/en/stable/parametrize.html&quot;&gt;pytest’s parametrize extension&lt;/a&gt; to feed one parameter at a time to the simulation and check that each one of them returns the expected output. The following snippet shows how to accomplish that:&lt;/p&gt;
&lt;p&gt;If you run the previous snippet, you should see something like:&lt;/p&gt;
&lt;p&gt;pytest -v test_parameters.py
test_parameters.py::test_simulation[pi-3.141592653589793] PASSED&lt;br&gt;
test_parameters.py::test_simulation[exp-2.718281828459045] FAILEDparameter = ‘exp’, expected = 2.718281828459045&lt;a href=&quot;http://twitter.com/pytest&quot;&gt;@pytest&lt;/a&gt;.mark.parametrize(“parameter, expected”,
[(“pi”, np.pi), (“exp”, np.exp(1))])
def test_simulation(parameter: str, expected: float) -&gt; None:
&quot;&quot;&quot;Check the simulation.&quot;&quot;&quot;
result = run_simulation(parameter)
&gt;       assert abs(result - expected) &amp;#x3C; 1e-8
E       assert 39.28171817154095 &amp;#x3C; 1e-08
E        +  where 39.28171817154095 = abs((42 - 2.718281828459045))test_parameter.py:16: AssertionError&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Pytest is a flexible tool with a great number of useful extensions. With Pytest, there is always a way to check your code functionality, even those annoying corner cases.&lt;/p&gt;
&lt;p&gt;Please comment if you find these tricks useful or if you find another nice trick that you want to share.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgement&quot;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;My special gratitude to Bas van Beek to share with me some of his useful recipes. I would like also to thank [Florian Huber] and Stefan Verhoeven for their feedback.&lt;/p&gt;
&lt;p&gt;Thanks to [Pablo Rodríguez-Sánchez] and Steven Roldan for their help editing the text.&lt;/p&gt;</description><pubDate>Mon, 22 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;As an alternative to the above snippet, you can install and run the &lt;a href=&quot;https://pypi.org/project/pytest-mypy-plugins/&quot;&gt;pytest-mypy-plugins&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;testing-the-documentation&quot;&gt;Testing the documentation&lt;/h2&gt;
&lt;p&gt;Testing the documentation is a must have. The following snippet shows how you can do so:&lt;/p&gt;
&lt;h2 id=&quot;testing-async-code&quot;&gt;Testing async code&lt;/h2&gt;
&lt;p&gt;If you do web applications or something similar you probably have run into Python &lt;a href=&quot;https://docs.python.org/3/library/asyncio.html&quot;&gt;asyncio&lt;/a&gt;. If you try to run async code using normal pytest code, chances are that you wouldn’t notice that there are no tests running at all. Async code is lazy and requires that you run it inside an async block*, otherwise nothing interesting happens. The following snippet shows how to invoke async code in Pytest:&lt;/p&gt;
&lt;p&gt;For more details about testing asynchronous code in python check &lt;a href=&quot;https://github.com/pytest-dev/pytest-asyncio&quot;&gt;pytest-asyncio&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;running-tests-in-parallel&quot;&gt;Running tests in parallel&lt;/h2&gt;
&lt;p&gt;If you, like me, have the tendency to procrastinate while waiting for the test suite to finish executing, then a good way to reduce the procrastination time is to run the tests in parallel.&lt;/p&gt;
&lt;p&gt;For running your tests in parallel, you just need to install the &lt;a href=&quot;https://github.com/browsertron/pytest-parallel&quot;&gt;pytest-parallel&lt;/a&gt; library that not only allows you to run your tests in parallel but also in a thread-safe manner, using commands as simple as:&lt;/p&gt;
&lt;p&gt;pytest —workers 2&lt;/p&gt;
&lt;h2 id=&quot;running-a-test-with-multiple-parameters&quot;&gt;Running a test with multiple parameters&lt;/h2&gt;
&lt;p&gt;Imaging that you have a simulation that receives some parameters as input and gives you back some numerical output. You can use &lt;a href=&quot;https://docs.pytest.org/en/stable/parametrize.html&quot;&gt;pytest’s parametrize extension&lt;/a&gt; to feed one parameter at a time to the simulation and check that each one of them returns the expected output. The following snippet shows how to accomplish that:&lt;/p&gt;
&lt;p&gt;If you run the previous snippet, you should see something like:&lt;/p&gt;
&lt;p&gt;pytest -v test_parameters.py
test_parameters.py::test_simulation[pi-3.141592653589793] PASSED&lt;br&gt;
test_parameters.py::test_simulation[exp-2.718281828459045] FAILEDparameter = ‘exp’, expected = 2.718281828459045&lt;a href=&quot;http://twitter.com/pytest&quot;&gt;@pytest&lt;/a&gt;.mark.parametrize(“parameter, expected”,
[(“pi”, np.pi), (“exp”, np.exp(1))])
def test_simulation(parameter: str, expected: float) -&gt; None:
&quot;&quot;&quot;Check the simulation.&quot;&quot;&quot;
result = run_simulation(parameter)
&gt;       assert abs(result - expected) &amp;#x3C; 1e-8
E       assert 39.28171817154095 &amp;#x3C; 1e-08
E        +  where 39.28171817154095 = abs((42 - 2.718281828459045))test_parameter.py:16: AssertionError&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Pytest is a flexible tool with a great number of useful extensions. With Pytest, there is always a way to check your code functionality, even those annoying corner cases.&lt;/p&gt;
&lt;p&gt;Please comment if you find these tricks useful or if you find another nice trick that you want to share.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgement&quot;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;My special gratitude to Bas van Beek to share with me some of his useful recipes. I would like also to thank [Florian Huber] and Stefan Verhoeven for their feedback.&lt;/p&gt;
&lt;p&gt;Thanks to [Pablo Rodríguez-Sánchez] and Steven Roldan for their help editing the text.&lt;/p&gt;</content:encoded><author>Felipe</author></item><item><title>Twitter Bots, for Science!</title><link>https://blog2.esciencecenter.nl/posts/2021-02-19---twitter-bots-for-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-02-19---twitter-bots-for-science</guid><description>&lt;h2 id=&quot;how-to-build-a-bot-to-show-covid-19-vaccination-progress&quot;&gt;How to build a bot to show Covid-19 vaccination progress&lt;/h2&gt;
&lt;p&gt;Twitter bots have a really bad rep. Troll armies, spam, fake news… You name it, a bot’s done it.&lt;/p&gt;
&lt;p&gt;But what if we could harness their powers for good? Use bots to inform people in a fun way? That would be &lt;strong&gt;science outreach&lt;/strong&gt;! It’s all in a name.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2053&quot; height=&quot;1095&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YL2rNx2g8oxkMG149unWgQ-2fde1464.1WN8Ucbt_17M1Gc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The knights who say “SCI!” ( Python et al., 1975 ). Photo: CC BY 2.0, Brickset&lt;/p&gt;
&lt;p&gt;Of course, Covid-19 is on everybody’s mind, but the tide of horribility (it’s a word) is slowly turning into one of hope and recovery. We’re not out of the woods yet, but we are jabbing our way out, one vaccine at a time.&lt;/p&gt;
&lt;p&gt;To spread a bit of this hope (and have some fun), I created a &lt;a href=&quot;https://twitter.com/CoVacProgress&quot;&gt;&lt;strong&gt;progress bar&lt;/strong&gt; (who doesn’t love progress bars?!) on Twitter&lt;/a&gt; that shows &lt;strong&gt;how many people have been vaccinated&lt;/strong&gt; worldwide and per continent. The bars are updated daily.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;304&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zMpiXECwyVswfe-fU4EWcg-78e58517.DcKfMD6c_Z2efLgs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot&quot;&gt;code is open source&lt;/a&gt; and the open data comes from &lt;a href=&quot;https://ourworldindata.org/covid-vaccinations&quot;&gt;Our World in Data&lt;/a&gt;. If you feel inspired by this little project to share some of &lt;strong&gt;your&lt;/strong&gt; scientific data, feel free to build on it! I had my first version up in about an hour: it’s really surprisingly easy, so &lt;em&gt;&lt;strong&gt;don’t let technical barriers hold you back from communicating cool science results automatically&lt;/strong&gt;&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;The requirements for reading this howto are a working knowledge of Python, Pandas, Git, GitHub and Twitter and a high tolerance for painfully horrible jokes. For the working knowledge part: check out our &lt;a href=&quot;https://guide.esciencecenter.nl/#/&quot;&gt;Guide&lt;/a&gt;. For the jokes, well… maybe reading this article will actually build up your tolerance.&lt;/p&gt;
&lt;p&gt;I’ll cover the five steps I took to build this bot:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a “bot account” on Twitter&lt;/li&gt;
&lt;li&gt;Get and mangle the data from Our World in Data with the Python Pandas package&lt;/li&gt;
&lt;li&gt;Use tqdm to make progress bars suitable for Twitter&lt;/li&gt;
&lt;li&gt;Send tweets using the Python Tweepy package&lt;/li&gt;
&lt;li&gt;Automate this using GitHub Actions&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;create-a-bot-account&quot;&gt;Create a “bot” account&lt;/h2&gt;
&lt;p&gt;The first thing you need is a developer account on Twitter. This allows you to get key strings which you can use later on to log in and do stuff on Twitter from a Python script.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/twitter-bot-python-tweepy/#creating-twitter-api-authentication-credentials&quot;&gt;This post&lt;/a&gt; (among many others) clearly explains the steps you need to take for this.&lt;/p&gt;
&lt;p&gt;It is possible to use your personal account for your bot (and for activating the developer account on), but for this project I decided to create a separate account. You’ll need a unique email address to do so, but you can use the same telephone number as your existing account for confirmation. A separate account allows for easy &lt;strong&gt;testing&lt;/strong&gt; of your bot before you start promoting it widely. Just delete the test tweets when everything is done.&lt;/p&gt;
&lt;p&gt;So, with your bot account ready, jot down the keys somewhere — but &lt;strong&gt;don’t put them in your git repo&lt;/strong&gt; (&lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/blob/dfbd3101aa192be8fd6448aa051b0ae14cc1520a/test_tweepy.py#L10&quot;&gt;like I obviously did 😁&lt;/a&gt;) — so we can use them in Tweepy later on.&lt;/p&gt;
&lt;h2 id=&quot;get-the-data-with-pandas&quot;&gt;Get the data with Pandas&lt;/h2&gt;
&lt;p&gt;One of &lt;strong&gt;the&lt;/strong&gt; authoritative sources on Covid-19 data is &lt;a href=&quot;https://ourworldindata.org/&quot;&gt;Our World in Data&lt;/a&gt;. You can find their graphs all over the place. The data they gather is conveniently open (under a Creative Commons license) and &lt;a href=&quot;https://github.com/owid/covid-19-data/tree/master/public/data/vaccinations&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;652&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dThJeI5ENXybCcen6GsAow-34e7bbdf.CK0okt-i_Z1dnOht.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Grizzlies would be a better name… Image: CC BY-NC-ND 2.0 iregretjumping.&lt;/p&gt;
&lt;p&gt;Pandas, the &lt;em&gt;ironically named omnivore of data science&lt;/em&gt;, can chew this right up, straight from the raw URL. This saves you the step of manually downloading. Convenient! Look for the little “raw” button when viewing a file on GitHub and give that URL to your favorite ursid:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pand&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;read_csv(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.csv&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, parse_dates&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us a nice dataframe containing which countries had what number of people vaccinated at which dates. They even keep track of whether people had only one or two (where applicable) shots. Not every country has good data, so Our World in Data only includes those numbers which pass their quality checks.&lt;/p&gt;
&lt;p&gt;For the time being, I’m using the column &lt;code&gt;people_vaccinated_per_hundred&lt;/code&gt; for the bot, because those numbers are a bit less depressing at the moment, but may switch to &lt;code&gt;people_fully_vaccinated_per_hundred&lt;/code&gt; later on. Since not all countries have data in these columns, this leaves us with a little over 50 countries &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/blob/e9d4eced48f315567c224f19068ab6bd8206020c/run.py#L55&quot;&gt;after filtering&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;calculate-continent-totals-with-pycountry_convert&quot;&gt;Calculate continent totals with pycountry_convert&lt;/h3&gt;
&lt;p&gt;Now, the table has numbers for the whole world pre-calculated, so I grabbed those for my first tests. But I thought it would be fun to also add some more detailed data.&lt;/p&gt;
&lt;p&gt;Twitter’s character limit prevents me from posting bars for all 56 countries, but we can certainly do continents. I think that’s still interesting, as well as poignant given the inequality in the world it so very clearly highlights. If the stark contrast makes policy makers think about fairer distribution for a second, that would be a huge win.&lt;/p&gt;
&lt;p&gt;Of course, finding the continents for 56 countries &lt;strong&gt;by hand&lt;/strong&gt; goes against everything I stand for as a lazy programmer. Obviously, I went about spending way more time on finding and figuring out a nice library that can do this work for me automatically. And, lo and behold, it exists, is called &lt;a href=&quot;https://pypi.org/project/pycountry-convert/&quot;&gt;pycountry_convert&lt;/a&gt; and &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/blob/e9d4eced48f315567c224f19068ab6bd8206020c/run.py#L49&quot;&gt;works like a charm&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Combine it with the &lt;a href=&quot;https://raw.githubusercontent.com/owid/covid-19-data/master/scripts/input/un/population_2020.csv&quot;&gt;total population table that Our World in Data also maintains&lt;/a&gt; and you’ve got all the ingredients you need to compute percentages per continent.&lt;/p&gt;
&lt;p&gt;Note that the continent numbers are not completely correct like this. Some countries span multiple continents (notably Russia). I treat such countries to just be part of one continent (so Russia is part of Europe, because pycountry_convert tells me it is).&lt;/p&gt;
&lt;h2 id=&quot;make-tweetable-progress-bars-with-tqdm&quot;&gt;Make Tweetable progress bars with tqdm&lt;/h2&gt;
&lt;p&gt;Now that we have percentages, we can convert them to progress bars.&lt;/p&gt;
&lt;p&gt;My go-to package for progress bars is &lt;code&gt;tqdm&lt;/code&gt;. It is especially good in interactive environments. There’s nothing like a progress bar to spice up a slow &lt;code&gt;for&lt;/code&gt; -loop. What’s more, &lt;code&gt;tqdm&lt;/code&gt; ’s bars look really good both in Jupyter notebooks and on the command line due to &lt;em&gt;using fancy unicode characters&lt;/em&gt;. The latter is exactly what I want to use here as well: Twitter is primarily a textual medium, and although I could just post images of progress bars (wait… why didn’t I? d’oh!), posting text-based bars should be an easy first option.&lt;/p&gt;
&lt;p&gt;Also, &lt;a href=&quot;https://twitter.com/year_progress&quot;&gt;year_progress&lt;/a&gt; does text-bars as well and that bot inspired this one, so there you go.&lt;/p&gt;
&lt;p&gt;Given some &lt;code&gt;percentage&lt;/code&gt; from the dataset, we can make a bar-string for posting to Twitter with something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bar &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tqdm(initial&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;percentage, total&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bar_format&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{bar&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {percentage&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;1f}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;, ascii&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bar_string &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str(bar)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tweet_string &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bar_string[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;replace(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;u3000&apos;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bar_string[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few tricks beyond the &lt;code&gt;tqdm&lt;/code&gt; basics to highlight are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I used a custom format string to remove some superfluous stuff. We need to use as little characters as possible, but, also, it is important to not make the string too wide, otherwise it doesn’t display nicely on all devices (read: phones).&lt;/li&gt;
&lt;li&gt;Usually, &lt;code&gt;tqdm&lt;/code&gt; is used to display an “animated” progress bar. To emulate animation on the command line, it does all sorts of magic with carriage return (&lt;code&gt;\r&lt;/code&gt;) and new line (&lt;code&gt;\n&lt;/code&gt;) characters. I first tried using the &lt;code&gt;tqdm&lt;/code&gt; option of specifying an output stream using an &lt;code&gt;io.StringIO&lt;/code&gt; stream object, to act as a virtual terminal so to speak. I then tried to extract the bar string from that. This turned out to be quite a nightmarish experience (may have had to do with it getting quite late). Probably, &lt;code&gt;tqdm&lt;/code&gt; tries to do very smart things when outputting to this stream, and clearly I wasn’t smart enough to undo those smart things. Luckily, after a good night’s rest, I found that directly extracting the bar string from &lt;code&gt;bar.__str__()&lt;/code&gt; does not do weird animation stuff and just gives a neat, clean progress bar. Phew.&lt;/li&gt;
&lt;li&gt;Twitter is not a terminal. The relevance of this obvious statement is that Twitter does not use a fixed width font. Madness, I know. But luckily, the unicode committee (I’m sure there is one, perhaps several, in fact) blessed us with more kinds of space characters than we could ever have hoped for. &lt;code&gt;\u3000&lt;/code&gt;, the “ideographic space”, is the one that turns out to have the same width on Twitter as (most) unicode characters used for the bar itself. So I replace spaces in the bar (barring (heehee) those around the bar) with this ideographic one.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tweet-with-tweepy&quot;&gt;Tweet with Tweepy&lt;/h2&gt;
&lt;p&gt;The actual tweeting is the easiest part in all this. The &lt;a href=&quot;https://realpython.com/twitter-bot-python-tweepy/#creating-twitter-api-authentication-credentials&quot;&gt;above mentioned article&lt;/a&gt; explains most of it using the &lt;a href=&quot;https://www.tweepy.org/&quot;&gt;Tweepy&lt;/a&gt; package. You need the keys you obtained earlier to authenticate and create an &lt;code&gt;api&lt;/code&gt; object (see the snippet in the article).&lt;/p&gt;
&lt;p&gt;Then, tweeting is as simple as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;update_status(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ceci n&apos;est pas une tweet&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;810&quot; height=&quot;475&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_ZdxO48qSyJmHrXsL-1f57d952.Gm0PiurH_Z1X5XYc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simple. J’approuve.&lt;/p&gt;
&lt;p&gt;If all goes well, this command will return a giant blob of JSON, wrapped in some Tweepy class. Not to worry, do not disturb it, it means you no harm. If for some reason the Tweepy call failed, you’ll get an error message, so you’ll know when you actually have to start paying attention.&lt;/p&gt;
&lt;h2 id=&quot;automate-on-github-actions&quot;&gt;Automate on GitHub Actions&lt;/h2&gt;
&lt;p&gt;Obviously, the last part of the show is about getting rid of any future manual action and getting back to watching YouTube. We are programmers, after all. Moreover, we are scientists and we don’t have time for manual labor. That is what PhD stu…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[anxious whispering]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[angry, impatient whispering]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not supposed to…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[university PR department whispers]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ok, but…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[whispered definitive executive order]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Automation, then!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[financial whispers]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For free! Yes, we can, with GitHub Actions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[mumbled approval]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After putting all my code in a git repository (on GitHub), I created a workflow file &lt;code&gt;.github/workflows/tweet_progress.yml&lt;/code&gt;. The file looks something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Tweet&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; latest progresson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  schedule&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cron&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &apos;0 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;00&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; UTC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, see https&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;://&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;crontab&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;guru&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; allows you to run this workflow manually from the &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Actions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tab&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  workflow_dispatch&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  tweet&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    runs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ubuntu&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; actions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;checkout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; actions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;setup&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; install dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pip install &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;r requirements&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        env&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_API&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_API }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_API_SECRET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_API_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_ACCESS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_ACCESS }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_ACCESS_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; python run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Under the &lt;code&gt;on&lt;/code&gt; section, we make our Tweepy script run on a regular &lt;code&gt;schedule&lt;/code&gt;: every day at 10 a.m., UTC (check out &lt;a href=&quot;https://crontab.guru/&quot;&gt;https://crontab.guru/&lt;/a&gt; if you don’t want to bother remembering the arcane cron syntax, thanks to&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/fca35bfb3190?source=post_page---user_mention--1cf3f19dcda8---------------------------------------&quot;&gt;Stefan Verhoeven&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;for the tip). The data is updated daily in the morning, so this should use the freshest data most days. We can also trigger the job manually by adding &lt;code&gt;workflow_dispatch&lt;/code&gt;. The part below &lt;code&gt;jobs&lt;/code&gt; is what will actually run on a GitHub machine and should be mostly self-explanatory. This will also be different for your specific application (unless you copy mine). The important thing to notice, though, is the bold part where I pass in all the keys.&lt;/p&gt;
&lt;p&gt;Two things to make this possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The awesome &lt;a href=&quot;https://pypi.org/project/ConfigArgParse/&quot;&gt;ConfigArgParse&lt;/a&gt; module allows for specifying program parameters in three ways: via command line arguments (like the Python standard library &lt;code&gt;argparse&lt;/code&gt;), via a config file or via environment variables, all through one convenient, almost-drop-in-replacement-of- &lt;code&gt;argparse&lt;/code&gt; call. On my laptop (for testing and such) I added a config file with the keys in it (and put the name of that file in &lt;code&gt;.gitignore&lt;/code&gt;, after my earlier key committing booboo), but on GitHub Actions I can now pass them in through environment variables via the &lt;code&gt;env&lt;/code&gt; section.&lt;/li&gt;
&lt;li&gt;The second part is those &lt;code&gt;${{ secrets.THING }}&lt;/code&gt; things. You have to &lt;a href=&quot;https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository&quot;&gt;store the Twitter keys in GitHub secrets (instructions here)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commit the yml file, push it to GitHub, and just like that you’ve got yourself an automatically updating Twitter bot!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;605&quot; height=&quot;568&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_l1__Q8DxN_LnAe_VU4L3CQ-2dc29b71.Dgpci5tY_2rTIFX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The top two tweets were automatically produced. It’s alive! ALIVE!!!&lt;/p&gt;
&lt;p&gt;I hope I convinced you that if you have a cool idea for a bot and know of a data source, you should immediately go for it! Just &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/&quot;&gt;fork my repo&lt;/a&gt; if you want to get a quick start, modify it to your liking and put it out there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Congratulations&lt;/strong&gt;, you just made the world a better, more well-informed place!&lt;/p&gt;
&lt;p&gt;I’d love to hear what you think, let me know in the comments. Also, if you want some help setting up your bot, don’t hesitate to ask.&lt;/p&gt;</description><pubDate>Fri, 19 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;how-to-build-a-bot-to-show-covid-19-vaccination-progress&quot;&gt;How to build a bot to show Covid-19 vaccination progress&lt;/h2&gt;
&lt;p&gt;Twitter bots have a really bad rep. Troll armies, spam, fake news… You name it, a bot’s done it.&lt;/p&gt;
&lt;p&gt;But what if we could harness their powers for good? Use bots to inform people in a fun way? That would be &lt;strong&gt;science outreach&lt;/strong&gt;! It’s all in a name.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2053&quot; height=&quot;1095&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YL2rNx2g8oxkMG149unWgQ-2fde1464.1WN8Ucbt_17M1Gc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The knights who say “SCI!” ( Python et al., 1975 ). Photo: CC BY 2.0, Brickset&lt;/p&gt;
&lt;p&gt;Of course, Covid-19 is on everybody’s mind, but the tide of horribility (it’s a word) is slowly turning into one of hope and recovery. We’re not out of the woods yet, but we are jabbing our way out, one vaccine at a time.&lt;/p&gt;
&lt;p&gt;To spread a bit of this hope (and have some fun), I created a &lt;a href=&quot;https://twitter.com/CoVacProgress&quot;&gt;&lt;strong&gt;progress bar&lt;/strong&gt; (who doesn’t love progress bars?!) on Twitter&lt;/a&gt; that shows &lt;strong&gt;how many people have been vaccinated&lt;/strong&gt; worldwide and per continent. The bars are updated daily.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;304&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zMpiXECwyVswfe-fU4EWcg-78e58517.DcKfMD6c_Z2efLgs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot&quot;&gt;code is open source&lt;/a&gt; and the open data comes from &lt;a href=&quot;https://ourworldindata.org/covid-vaccinations&quot;&gt;Our World in Data&lt;/a&gt;. If you feel inspired by this little project to share some of &lt;strong&gt;your&lt;/strong&gt; scientific data, feel free to build on it! I had my first version up in about an hour: it’s really surprisingly easy, so &lt;em&gt;&lt;strong&gt;don’t let technical barriers hold you back from communicating cool science results automatically&lt;/strong&gt;&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;The requirements for reading this howto are a working knowledge of Python, Pandas, Git, GitHub and Twitter and a high tolerance for painfully horrible jokes. For the working knowledge part: check out our &lt;a href=&quot;https://guide.esciencecenter.nl/#/&quot;&gt;Guide&lt;/a&gt;. For the jokes, well… maybe reading this article will actually build up your tolerance.&lt;/p&gt;
&lt;p&gt;I’ll cover the five steps I took to build this bot:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a “bot account” on Twitter&lt;/li&gt;
&lt;li&gt;Get and mangle the data from Our World in Data with the Python Pandas package&lt;/li&gt;
&lt;li&gt;Use tqdm to make progress bars suitable for Twitter&lt;/li&gt;
&lt;li&gt;Send tweets using the Python Tweepy package&lt;/li&gt;
&lt;li&gt;Automate this using GitHub Actions&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;create-a-bot-account&quot;&gt;Create a “bot” account&lt;/h2&gt;
&lt;p&gt;The first thing you need is a developer account on Twitter. This allows you to get key strings which you can use later on to log in and do stuff on Twitter from a Python script.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/twitter-bot-python-tweepy/#creating-twitter-api-authentication-credentials&quot;&gt;This post&lt;/a&gt; (among many others) clearly explains the steps you need to take for this.&lt;/p&gt;
&lt;p&gt;It is possible to use your personal account for your bot (and for activating the developer account on), but for this project I decided to create a separate account. You’ll need a unique email address to do so, but you can use the same telephone number as your existing account for confirmation. A separate account allows for easy &lt;strong&gt;testing&lt;/strong&gt; of your bot before you start promoting it widely. Just delete the test tweets when everything is done.&lt;/p&gt;
&lt;p&gt;So, with your bot account ready, jot down the keys somewhere — but &lt;strong&gt;don’t put them in your git repo&lt;/strong&gt; (&lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/blob/dfbd3101aa192be8fd6448aa051b0ae14cc1520a/test_tweepy.py#L10&quot;&gt;like I obviously did 😁&lt;/a&gt;) — so we can use them in Tweepy later on.&lt;/p&gt;
&lt;h2 id=&quot;get-the-data-with-pandas&quot;&gt;Get the data with Pandas&lt;/h2&gt;
&lt;p&gt;One of &lt;strong&gt;the&lt;/strong&gt; authoritative sources on Covid-19 data is &lt;a href=&quot;https://ourworldindata.org/&quot;&gt;Our World in Data&lt;/a&gt;. You can find their graphs all over the place. The data they gather is conveniently open (under a Creative Commons license) and &lt;a href=&quot;https://github.com/owid/covid-19-data/tree/master/public/data/vaccinations&quot;&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;652&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dThJeI5ENXybCcen6GsAow-34e7bbdf.CK0okt-i_Z1dnOht.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Grizzlies would be a better name… Image: CC BY-NC-ND 2.0 iregretjumping.&lt;/p&gt;
&lt;p&gt;Pandas, the &lt;em&gt;ironically named omnivore of data science&lt;/em&gt;, can chew this right up, straight from the raw URL. This saves you the step of manually downloading. Convenient! Look for the little “raw” button when viewing a file on GitHub and give that URL to your favorite ursid:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pand&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; as&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;read_csv(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/vaccinations.csv&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, parse_dates&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives us a nice dataframe containing which countries had what number of people vaccinated at which dates. They even keep track of whether people had only one or two (where applicable) shots. Not every country has good data, so Our World in Data only includes those numbers which pass their quality checks.&lt;/p&gt;
&lt;p&gt;For the time being, I’m using the column &lt;code&gt;people_vaccinated_per_hundred&lt;/code&gt; for the bot, because those numbers are a bit less depressing at the moment, but may switch to &lt;code&gt;people_fully_vaccinated_per_hundred&lt;/code&gt; later on. Since not all countries have data in these columns, this leaves us with a little over 50 countries &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/blob/e9d4eced48f315567c224f19068ab6bd8206020c/run.py#L55&quot;&gt;after filtering&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;calculate-continent-totals-with-pycountry_convert&quot;&gt;Calculate continent totals with pycountry_convert&lt;/h3&gt;
&lt;p&gt;Now, the table has numbers for the whole world pre-calculated, so I grabbed those for my first tests. But I thought it would be fun to also add some more detailed data.&lt;/p&gt;
&lt;p&gt;Twitter’s character limit prevents me from posting bars for all 56 countries, but we can certainly do continents. I think that’s still interesting, as well as poignant given the inequality in the world it so very clearly highlights. If the stark contrast makes policy makers think about fairer distribution for a second, that would be a huge win.&lt;/p&gt;
&lt;p&gt;Of course, finding the continents for 56 countries &lt;strong&gt;by hand&lt;/strong&gt; goes against everything I stand for as a lazy programmer. Obviously, I went about spending way more time on finding and figuring out a nice library that can do this work for me automatically. And, lo and behold, it exists, is called &lt;a href=&quot;https://pypi.org/project/pycountry-convert/&quot;&gt;pycountry_convert&lt;/a&gt; and &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/blob/e9d4eced48f315567c224f19068ab6bd8206020c/run.py#L49&quot;&gt;works like a charm&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Combine it with the &lt;a href=&quot;https://raw.githubusercontent.com/owid/covid-19-data/master/scripts/input/un/population_2020.csv&quot;&gt;total population table that Our World in Data also maintains&lt;/a&gt; and you’ve got all the ingredients you need to compute percentages per continent.&lt;/p&gt;
&lt;p&gt;Note that the continent numbers are not completely correct like this. Some countries span multiple continents (notably Russia). I treat such countries to just be part of one continent (so Russia is part of Europe, because pycountry_convert tells me it is).&lt;/p&gt;
&lt;h2 id=&quot;make-tweetable-progress-bars-with-tqdm&quot;&gt;Make Tweetable progress bars with tqdm&lt;/h2&gt;
&lt;p&gt;Now that we have percentages, we can convert them to progress bars.&lt;/p&gt;
&lt;p&gt;My go-to package for progress bars is &lt;code&gt;tqdm&lt;/code&gt;. It is especially good in interactive environments. There’s nothing like a progress bar to spice up a slow &lt;code&gt;for&lt;/code&gt; -loop. What’s more, &lt;code&gt;tqdm&lt;/code&gt; ’s bars look really good both in Jupyter notebooks and on the command line due to &lt;em&gt;using fancy unicode characters&lt;/em&gt;. The latter is exactly what I want to use here as well: Twitter is primarily a textual medium, and although I could just post images of progress bars (wait… why didn’t I? d’oh!), posting text-based bars should be an easy first option.&lt;/p&gt;
&lt;p&gt;Also, &lt;a href=&quot;https://twitter.com/year_progress&quot;&gt;year_progress&lt;/a&gt; does text-bars as well and that bot inspired this one, so there you go.&lt;/p&gt;
&lt;p&gt;Given some &lt;code&gt;percentage&lt;/code&gt; from the dataset, we can make a bar-string for posting to Twitter with something like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bar &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tqdm(initial&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;percentage, total&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bar_format&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{bar&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;15&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {percentage&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;1f}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;, ascii&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bar_string &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; str(bar)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tweet_string &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bar_string[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;replace(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;u3000&apos;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bar_string[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A few tricks beyond the &lt;code&gt;tqdm&lt;/code&gt; basics to highlight are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I used a custom format string to remove some superfluous stuff. We need to use as little characters as possible, but, also, it is important to not make the string too wide, otherwise it doesn’t display nicely on all devices (read: phones).&lt;/li&gt;
&lt;li&gt;Usually, &lt;code&gt;tqdm&lt;/code&gt; is used to display an “animated” progress bar. To emulate animation on the command line, it does all sorts of magic with carriage return (&lt;code&gt;\r&lt;/code&gt;) and new line (&lt;code&gt;\n&lt;/code&gt;) characters. I first tried using the &lt;code&gt;tqdm&lt;/code&gt; option of specifying an output stream using an &lt;code&gt;io.StringIO&lt;/code&gt; stream object, to act as a virtual terminal so to speak. I then tried to extract the bar string from that. This turned out to be quite a nightmarish experience (may have had to do with it getting quite late). Probably, &lt;code&gt;tqdm&lt;/code&gt; tries to do very smart things when outputting to this stream, and clearly I wasn’t smart enough to undo those smart things. Luckily, after a good night’s rest, I found that directly extracting the bar string from &lt;code&gt;bar.__str__()&lt;/code&gt; does not do weird animation stuff and just gives a neat, clean progress bar. Phew.&lt;/li&gt;
&lt;li&gt;Twitter is not a terminal. The relevance of this obvious statement is that Twitter does not use a fixed width font. Madness, I know. But luckily, the unicode committee (I’m sure there is one, perhaps several, in fact) blessed us with more kinds of space characters than we could ever have hoped for. &lt;code&gt;\u3000&lt;/code&gt;, the “ideographic space”, is the one that turns out to have the same width on Twitter as (most) unicode characters used for the bar itself. So I replace spaces in the bar (barring (heehee) those around the bar) with this ideographic one.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tweet-with-tweepy&quot;&gt;Tweet with Tweepy&lt;/h2&gt;
&lt;p&gt;The actual tweeting is the easiest part in all this. The &lt;a href=&quot;https://realpython.com/twitter-bot-python-tweepy/#creating-twitter-api-authentication-credentials&quot;&gt;above mentioned article&lt;/a&gt; explains most of it using the &lt;a href=&quot;https://www.tweepy.org/&quot;&gt;Tweepy&lt;/a&gt; package. You need the keys you obtained earlier to authenticate and create an &lt;code&gt;api&lt;/code&gt; object (see the snippet in the article).&lt;/p&gt;
&lt;p&gt;Then, tweeting is as simple as:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;update_status(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Ceci n&apos;est pas une tweet&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;810&quot; height=&quot;475&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_ZdxO48qSyJmHrXsL-1f57d952.Gm0PiurH_Z1X5XYc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simple. J’approuve.&lt;/p&gt;
&lt;p&gt;If all goes well, this command will return a giant blob of JSON, wrapped in some Tweepy class. Not to worry, do not disturb it, it means you no harm. If for some reason the Tweepy call failed, you’ll get an error message, so you’ll know when you actually have to start paying attention.&lt;/p&gt;
&lt;h2 id=&quot;automate-on-github-actions&quot;&gt;Automate on GitHub Actions&lt;/h2&gt;
&lt;p&gt;Obviously, the last part of the show is about getting rid of any future manual action and getting back to watching YouTube. We are programmers, after all. Moreover, we are scientists and we don’t have time for manual labor. That is what PhD stu…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[anxious whispering]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[angry, impatient whispering]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not supposed to…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[university PR department whispers]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ok, but…&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[whispered definitive executive order]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Automation, then!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[financial whispers]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For free! Yes, we can, with GitHub Actions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[mumbled approval]&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After putting all my code in a git repository (on GitHub), I created a workflow file &lt;code&gt;.github/workflows/tweet_progress.yml&lt;/code&gt;. The file looks something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Tweet&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; latest progresson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  schedule&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cron&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  &apos;0 &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&apos;  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;00&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; UTC&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, see https&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;://&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;crontab&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;guru&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; allows you to run this workflow manually from the &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Actions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tab&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  workflow_dispatch&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  tweet&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    runs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ubuntu&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    steps&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; actions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;checkout&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; uses&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; actions&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;setup&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; install dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pip install &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;r requirements&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run script&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        env&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_API&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_API }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_API_SECRET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_API_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_ACCESS&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_ACCESS }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;          BOT_ACCESS_SECRET&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{{ secrets.BOT_ACCESS_SECRET }}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; python run&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Under the &lt;code&gt;on&lt;/code&gt; section, we make our Tweepy script run on a regular &lt;code&gt;schedule&lt;/code&gt;: every day at 10 a.m., UTC (check out &lt;a href=&quot;https://crontab.guru/&quot;&gt;https://crontab.guru/&lt;/a&gt; if you don’t want to bother remembering the arcane cron syntax, thanks to&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/fca35bfb3190?source=post_page---user_mention--1cf3f19dcda8---------------------------------------&quot;&gt;Stefan Verhoeven&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;for the tip). The data is updated daily in the morning, so this should use the freshest data most days. We can also trigger the job manually by adding &lt;code&gt;workflow_dispatch&lt;/code&gt;. The part below &lt;code&gt;jobs&lt;/code&gt; is what will actually run on a GitHub machine and should be mostly self-explanatory. This will also be different for your specific application (unless you copy mine). The important thing to notice, though, is the bold part where I pass in all the keys.&lt;/p&gt;
&lt;p&gt;Two things to make this possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The awesome &lt;a href=&quot;https://pypi.org/project/ConfigArgParse/&quot;&gt;ConfigArgParse&lt;/a&gt; module allows for specifying program parameters in three ways: via command line arguments (like the Python standard library &lt;code&gt;argparse&lt;/code&gt;), via a config file or via environment variables, all through one convenient, almost-drop-in-replacement-of- &lt;code&gt;argparse&lt;/code&gt; call. On my laptop (for testing and such) I added a config file with the keys in it (and put the name of that file in &lt;code&gt;.gitignore&lt;/code&gt;, after my earlier key committing booboo), but on GitHub Actions I can now pass them in through environment variables via the &lt;code&gt;env&lt;/code&gt; section.&lt;/li&gt;
&lt;li&gt;The second part is those &lt;code&gt;${{ secrets.THING }}&lt;/code&gt; things. You have to &lt;a href=&quot;https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository&quot;&gt;store the Twitter keys in GitHub secrets (instructions here)&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Commit the yml file, push it to GitHub, and just like that you’ve got yourself an automatically updating Twitter bot!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;605&quot; height=&quot;568&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_l1__Q8DxN_LnAe_VU4L3CQ-2dc29b71.Dgpci5tY_2rTIFX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The top two tweets were automatically produced. It’s alive! ALIVE!!!&lt;/p&gt;
&lt;p&gt;I hope I convinced you that if you have a cool idea for a bot and know of a data source, you should immediately go for it! Just &lt;a href=&quot;https://github.com/egpbos/covid_vaccine_progress_bot/&quot;&gt;fork my repo&lt;/a&gt; if you want to get a quick start, modify it to your liking and put it out there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Congratulations&lt;/strong&gt;, you just made the world a better, more well-informed place!&lt;/p&gt;
&lt;p&gt;I’d love to hear what you think, let me know in the comments. Also, if you want some help setting up your bot, don’t hesitate to ask.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_YL2rNx2g8oxkMG149unWgQ-2fde1464.1WN8Ucbt.png" medium="image"/><author>Patrick Bos</author></item><item><title>Building a Web Service to Manage Scientific Simulation Data Using GraphQL</title><link>https://blog2.esciencecenter.nl/posts/2021-01-15---building-a-web-service-to-manage-scientific-simulation-data-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2021-01-15---building-a-web-service-to-manage-scientific-simulation-data-</guid><description>&lt;p&gt;Therefore, the &lt;a href=&quot;https://github.com/nlesc-nano/ceiba&quot;&gt;Ceiba&lt;/a&gt; web service needs to handle two kinds of requests by the client: read-only queries and mutations on the datasets. These “queries” and “mutations” can be easily describe with &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In a nutshell, &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; defines a contract (known as a schema) between the actions that a client can perform with the web service and the possible outcomes of those actions. More formally, &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; is a query language that allows you to specify an application Programming interface (API) using different programming languages. If you have previous experience with &lt;a href=&quot;https://en.wikipedia.org/wiki/Representational_state_transfer&quot;&gt;RESTful API&lt;/a&gt; have a look at a comparison between &lt;a href=&quot;https://www.howtographql.com/basics/1-graphql-is-the-better-rest/&quot;&gt;GraphQL and REST&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But how does GraphQL work? First, you need to define a schema using the &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; schema language. The following code snippet defines a schema to query a job using its status,&lt;/p&gt;
&lt;p&gt;Schema definition for job query&lt;/p&gt;
&lt;p&gt;The Query** schema specifies that in order to request some &lt;strong&gt;jobs&lt;/strong&gt;* you need to provide a &lt;em&gt;Status&lt;/em&gt; argument, where &lt;em&gt;Status&lt;/em&gt; can be one of four possibilities: &lt;em&gt;AVAILABLE, DONE, FAILED&lt;/em&gt; and *RUNNING. *The exclamation mark (!) indicates that the argument cannot be &lt;em&gt;Null&lt;/em&gt; (a.k.a &lt;em&gt;None&lt;/em&gt; in Python).&lt;/p&gt;
&lt;p&gt;The following &lt;strong&gt;Mutation&lt;/strong&gt; schema defines the required arguments to update a given job status.&lt;/p&gt;
&lt;p&gt;Schema definitation for Job status mutation&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;&lt;strong&gt;updateJob&lt;/strong&gt;&lt;/em&gt; action specifies that you must provide an &lt;em&gt;id&lt;/em&gt; and a &lt;em&gt;new_status&lt;/em&gt; in order to be able to update a job. You will receive a &lt;em&gt;Reply&lt;/em&gt; specifying whether the update action has succeeded.&lt;/p&gt;
&lt;p&gt;Have a look at the Ceiba &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/insilicoserver/sdl/Query.graphql&quot;&gt;queries&lt;/a&gt; and &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/insilicoserver/sdl/Mutation.graphql&quot;&gt;mutations&lt;/a&gt; schemas. They are slightly more complex than the aforementioned schemas but follow the same rationale as the previous examples. You can also have a look at the official &lt;a href=&quot;https://graphql.org/learn/&quot;&gt;introduction to GraphQL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have just defined the schemas that specify the actions that we want to perform. We still need to implement the actions and for doing so, we need a GraphQL engine: a library that takes the schemas together with the code that implements the actions and generates an API.&lt;/p&gt;
&lt;p&gt;We have chosen the &lt;a href=&quot;https://tartiflette.io/&quot;&gt;Tartiflette GraphQL engine&lt;/a&gt; to implement our web service mostly because it is easy to use and open source. The following snippet shows a possible implementation for querying jobs based on their status using &lt;a href=&quot;https://tartiflette.io/&quot;&gt;Tartiflette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;the &lt;em&gt;&lt;strong&gt;Resolver&lt;/strong&gt;&lt;/em&gt; decorator indicates that the &lt;em&gt;&lt;strong&gt;resolver_query_jobs&lt;/strong&gt;&lt;/em&gt; function corresponds to the implementation of the &lt;em&gt;&lt;strong&gt;query jobs&lt;/strong&gt;&lt;/em&gt; schema. The function takes 4 arguments of which I only use &lt;em&gt;&lt;strong&gt;args&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;ctx&lt;/strong&gt;&lt;/em&gt;(You can refer to &lt;a href=&quot;https://tartiflette.io/&quot;&gt;Tartiflette&lt;/a&gt; for further details). ***args ***contains the arguments given by the client code, while ***ctx ***contains the context for running the current function, for example the handler to access the database that is called &lt;em&gt;&lt;strong&gt;mongodb&lt;/strong&gt;&lt;/em&gt; in this code snippet.&lt;/p&gt;
&lt;p&gt;Notice that the definition of the aforementioned function starts with the &lt;em&gt;async&lt;/em&gt; keyword. &lt;a href=&quot;https://docs.python.org/3/library/asyncio.html&quot;&gt;Asyncio&lt;/a&gt; is a popular built-in Python library to write concurrent code. It is extensively used to write high performance web services.&lt;/p&gt;
&lt;p&gt;In the Ceiba web service implementation of the &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/tree/master/provisioning&quot;&gt;&lt;strong&gt;queries&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/insilicoserver/mutation_resolvers.py&quot;&gt;&lt;strong&gt;mutations&lt;/strong&gt;&lt;/a&gt;, there are definitions for all the Python functions that perform the actions specified in the GraphQL schemas. For each query and mutation, there is a corresponding function.&lt;/p&gt;
&lt;h2 id=&quot;the-database&quot;&gt;The database&lt;/h2&gt;
&lt;p&gt;We need a database not only for storing the interesting data but also to store the jobs metadata, like what jobs are available. For the Ceiba web service we use &lt;a href=&quot;https://www.mongodb.com/&quot;&gt;MongoDB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My personal opinion is that a &lt;a href=&quot;https://en.wikipedia.org/wiki/NoSQL&quot;&gt;NoSQL database&lt;/a&gt; like &lt;a href=&quot;https://www.mongodb.com/&quot;&gt;MongoDB&lt;/a&gt; gives a significant advantage over traditional SQL databases on research projects where up-front design of the schemas to store data is unfeasible. The research priorities can change as the project evolves and having dynamic schemas to store the data makes the researchers’ lives easier.&lt;/p&gt;
&lt;h2 id=&quot;putting-all-together&quot;&gt;Putting all together&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Building a Web Service to Manage Scientific Simulation Data Using GraphQL&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;456&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/building-a-web-service-to-manage-scienti-33d7f19d.DZVFi1SS_Z1O8kwP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@frankiefoto?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;frank mckenna&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker containers&lt;/a&gt; are the perfect way to ship our web service. We just need to write a [Dockerfile](&lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/&quot;&gt;https://github.com/nlesc-nano/insilico-server/blob/master/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dockerfile) with the recipe to install and start the service together with the &lt;a href=&quot;https://hub.docker.com/_/mongo&quot;&gt;mongo container&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to deploy the Ceiba web service to a remote server you need to follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install &lt;a href=&quot;https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html&quot;&gt;Ansible&lt;/a&gt; in your computer.&lt;/li&gt;
&lt;li&gt;Clone the &lt;a href=&quot;https://github.com/nlesc-nano/ceiba&quot;&gt;Ceiba&lt;/a&gt; repo and go to the &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/tree/master/provisioning&quot;&gt;provisioning&lt;/a&gt; folder.&lt;/li&gt;
&lt;li&gt;Edit the &lt;a href=&quot;https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html&quot;&gt;inventory&lt;/a&gt; file with the address of the server(s) where you want to install the runner.&lt;/li&gt;
&lt;li&gt;Edit the &lt;a href=&quot;https://docs.ansible.com/ansible/latest/user_guide/playbooks.html&quot;&gt;playbook&lt;/a&gt; file with the &lt;code&gt;remote_user&lt;/code&gt; name for the remote servers.&lt;/li&gt;
&lt;li&gt;Make sure that you can ssh to your server(s).&lt;/li&gt;
&lt;li&gt;Install the runner with the following command:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ansible-playbook -i inventory playbook.ymlThe Ceiba server should be up and running!&lt;/p&gt;
&lt;h2 id=&quot;the-pesky-details&quot;&gt;The pesky details&lt;/h2&gt;
&lt;p&gt;You certainly do not want to keep your web service open, so people can remove your data. You want that users are authenticated before using your service, but you also do not want to manage all the security on your own. Getting authentication right using something like &lt;a href=&quot;https://en.wikipedia.org/wiki/OAuth&quot;&gt;OAuth2&lt;/a&gt; is tricky and it needs at least an entire post on its own.&lt;/p&gt;
&lt;p&gt;Also, you need to host your web service somewhere and &lt;strong&gt;hosting costs money&lt;/strong&gt;. It is simply not viable that you host your service in your computer, it is not safe and it takes too much time to maintain. Fortunately for researchers, there are institutions like &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt; that can help you to host a web service for research purposes.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgement&quot;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;Creating the Ceiba web service would not be possible without &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt; advice and the computational resources provided by &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will also to thank &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jens-wehner/&quot;&gt;Jens Wehner&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-nicolas-renaud-2/&quot;&gt;Nicolas Renaud,&lt;/a&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/johan-hidding-msc/&quot;&gt;Johan Hidding&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-pablo-lopez-tarifa/&quot;&gt;Pablo Lopez-Tarifa&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/victor-azizi-msc/&quot;&gt;Victor Azizi&lt;/a&gt; for their feedback and support.&lt;/p&gt;
&lt;p&gt;Specially thanks to [Patrick Bos,] &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/tree/master/provisioning&quot;&gt;Tom Bakker&lt;/a&gt; for their feedback.&lt;/p&gt;</description><pubDate>Fri, 15 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Therefore, the &lt;a href=&quot;https://github.com/nlesc-nano/ceiba&quot;&gt;Ceiba&lt;/a&gt; web service needs to handle two kinds of requests by the client: read-only queries and mutations on the datasets. These “queries” and “mutations” can be easily describe with &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In a nutshell, &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; defines a contract (known as a schema) between the actions that a client can perform with the web service and the possible outcomes of those actions. More formally, &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; is a query language that allows you to specify an application Programming interface (API) using different programming languages. If you have previous experience with &lt;a href=&quot;https://en.wikipedia.org/wiki/Representational_state_transfer&quot;&gt;RESTful API&lt;/a&gt; have a look at a comparison between &lt;a href=&quot;https://www.howtographql.com/basics/1-graphql-is-the-better-rest/&quot;&gt;GraphQL and REST&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But how does GraphQL work? First, you need to define a schema using the &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt; schema language. The following code snippet defines a schema to query a job using its status,&lt;/p&gt;
&lt;p&gt;Schema definition for job query&lt;/p&gt;
&lt;p&gt;The Query** schema specifies that in order to request some &lt;strong&gt;jobs&lt;/strong&gt;* you need to provide a &lt;em&gt;Status&lt;/em&gt; argument, where &lt;em&gt;Status&lt;/em&gt; can be one of four possibilities: &lt;em&gt;AVAILABLE, DONE, FAILED&lt;/em&gt; and *RUNNING. *The exclamation mark (!) indicates that the argument cannot be &lt;em&gt;Null&lt;/em&gt; (a.k.a &lt;em&gt;None&lt;/em&gt; in Python).&lt;/p&gt;
&lt;p&gt;The following &lt;strong&gt;Mutation&lt;/strong&gt; schema defines the required arguments to update a given job status.&lt;/p&gt;
&lt;p&gt;Schema definitation for Job status mutation&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;&lt;strong&gt;updateJob&lt;/strong&gt;&lt;/em&gt; action specifies that you must provide an &lt;em&gt;id&lt;/em&gt; and a &lt;em&gt;new_status&lt;/em&gt; in order to be able to update a job. You will receive a &lt;em&gt;Reply&lt;/em&gt; specifying whether the update action has succeeded.&lt;/p&gt;
&lt;p&gt;Have a look at the Ceiba &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/insilicoserver/sdl/Query.graphql&quot;&gt;queries&lt;/a&gt; and &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/insilicoserver/sdl/Mutation.graphql&quot;&gt;mutations&lt;/a&gt; schemas. They are slightly more complex than the aforementioned schemas but follow the same rationale as the previous examples. You can also have a look at the official &lt;a href=&quot;https://graphql.org/learn/&quot;&gt;introduction to GraphQL&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have just defined the schemas that specify the actions that we want to perform. We still need to implement the actions and for doing so, we need a GraphQL engine: a library that takes the schemas together with the code that implements the actions and generates an API.&lt;/p&gt;
&lt;p&gt;We have chosen the &lt;a href=&quot;https://tartiflette.io/&quot;&gt;Tartiflette GraphQL engine&lt;/a&gt; to implement our web service mostly because it is easy to use and open source. The following snippet shows a possible implementation for querying jobs based on their status using &lt;a href=&quot;https://tartiflette.io/&quot;&gt;Tartiflette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;the &lt;em&gt;&lt;strong&gt;Resolver&lt;/strong&gt;&lt;/em&gt; decorator indicates that the &lt;em&gt;&lt;strong&gt;resolver_query_jobs&lt;/strong&gt;&lt;/em&gt; function corresponds to the implementation of the &lt;em&gt;&lt;strong&gt;query jobs&lt;/strong&gt;&lt;/em&gt; schema. The function takes 4 arguments of which I only use &lt;em&gt;&lt;strong&gt;args&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;ctx&lt;/strong&gt;&lt;/em&gt;(You can refer to &lt;a href=&quot;https://tartiflette.io/&quot;&gt;Tartiflette&lt;/a&gt; for further details). ***args ***contains the arguments given by the client code, while ***ctx ***contains the context for running the current function, for example the handler to access the database that is called &lt;em&gt;&lt;strong&gt;mongodb&lt;/strong&gt;&lt;/em&gt; in this code snippet.&lt;/p&gt;
&lt;p&gt;Notice that the definition of the aforementioned function starts with the &lt;em&gt;async&lt;/em&gt; keyword. &lt;a href=&quot;https://docs.python.org/3/library/asyncio.html&quot;&gt;Asyncio&lt;/a&gt; is a popular built-in Python library to write concurrent code. It is extensively used to write high performance web services.&lt;/p&gt;
&lt;p&gt;In the Ceiba web service implementation of the &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/tree/master/provisioning&quot;&gt;&lt;strong&gt;queries&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/insilicoserver/mutation_resolvers.py&quot;&gt;&lt;strong&gt;mutations&lt;/strong&gt;&lt;/a&gt;, there are definitions for all the Python functions that perform the actions specified in the GraphQL schemas. For each query and mutation, there is a corresponding function.&lt;/p&gt;
&lt;h2 id=&quot;the-database&quot;&gt;The database&lt;/h2&gt;
&lt;p&gt;We need a database not only for storing the interesting data but also to store the jobs metadata, like what jobs are available. For the Ceiba web service we use &lt;a href=&quot;https://www.mongodb.com/&quot;&gt;MongoDB&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My personal opinion is that a &lt;a href=&quot;https://en.wikipedia.org/wiki/NoSQL&quot;&gt;NoSQL database&lt;/a&gt; like &lt;a href=&quot;https://www.mongodb.com/&quot;&gt;MongoDB&lt;/a&gt; gives a significant advantage over traditional SQL databases on research projects where up-front design of the schemas to store data is unfeasible. The research priorities can change as the project evolves and having dynamic schemas to store the data makes the researchers’ lives easier.&lt;/p&gt;
&lt;h2 id=&quot;putting-all-together&quot;&gt;Putting all together&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;Building a Web Service to Manage Scientific Simulation Data Using GraphQL&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;456&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/building-a-web-service-to-manage-scienti-33d7f19d.DZVFi1SS_Z1O8kwP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@frankiefoto?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;frank mckenna&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker containers&lt;/a&gt; are the perfect way to ship our web service. We just need to write a [Dockerfile](&lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/blob/master/&quot;&gt;https://github.com/nlesc-nano/insilico-server/blob/master/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dockerfile) with the recipe to install and start the service together with the &lt;a href=&quot;https://hub.docker.com/_/mongo&quot;&gt;mongo container&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to deploy the Ceiba web service to a remote server you need to follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install &lt;a href=&quot;https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html&quot;&gt;Ansible&lt;/a&gt; in your computer.&lt;/li&gt;
&lt;li&gt;Clone the &lt;a href=&quot;https://github.com/nlesc-nano/ceiba&quot;&gt;Ceiba&lt;/a&gt; repo and go to the &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/tree/master/provisioning&quot;&gt;provisioning&lt;/a&gt; folder.&lt;/li&gt;
&lt;li&gt;Edit the &lt;a href=&quot;https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html&quot;&gt;inventory&lt;/a&gt; file with the address of the server(s) where you want to install the runner.&lt;/li&gt;
&lt;li&gt;Edit the &lt;a href=&quot;https://docs.ansible.com/ansible/latest/user_guide/playbooks.html&quot;&gt;playbook&lt;/a&gt; file with the &lt;code&gt;remote_user&lt;/code&gt; name for the remote servers.&lt;/li&gt;
&lt;li&gt;Make sure that you can ssh to your server(s).&lt;/li&gt;
&lt;li&gt;Install the runner with the following command:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ansible-playbook -i inventory playbook.ymlThe Ceiba server should be up and running!&lt;/p&gt;
&lt;h2 id=&quot;the-pesky-details&quot;&gt;The pesky details&lt;/h2&gt;
&lt;p&gt;You certainly do not want to keep your web service open, so people can remove your data. You want that users are authenticated before using your service, but you also do not want to manage all the security on your own. Getting authentication right using something like &lt;a href=&quot;https://en.wikipedia.org/wiki/OAuth&quot;&gt;OAuth2&lt;/a&gt; is tricky and it needs at least an entire post on its own.&lt;/p&gt;
&lt;p&gt;Also, you need to host your web service somewhere and &lt;strong&gt;hosting costs money&lt;/strong&gt;. It is simply not viable that you host your service in your computer, it is not safe and it takes too much time to maintain. Fortunately for researchers, there are institutions like &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt; that can help you to host a web service for research purposes.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgement&quot;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;Creating the Ceiba web service would not be possible without &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt; advice and the computational resources provided by &lt;a href=&quot;https://www.surf.nl/en&quot;&gt;SURF&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will also to thank &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-jens-wehner/&quot;&gt;Jens Wehner&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-nicolas-renaud-2/&quot;&gt;Nicolas Renaud,&lt;/a&gt; &lt;a href=&quot;https://www.esciencecenter.nl/team/johan-hidding-msc/&quot;&gt;Johan Hidding&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-pablo-lopez-tarifa/&quot;&gt;Pablo Lopez-Tarifa&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/victor-azizi-msc/&quot;&gt;Victor Azizi&lt;/a&gt; for their feedback and support.&lt;/p&gt;
&lt;p&gt;Specially thanks to [Patrick Bos,] &lt;a href=&quot;https://github.com/nlesc-nano/insilico-server/tree/master/provisioning&quot;&gt;Tom Bakker&lt;/a&gt; for their feedback.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/building-a-web-service-to-manage-scienti-33d7f19d.DZVFi1SS.jpg" medium="image"/><author>Felipe</author></item><item><title>eScience trends from ADASS 2020</title><link>https://blog2.esciencecenter.nl/posts/2020-11-23---escience-trends-from-adass-2020</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-11-23---escience-trends-from-adass-2020</guid><description>&lt;h1 id=&quot;escience-trends-from-adass-2020&quot;&gt;&lt;strong&gt;eScience trends from ADASS 2020&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;scaling-up-compute-and-storage-resources-are-not-going-to-be-the-biggest-hurdles&quot;&gt;&lt;strong&gt;Scaling up compute and storage resources are not going to be the biggest hurdles.&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;**8&lt;/p&gt;
&lt;h3 id=&quot;my-general-feeling-about-this-conference&quot;&gt;My general feeling about this conference&lt;/h3&gt;
&lt;p&gt;What a delight ADASS (Astronomical Data Analysis Software and Systems) 2020 was! My first virtual conference, but the same positive vibe as the previous one, ADASS 2019 in Groningen, The Netherlands. This one was in Granada, Spain, but it could have been anywhere, obviously. There were 581 participants and over 50 talks. Last year, ADASS had 353 participants, which was also quite considerable. One of the organisers said that there were quite a few participants from previously underrepresented countries. The cost of participating in this virtual conference was substantially lower than for the physical conferences, which could explain its popularity this year.&lt;/p&gt;
&lt;p&gt;In hindsight, the Discord tool for discussion and social talk was essential. This gave me a feeling of being part of this conference. It was set up nicely with separate channels for each session, that continued after the session had ended, together with a number of general channels. Talks started at 6:00 a.m. CET and ended at 20:30 CET with somewhat fewer talks during the middle of the day to accommodate for speakers and audience in other time zones. Of course, it is impossible to make a schedule that fits all time zones, but I guess the organisers wanted to avoid people having to present their work at 3 a.m. local time.&lt;/p&gt;
&lt;h3 id=&quot;highlights&quot;&gt;Highlights&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;eScience trends from ADASS 2020&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;372&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-5a8a4b9c.BSv99xzV_Z1ukvpi.webp&quot; srcset=&quot;&quot;&gt;
Slide from Matthew Graham’s presentation “&lt;a href=&quot;https://www.youtube.com/watch?v=rPb22usn7hU&amp;#x26;t=41m10s&quot;&gt;What did we get right? Lessons learned from the first 300 million alerts of ZTF&lt;/a&gt;” .Matthew Graham** (invited speaker, professor at Caltech and project scientist for ZTF, the Zwicky Transient Facility), started off by listing his predictions from his ADASS 2008 presentation: what he thought would be the main bottlenecks and achievements in astronomy by the year 2020. Here are two of those predictions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In 2008 he perceived that artificial intelligence would govern the alert streams without human interactions. We have clearly not reached that point yet. Humans are still in the loop, i.e. the current machine learning algorithms are not fully trusted.&lt;/li&gt;
&lt;li&gt;In 2020, we would have huge problems with scalability to process the data firehoses and store the data lakes. As stated clearly in the slide above, this turns out not to be the case: we do have the compute power and storage to handle all this data and we can develop software that scales well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead our focus needs to shift from data management to information and knowledge management. Present concerns are about establishing veracity, about provenance and probabilities based on astrophysical statistics. What are my assumptions and where are they coming from? These are presently much more severe concerns in delivering sound scientific conclusions than technogical challenges, they require astronomical or astrophysical expertise rather than computer engineering solutions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;eScience trends from ADASS 2020&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;341&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-fce35a68.D-tBYYNM_1P46Xj.webp&quot; srcset=&quot;&quot;&gt;
Slide from talk by Verdana Desai: “Enabling next-generation science investigations with the NASA Astrophysics Archives”.&lt;strong&gt;Vandana Desai&lt;/strong&gt; (invited speaker, associate scientist at Caltech and science lead for the Infrared Science Archive (IRSA) of IPAC, the Infrared Processing &amp;#x26; Analysis Center) gave an insightful talk: “Enabling next-generation science investigations with the NASA Astrophysics Archives”. This covered part of her white paper “&lt;a href=&quot;https://www.noao.edu/2020Decadal/files/DesaiVandana.pdf&quot;&gt;A Science Platform Network to Facilitate Astrophysics in the 2020s&lt;/a&gt;”. This white paper advocates “funding of data centers to develop and operate ‘science platforms’, which will provide storage and computing resources for the astronomical community to run analyses near the data”. “Science platforms” are envisaged as the way to enable scientific progress in the era of big data; our progress in understanding physical processes in the cosmos is enhanced by the simultaneous use of multi-wavelength observations possibly augmented with neutrino and gravitational wave detections. These platforms should accommodate the needs of a much larger group than just the ‘power users’, serving many more than the inner circle of scientists that are aware of all the complexities involved in reducing the raw data. Desai made clear that “We cannot have all of the data that an astronomer might want to use under a single, unified science platform”. This is not feasible “and probably never will be “ because of the “practicalities involved” which I suppose reflects the heterogeneity of astronomical observations. It is clear that analysis tools, including machine learning will require more compute power. The bottom panel from the slide above shows the increased use of archival data in the last decades, i.e. the use of data by others than the people near the principal investigator of a rewarded observing proposal. Until now, the combined data from astronomical sources was mostly extracted from catalogs which only include a few quantities like position on the sky, peak intensity, integrated flux and perhaps a few other quantities derived from the source pixel distribution. In the future, astronomers will need access to the actual pixels comprising the source for a more accurate analysis, which enhances the demand for storage and computing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;eScience trends from ADASS 2020&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-cf4353c4.CBfjN8-G_jh76q.webp&quot; srcset=&quot;&quot;&gt;
Slide from Cristobal Bordiu’s presentation “&lt;a href=&quot;https://www.youtube.com/watch?v=oG_Xq3FzRGU&amp;#x26;t=1h53m36s&quot;&gt;Astronomical research in the next decade: trends, barriers and needs in data access, management, visualization and analysis&lt;/a&gt;”.Some of the same conclusions, but more from a European rather than American perspective, were drawn by &lt;strong&gt;Cristobal Bordiu&lt;/strong&gt; (postdoc for the Italian National Institute of Astrophysics (INAF) at the Catania Astrophysical Observatory) from a survey for NEANIAS (Novel EOSC Services for Emerging Atmosphere, Underwater &amp;#x26; Space Challenges). This project, which emerged from EOSC, the European Open Science Cloud, aims to set solid foundations for astronomy in the coming decade, so it covers the same time span as the &lt;a href=&quot;https://www.noao.edu/2020Decadal/files/DesaiVandana.pdf&quot;&gt;white paper by Desai et al.&lt;/a&gt; The respondees showed concern about storage, about reproducibility and about findability and interopability of raw, calibrated and higher level data products, as reflected by the slide above. They also perceive the availability of visual analytics tools as a main research barrier.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The lack of science-ready data products, &lt;a href=&quot;https://blog2.esciencecenter.nl/escience-trends-from-adass-2019-f68cd8cca49b&quot;&gt;which I reported on last year&lt;/a&gt;, applies mostly to radio astronomy, where the complete reduction of observations, including calibration of visibilities and subsequent imaging has to be done quite often by the researchers themselves. Fortunately, this situation is improving, with radio observatories taking up the glove. However, what ADASS 2020 made clear, is that more is needed that just these science-ready data products; to enhance scientific progress interoperable data from simultaneous observations at multiple electromagnetic wavelengths — possibly augmented with neutrino and gravitational wave detections— are required. Most conveniently, these would be analysed using “science platforms” which offer software tools for analysis, such as machine learning, that can be run in a completely hardware agnostic way.&lt;/p&gt;</description><pubDate>Mon, 23 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;escience-trends-from-adass-2020&quot;&gt;&lt;strong&gt;eScience trends from ADASS 2020&lt;/strong&gt;&lt;/h1&gt;
&lt;h2 id=&quot;scaling-up-compute-and-storage-resources-are-not-going-to-be-the-biggest-hurdles&quot;&gt;&lt;strong&gt;Scaling up compute and storage resources are not going to be the biggest hurdles.&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;**8&lt;/p&gt;
&lt;h3 id=&quot;my-general-feeling-about-this-conference&quot;&gt;My general feeling about this conference&lt;/h3&gt;
&lt;p&gt;What a delight ADASS (Astronomical Data Analysis Software and Systems) 2020 was! My first virtual conference, but the same positive vibe as the previous one, ADASS 2019 in Groningen, The Netherlands. This one was in Granada, Spain, but it could have been anywhere, obviously. There were 581 participants and over 50 talks. Last year, ADASS had 353 participants, which was also quite considerable. One of the organisers said that there were quite a few participants from previously underrepresented countries. The cost of participating in this virtual conference was substantially lower than for the physical conferences, which could explain its popularity this year.&lt;/p&gt;
&lt;p&gt;In hindsight, the Discord tool for discussion and social talk was essential. This gave me a feeling of being part of this conference. It was set up nicely with separate channels for each session, that continued after the session had ended, together with a number of general channels. Talks started at 6:00 a.m. CET and ended at 20:30 CET with somewhat fewer talks during the middle of the day to accommodate for speakers and audience in other time zones. Of course, it is impossible to make a schedule that fits all time zones, but I guess the organisers wanted to avoid people having to present their work at 3 a.m. local time.&lt;/p&gt;
&lt;h3 id=&quot;highlights&quot;&gt;Highlights&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;eScience trends from ADASS 2020&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;372&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-5a8a4b9c.BSv99xzV_Z1ukvpi.webp&quot; srcset=&quot;&quot;&gt;
Slide from Matthew Graham’s presentation “&lt;a href=&quot;https://www.youtube.com/watch?v=rPb22usn7hU&amp;#x26;t=41m10s&quot;&gt;What did we get right? Lessons learned from the first 300 million alerts of ZTF&lt;/a&gt;” .Matthew Graham** (invited speaker, professor at Caltech and project scientist for ZTF, the Zwicky Transient Facility), started off by listing his predictions from his ADASS 2008 presentation: what he thought would be the main bottlenecks and achievements in astronomy by the year 2020. Here are two of those predictions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In 2008 he perceived that artificial intelligence would govern the alert streams without human interactions. We have clearly not reached that point yet. Humans are still in the loop, i.e. the current machine learning algorithms are not fully trusted.&lt;/li&gt;
&lt;li&gt;In 2020, we would have huge problems with scalability to process the data firehoses and store the data lakes. As stated clearly in the slide above, this turns out not to be the case: we do have the compute power and storage to handle all this data and we can develop software that scales well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead our focus needs to shift from data management to information and knowledge management. Present concerns are about establishing veracity, about provenance and probabilities based on astrophysical statistics. What are my assumptions and where are they coming from? These are presently much more severe concerns in delivering sound scientific conclusions than technogical challenges, they require astronomical or astrophysical expertise rather than computer engineering solutions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;eScience trends from ADASS 2020&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;341&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-fce35a68.D-tBYYNM_1P46Xj.webp&quot; srcset=&quot;&quot;&gt;
Slide from talk by Verdana Desai: “Enabling next-generation science investigations with the NASA Astrophysics Archives”.&lt;strong&gt;Vandana Desai&lt;/strong&gt; (invited speaker, associate scientist at Caltech and science lead for the Infrared Science Archive (IRSA) of IPAC, the Infrared Processing &amp;#x26; Analysis Center) gave an insightful talk: “Enabling next-generation science investigations with the NASA Astrophysics Archives”. This covered part of her white paper “&lt;a href=&quot;https://www.noao.edu/2020Decadal/files/DesaiVandana.pdf&quot;&gt;A Science Platform Network to Facilitate Astrophysics in the 2020s&lt;/a&gt;”. This white paper advocates “funding of data centers to develop and operate ‘science platforms’, which will provide storage and computing resources for the astronomical community to run analyses near the data”. “Science platforms” are envisaged as the way to enable scientific progress in the era of big data; our progress in understanding physical processes in the cosmos is enhanced by the simultaneous use of multi-wavelength observations possibly augmented with neutrino and gravitational wave detections. These platforms should accommodate the needs of a much larger group than just the ‘power users’, serving many more than the inner circle of scientists that are aware of all the complexities involved in reducing the raw data. Desai made clear that “We cannot have all of the data that an astronomer might want to use under a single, unified science platform”. This is not feasible “and probably never will be “ because of the “practicalities involved” which I suppose reflects the heterogeneity of astronomical observations. It is clear that analysis tools, including machine learning will require more compute power. The bottom panel from the slide above shows the increased use of archival data in the last decades, i.e. the use of data by others than the people near the principal investigator of a rewarded observing proposal. Until now, the combined data from astronomical sources was mostly extracted from catalogs which only include a few quantities like position on the sky, peak intensity, integrated flux and perhaps a few other quantities derived from the source pixel distribution. In the future, astronomers will need access to the actual pixels comprising the source for a more accurate analysis, which enhances the demand for storage and computing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;eScience trends from ADASS 2020&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-cf4353c4.CBfjN8-G_jh76q.webp&quot; srcset=&quot;&quot;&gt;
Slide from Cristobal Bordiu’s presentation “&lt;a href=&quot;https://www.youtube.com/watch?v=oG_Xq3FzRGU&amp;#x26;t=1h53m36s&quot;&gt;Astronomical research in the next decade: trends, barriers and needs in data access, management, visualization and analysis&lt;/a&gt;”.Some of the same conclusions, but more from a European rather than American perspective, were drawn by &lt;strong&gt;Cristobal Bordiu&lt;/strong&gt; (postdoc for the Italian National Institute of Astrophysics (INAF) at the Catania Astrophysical Observatory) from a survey for NEANIAS (Novel EOSC Services for Emerging Atmosphere, Underwater &amp;#x26; Space Challenges). This project, which emerged from EOSC, the European Open Science Cloud, aims to set solid foundations for astronomy in the coming decade, so it covers the same time span as the &lt;a href=&quot;https://www.noao.edu/2020Decadal/files/DesaiVandana.pdf&quot;&gt;white paper by Desai et al.&lt;/a&gt; The respondees showed concern about storage, about reproducibility and about findability and interopability of raw, calibrated and higher level data products, as reflected by the slide above. They also perceive the availability of visual analytics tools as a main research barrier.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The lack of science-ready data products, &lt;a href=&quot;https://blog2.esciencecenter.nl/escience-trends-from-adass-2019-f68cd8cca49b&quot;&gt;which I reported on last year&lt;/a&gt;, applies mostly to radio astronomy, where the complete reduction of observations, including calibration of visibilities and subsequent imaging has to be done quite often by the researchers themselves. Fortunately, this situation is improving, with radio observatories taking up the glove. However, what ADASS 2020 made clear, is that more is needed that just these science-ready data products; to enhance scientific progress interoperable data from simultaneous observations at multiple electromagnetic wavelengths — possibly augmented with neutrino and gravitational wave detections— are required. Most conveniently, these would be analysed using “science platforms” which offer software tools for analysis, such as machine learning, that can be run in a completely hardware agnostic way.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/escience-trends-from-adass-2020-5a8a4b9c.BSv99xzV.png" medium="image"/><author>Hanno Spreeuw</author></item><item><title>Being a minority in fancy coding land: a Windows user.</title><link>https://blog2.esciencecenter.nl/posts/2020-11-10---being-a-minority-in-fancy-coding-land-a-windows-user</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-11-10---being-a-minority-in-fancy-coding-land-a-windows-user</guid><description>&lt;h2 id=&quot;how-i-slowly-went-from-my-imposter-syndrome-hiding-to-accepting-what-i-am-a-windows-user-at-least-most-of-the-time-dont-worry-this-is-not-one-of-those-linux-vs-windows-posts&quot;&gt;How I slowly went from my imposter-syndrome hiding to accepting what I am. A Windows user, at least most of the time. (Don’t worry, this is NOT one of those Linux vs. Windows posts!)&lt;/h2&gt;
&lt;p&gt;I work at the &lt;a href=&quot;http://esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, a wonderful organization with very nice colleagues. Hopefully nice enough to stay my colleagues after the following confession: I am a Windows user.&lt;/p&gt;
&lt;p&gt;What’s so special about this? Most people use Windows, right?&lt;br&gt;
Well, not in my small &lt;em&gt;coding bubble&lt;/em&gt;.&lt;br&gt;
In the world I work in (use all your cliché imagination on nerds, hackers, computer scientists … but then remove those pictures of people wearing sun glasses indoors and desks full of pizza and caffeine-rich soft-drinks) coding from a Windows environment is often considered something between a no-go and a handicap. Breathing quickly, my fingers start to tremble as I write this, risking my career as a data scientist and machine learning practitioner. Or isn’t it all that bad?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1143&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_omI5G0XyVglCsQpBFmgf9A-744fa126.DLyAPxQw_Z1a64X8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;how-did-i-end-up-using-windows&quot;&gt;How did I end up using Windows?&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(I see your shaking heads… why the hell did he end up there?)&lt;/em&gt;&lt;br&gt;
Let’s just say I have grown into it. All the way from &lt;a href=&quot;https://en.wikipedia.org/wiki/MS-DOS&quot;&gt;MS DOS&lt;/a&gt; through many painfully bad Windows versions and then I got so used to it that &lt;strong&gt;my skills to deal with it always felt better than my skills in handling the alternatives&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In addition, I am not a software developer or computer scientist by training. For a long time I was a physicist, a scientist, an academic. And in the scientific fields where I was working, using Windows was — believe it or not —the norm.&lt;/p&gt;
&lt;p&gt;Sure, I had already installed VirtualBox on my computer to run Ubuntu. I had even done some stuff with Ubuntu, including training some machine learning models (for implementations for which the packages didn’t support Windows…). I knew the 10 most common shell commands and everything else I would simply look up when needed. No wonder working with Linux still feels like writing a long letter with my left hand (I am right handed): I am terribly slow and in the end it looks horrible.&lt;/p&gt;
&lt;h3 id=&quot;but--why&quot;&gt;But … why?&lt;/h3&gt;
&lt;p&gt;Ah, I see. That all sounds like lame excuses to you.&lt;br&gt;
Well, it is not that I didn’t see all those golden merits of using Linux over Windows. Of course that’s the better system for many tasks, say setting up a server or handling access rights. And yes, it is much less wasteful in using hardware resources, it is considered less vulnerable, … and so on …, plus it is freely available without commercial interests. Still, I never wanted to pay the price of not having access to some of the high-end software that you would get on mac-OS or Windows (such as some MS office stuff or Adobe products). By the way: I am not trying to convince anybody that Windows is the best option. I am already happy if we can agree that it is &lt;em&gt;&lt;strong&gt;an&lt;/strong&gt;&lt;/em&gt; option.&lt;/p&gt;
&lt;p&gt;Time for another uncomfortable revelation: sometimes, being lazy simply pays off. For instance if you need to sort out a huge pile of stuff with some emotional value to you. Just put it in a box and hide it, take it out 10 years later and easily decide to dump nearly all of it. That’s a bit what I did with Linux. I survived with minimal use of VirtualBx and alike. Until recently, &lt;em&gt;finally!&lt;/em&gt;, Linux became part of Windows. And that works pretty well for me. &lt;a href=&quot;https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/&quot;&gt;See how simple it now is to run Linux from Windows 10.&lt;/a&gt; And enjoy how easily you now can have the best of both worlds (not for nothing are more and more people arguing &lt;a href=&quot;https://towardsdatascience.com/dual-boot-is-dead-windows-and-linux-are-now-one-27555902a128&quot;&gt;that the good old “dual boot” is dead&lt;/a&gt; for exactly this reason).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1882&quot; height=&quot;1122&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ct2nr1TdVL8Qnmn5S2StDA-d5cb5a59.CpL0kF93_1djj7g.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using Windows and Ubuntu side by side… in front of wonderful ugly-ish Windows blue… what a peaceful view, isn’t it?&lt;/p&gt;
&lt;p&gt;Enough all-united-hippie-talk. Let me share a few impressions of the actual life of an aspiring data scientist/research software engineer that happens to use Windows:&lt;/p&gt;
&lt;h3 id=&quot;starting-a-new-job&quot;&gt;Starting a new job.&lt;/h3&gt;
&lt;p&gt;I did a lot of programming as a researcher, but clearly I had never learned the proper software development basics such as testing, versioning etc. (in many academic fields those terms are often still unheard of!). No wonder I suffered a lot from imposter syndrome in the very beginning.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I hope they won’t find out I can’t write proper code!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Naturally, that means that you might not immediately ask your colleagues for help, because that would reveal your amateur level, right?&lt;br&gt;
But even worse, imagining you ask that colleague about how to get that Python package working and it turns out you are using Windows?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can you help me setting up that environment? … By the way … I use Windows for that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The looks you get are suggesting that you have just asked how to import a 5GB.csv file into your Excel table (&lt;em&gt;*you don’t*&lt;/em&gt;). So little surprise I did spend a fair amount of time in Forum-Land during my first months…&lt;/p&gt;
&lt;h3 id=&quot;being-that-windows-user-in-the-room&quot;&gt;Being that Windows user in the room&lt;/h3&gt;
&lt;p&gt;You sit in that hands-on workshop on some fancy programming techniques, and the instructors asks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is there anybody using Windows? (chuckles)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or, actually worse, nobody asks. Of course the instructions are only given for Linux and mac-OS. Well, at least I can hide my Windows handicap for a little longer then… but &lt;strong&gt;NO&lt;/strong&gt;!, when the instructor walks around to inspect the progress of the participants she/he will of course shout out:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Wow … you are really using Windows for that!?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Great. Now officially being tagged as &lt;strong&gt;the Windows user&lt;/strong&gt; in the room. Better keep quiet and not ask any silly questions then…&lt;/p&gt;
&lt;h3 id=&quot;get-used-to-rolled-eyes-then-secretly-roll-your-eyes-too&quot;&gt;Get used to rolled eyes —then secretly roll your eyes, too.&lt;/h3&gt;
&lt;p&gt;As I grew more confident of what I was doing, the imposter syndrome started to disappear. It still occasionally comes back to say hello (for instance if people speak shell over coffee), but that’s OK.&lt;/p&gt;
&lt;p&gt;In the end it’s luckily the results that matters most. I learned that you can write as good or bad code on Windows as on Linux. You can build great software on Windows that is then used by Linux people, and the other way around. Sure, for some things you better go the Linux way. But it turns out that in my projects this is less than 1% of my working time, which makes it OK to be a bit clumsy using it. And secretly (&lt;em&gt;don’t point at them, that’s mean!&lt;/em&gt;), I can also enjoy those moments when another colloquium presentation doesn’t run properly because Ubuntu did not work well with the projector, or the microphone, or both.&lt;/p&gt;
&lt;h3 id=&quot;do-better-than-pointing-at-each-other&quot;&gt;Do better than pointing at each other&lt;/h3&gt;
&lt;p&gt;Windows is more convenient for running some very common software (e.g. MS office), Linux is more stable… so go some cliches. But instead of fighting about what’s better (or hiding what feels inferior) it makes more sense to me to accept what’s there and simply go along with it. If somebody lives in a very geeky bubble it works fine to safely assume everyone runs their code on a certain operating systems and knows the in and outs of object oriented programming and containerization. But many of the more exciting projects involve people outside this bubble: researchers, users, future contributors, students. And they might as well — lo and behold — be using Windows (and by the way: containers are still primarily &lt;strong&gt;big steel boxes&lt;/strong&gt; to most people).&lt;/p&gt;
&lt;p&gt;So, even though in some IT-bubbles it can occasionally feel as if we are talking about a small unfortunate minority … in reality that’s really not true. Check out &lt;a href=&quot;https://www.freecodecamp.org/news/stack-overflow-developer-survey-2020-programming-language-framework-salary-data/&quot;&gt;the 2020 Stack Overflow Developer Survey&lt;/a&gt; to see that &lt;strong&gt;most developers actually use Windows&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;what-can-you-do-to-get-more-windows-users-to-adopt-your-package&quot;&gt;What can you do to get more Windows users to adopt your package?&lt;/h3&gt;
&lt;p&gt;Think of Windows what you want. I don’t work for Microsoft, and honestly, I don’t really care. But I assume that many coders out there working on great new software, methods, tools, tutorials, etc. actually want that people become happy users (paid by eternal gratitude). And that is a good enough reason to think about those Windows users as well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consider setting up your next continuous integration for your software package, so that it runs on all systems and will be used by more people.&lt;br&gt;
For instance with &lt;a href=&quot;https://docs.github.com/en/free-pro-team@latest/actions/guides/about-continuous-integration&quot;&gt;continuous integration using GitHub&lt;/a&gt; actions it can be as simple as adding a &lt;code&gt;‘windows-latest’&lt;/code&gt; to your matrix:&lt;br&gt;
&lt;code&gt;os: [‘ubuntu-latest’, ‘macos-latest’, ‘windows-latest’]   &lt;/code&gt; (small warning: adding different operating systems to such a continuous integration workflow is comparably easy, the later debugging sometimes is not. One option can be to work with &lt;a href=&quot;https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/&quot;&gt;Windows virtual machine&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;What about providing installation instructions for Windows users as well? Or did you just write a new tutorial? Great! But will it work for your fellow Windows users? You would be surprised how many packages and tutorials come with instructions that clearly won’t work for a Windows user.&lt;br&gt;
Don’t know how to do that? No Problem! Just ask a Windows user to help you. Believe me, they will be very glad to assist.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;final-symmetry&quot;&gt;Final symmetry&lt;/h3&gt;
&lt;p&gt;Most of my arguments will hold when we just swap the named OS. So, obviously if you are (like me) primarily a Windows user: Think of all those Linux and mac-OS people out there. Either way, it will require learning a bit about the differences. But it will help to avoid a lot of frustration on all ends due to failing notebooks or hard to install packages.&lt;/p&gt;
&lt;h3 id=&quot;get-in-touch&quot;&gt;Get in touch&lt;/h3&gt;
&lt;p&gt;If you have comments or questions please get in touch! You can also find me on twitter: &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;&lt;strong&gt;me_datapoint&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 10 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;how-i-slowly-went-from-my-imposter-syndrome-hiding-to-accepting-what-i-am-a-windows-user-at-least-most-of-the-time-dont-worry-this-is-not-one-of-those-linux-vs-windows-posts&quot;&gt;How I slowly went from my imposter-syndrome hiding to accepting what I am. A Windows user, at least most of the time. (Don’t worry, this is NOT one of those Linux vs. Windows posts!)&lt;/h2&gt;
&lt;p&gt;I work at the &lt;a href=&quot;http://esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, a wonderful organization with very nice colleagues. Hopefully nice enough to stay my colleagues after the following confession: I am a Windows user.&lt;/p&gt;
&lt;p&gt;What’s so special about this? Most people use Windows, right?&lt;br&gt;
Well, not in my small &lt;em&gt;coding bubble&lt;/em&gt;.&lt;br&gt;
In the world I work in (use all your cliché imagination on nerds, hackers, computer scientists … but then remove those pictures of people wearing sun glasses indoors and desks full of pizza and caffeine-rich soft-drinks) coding from a Windows environment is often considered something between a no-go and a handicap. Breathing quickly, my fingers start to tremble as I write this, risking my career as a data scientist and machine learning practitioner. Or isn’t it all that bad?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1143&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_omI5G0XyVglCsQpBFmgf9A-744fa126.DLyAPxQw_Z1a64X8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;how-did-i-end-up-using-windows&quot;&gt;How did I end up using Windows?&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(I see your shaking heads… why the hell did he end up there?)&lt;/em&gt;&lt;br&gt;
Let’s just say I have grown into it. All the way from &lt;a href=&quot;https://en.wikipedia.org/wiki/MS-DOS&quot;&gt;MS DOS&lt;/a&gt; through many painfully bad Windows versions and then I got so used to it that &lt;strong&gt;my skills to deal with it always felt better than my skills in handling the alternatives&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In addition, I am not a software developer or computer scientist by training. For a long time I was a physicist, a scientist, an academic. And in the scientific fields where I was working, using Windows was — believe it or not —the norm.&lt;/p&gt;
&lt;p&gt;Sure, I had already installed VirtualBox on my computer to run Ubuntu. I had even done some stuff with Ubuntu, including training some machine learning models (for implementations for which the packages didn’t support Windows…). I knew the 10 most common shell commands and everything else I would simply look up when needed. No wonder working with Linux still feels like writing a long letter with my left hand (I am right handed): I am terribly slow and in the end it looks horrible.&lt;/p&gt;
&lt;h3 id=&quot;but--why&quot;&gt;But … why?&lt;/h3&gt;
&lt;p&gt;Ah, I see. That all sounds like lame excuses to you.&lt;br&gt;
Well, it is not that I didn’t see all those golden merits of using Linux over Windows. Of course that’s the better system for many tasks, say setting up a server or handling access rights. And yes, it is much less wasteful in using hardware resources, it is considered less vulnerable, … and so on …, plus it is freely available without commercial interests. Still, I never wanted to pay the price of not having access to some of the high-end software that you would get on mac-OS or Windows (such as some MS office stuff or Adobe products). By the way: I am not trying to convince anybody that Windows is the best option. I am already happy if we can agree that it is &lt;em&gt;&lt;strong&gt;an&lt;/strong&gt;&lt;/em&gt; option.&lt;/p&gt;
&lt;p&gt;Time for another uncomfortable revelation: sometimes, being lazy simply pays off. For instance if you need to sort out a huge pile of stuff with some emotional value to you. Just put it in a box and hide it, take it out 10 years later and easily decide to dump nearly all of it. That’s a bit what I did with Linux. I survived with minimal use of VirtualBx and alike. Until recently, &lt;em&gt;finally!&lt;/em&gt;, Linux became part of Windows. And that works pretty well for me. &lt;a href=&quot;https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/&quot;&gt;See how simple it now is to run Linux from Windows 10.&lt;/a&gt; And enjoy how easily you now can have the best of both worlds (not for nothing are more and more people arguing &lt;a href=&quot;https://towardsdatascience.com/dual-boot-is-dead-windows-and-linux-are-now-one-27555902a128&quot;&gt;that the good old “dual boot” is dead&lt;/a&gt; for exactly this reason).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1882&quot; height=&quot;1122&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ct2nr1TdVL8Qnmn5S2StDA-d5cb5a59.CpL0kF93_1djj7g.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using Windows and Ubuntu side by side… in front of wonderful ugly-ish Windows blue… what a peaceful view, isn’t it?&lt;/p&gt;
&lt;p&gt;Enough all-united-hippie-talk. Let me share a few impressions of the actual life of an aspiring data scientist/research software engineer that happens to use Windows:&lt;/p&gt;
&lt;h3 id=&quot;starting-a-new-job&quot;&gt;Starting a new job.&lt;/h3&gt;
&lt;p&gt;I did a lot of programming as a researcher, but clearly I had never learned the proper software development basics such as testing, versioning etc. (in many academic fields those terms are often still unheard of!). No wonder I suffered a lot from imposter syndrome in the very beginning.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I hope they won’t find out I can’t write proper code!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Naturally, that means that you might not immediately ask your colleagues for help, because that would reveal your amateur level, right?&lt;br&gt;
But even worse, imagining you ask that colleague about how to get that Python package working and it turns out you are using Windows?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can you help me setting up that environment? … By the way … I use Windows for that.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The looks you get are suggesting that you have just asked how to import a 5GB.csv file into your Excel table (&lt;em&gt;*you don’t*&lt;/em&gt;). So little surprise I did spend a fair amount of time in Forum-Land during my first months…&lt;/p&gt;
&lt;h3 id=&quot;being-that-windows-user-in-the-room&quot;&gt;Being that Windows user in the room&lt;/h3&gt;
&lt;p&gt;You sit in that hands-on workshop on some fancy programming techniques, and the instructors asks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is there anybody using Windows? (chuckles)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or, actually worse, nobody asks. Of course the instructions are only given for Linux and mac-OS. Well, at least I can hide my Windows handicap for a little longer then… but &lt;strong&gt;NO&lt;/strong&gt;!, when the instructor walks around to inspect the progress of the participants she/he will of course shout out:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Wow … you are really using Windows for that!?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Great. Now officially being tagged as &lt;strong&gt;the Windows user&lt;/strong&gt; in the room. Better keep quiet and not ask any silly questions then…&lt;/p&gt;
&lt;h3 id=&quot;get-used-to-rolled-eyes-then-secretly-roll-your-eyes-too&quot;&gt;Get used to rolled eyes —then secretly roll your eyes, too.&lt;/h3&gt;
&lt;p&gt;As I grew more confident of what I was doing, the imposter syndrome started to disappear. It still occasionally comes back to say hello (for instance if people speak shell over coffee), but that’s OK.&lt;/p&gt;
&lt;p&gt;In the end it’s luckily the results that matters most. I learned that you can write as good or bad code on Windows as on Linux. You can build great software on Windows that is then used by Linux people, and the other way around. Sure, for some things you better go the Linux way. But it turns out that in my projects this is less than 1% of my working time, which makes it OK to be a bit clumsy using it. And secretly (&lt;em&gt;don’t point at them, that’s mean!&lt;/em&gt;), I can also enjoy those moments when another colloquium presentation doesn’t run properly because Ubuntu did not work well with the projector, or the microphone, or both.&lt;/p&gt;
&lt;h3 id=&quot;do-better-than-pointing-at-each-other&quot;&gt;Do better than pointing at each other&lt;/h3&gt;
&lt;p&gt;Windows is more convenient for running some very common software (e.g. MS office), Linux is more stable… so go some cliches. But instead of fighting about what’s better (or hiding what feels inferior) it makes more sense to me to accept what’s there and simply go along with it. If somebody lives in a very geeky bubble it works fine to safely assume everyone runs their code on a certain operating systems and knows the in and outs of object oriented programming and containerization. But many of the more exciting projects involve people outside this bubble: researchers, users, future contributors, students. And they might as well — lo and behold — be using Windows (and by the way: containers are still primarily &lt;strong&gt;big steel boxes&lt;/strong&gt; to most people).&lt;/p&gt;
&lt;p&gt;So, even though in some IT-bubbles it can occasionally feel as if we are talking about a small unfortunate minority … in reality that’s really not true. Check out &lt;a href=&quot;https://www.freecodecamp.org/news/stack-overflow-developer-survey-2020-programming-language-framework-salary-data/&quot;&gt;the 2020 Stack Overflow Developer Survey&lt;/a&gt; to see that &lt;strong&gt;most developers actually use Windows&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;what-can-you-do-to-get-more-windows-users-to-adopt-your-package&quot;&gt;What can you do to get more Windows users to adopt your package?&lt;/h3&gt;
&lt;p&gt;Think of Windows what you want. I don’t work for Microsoft, and honestly, I don’t really care. But I assume that many coders out there working on great new software, methods, tools, tutorials, etc. actually want that people become happy users (paid by eternal gratitude). And that is a good enough reason to think about those Windows users as well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consider setting up your next continuous integration for your software package, so that it runs on all systems and will be used by more people.&lt;br&gt;
For instance with &lt;a href=&quot;https://docs.github.com/en/free-pro-team@latest/actions/guides/about-continuous-integration&quot;&gt;continuous integration using GitHub&lt;/a&gt; actions it can be as simple as adding a &lt;code&gt;‘windows-latest’&lt;/code&gt; to your matrix:&lt;br&gt;
&lt;code&gt;os: [‘ubuntu-latest’, ‘macos-latest’, ‘windows-latest’]   &lt;/code&gt; (small warning: adding different operating systems to such a continuous integration workflow is comparably easy, the later debugging sometimes is not. One option can be to work with &lt;a href=&quot;https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/&quot;&gt;Windows virtual machine&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;What about providing installation instructions for Windows users as well? Or did you just write a new tutorial? Great! But will it work for your fellow Windows users? You would be surprised how many packages and tutorials come with instructions that clearly won’t work for a Windows user.&lt;br&gt;
Don’t know how to do that? No Problem! Just ask a Windows user to help you. Believe me, they will be very glad to assist.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;final-symmetry&quot;&gt;Final symmetry&lt;/h3&gt;
&lt;p&gt;Most of my arguments will hold when we just swap the named OS. So, obviously if you are (like me) primarily a Windows user: Think of all those Linux and mac-OS people out there. Either way, it will require learning a bit about the differences. But it will help to avoid a lot of frustration on all ends due to failing notebooks or hard to install packages.&lt;/p&gt;
&lt;h3 id=&quot;get-in-touch&quot;&gt;Get in touch&lt;/h3&gt;
&lt;p&gt;If you have comments or questions please get in touch! You can also find me on twitter: &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;&lt;strong&gt;me_datapoint&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_omI5G0XyVglCsQpBFmgf9A-744fa126.DLyAPxQw.png" medium="image"/><author>Florian Huber</author></item><item><title>Coalition polls for the people with Coalitiewijzer</title><link>https://blog2.esciencecenter.nl/posts/2020-11-10---coalition-polls-for-the-people-with-coalitiewijzer</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-11-10---coalition-polls-for-the-people-with-coalitiewijzer</guid><description>&lt;h2 id=&quot;build-interactive-web-apps-with-polling-data-voilà--heroku&quot;&gt;Build interactive web apps with polling data, Voilà &amp;#x26; Heroku&lt;/h2&gt;
&lt;p&gt;My first attempt at actual visualization was to make another grid, but this time consisting of 150 HTML widgets, one for each seat. Then we can adjust &lt;code&gt;on_toggle&lt;/code&gt; to modify the &lt;code&gt;value&lt;/code&gt; attribute of each HTML widget, which is the character it displays. This gives us a poor man’s ASCII based seats visualization (see the &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/explore_things.ipynb&quot;&gt;explore_things notebook on GitHub&lt;/a&gt; for the code). I was already pretty happy at this point…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coalition polls for the people with Coalitiewijzer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;221&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-beb03350.DhGoA2Ue_1gIqFT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;fancy-vuetify-widgets&quot;&gt;Fancy Vuetify widgets&lt;/h3&gt;
&lt;p&gt;However, to make sure I wasn’t reinventing the wheel in the form of a square block of granite, I asked [Maarten Breddels], who is strongly involved in ipywidgets development, whether he knew of any existing options in the landscape of available widgets.&lt;/p&gt;
&lt;p&gt;He helped me set up a really fancy seats widget using &lt;a href=&quot;https://ipyvuetify.readthedocs.io/&quot;&gt;ipyvuetify&lt;/a&gt;, an alternative widget library built by [Mario Buikhuizen] on top of ipywidgets using the &lt;a href=&quot;https://vuetifyjs.com/en/&quot;&gt;Vuetify&lt;/a&gt; Javascript UI library, a Vue library.&lt;/p&gt;
&lt;p&gt;I won’t go into Vue here, because I don’t know much about it myself, except that it is a web framework like React. Apparently, though, it is not that hard to write Vue template based widgets. Vue templates have their own programming syntax with for-loops, conditionals and other useful stuff. What Maarten then came up with was something like this:&lt;/p&gt;
&lt;p&gt;from ipyvuetify import VuetifyTemplate
import traitletsclass PartyWidget(VuetifyTemplate):
rows** = traitlets.Int(10).tag(sync=True)**    cols** = traitlets.Int(15).tag(sync=True)**    low** = traitlets.Int(0).tag(sync=True)**    exp** = traitlets.Int(0).tag(sync=True)**    high** = traitlets.Int(0).tag(sync=True)**    template = traitlets.Unicode(&apos;&apos;&apos;
&amp;#x3C;template&gt;
&amp;#x3C;div&gt;
&amp;#x3C;table&gt;&amp;#x3C;tr v-for=“i in rows”&lt;strong&gt;&gt;&lt;/strong&gt;&amp;#x3C;td v-for=“j in cols”&lt;strong&gt;&gt;&lt;/strong&gt;    &amp;#x3C;div&gt;&amp;#x3C;v-icon v-if=“(j + i * cols) &amp;#x3C; low”&lt;strong&gt;&gt;mdi-seat*&amp;#x3C;/v-icon&gt;&lt;/strong&gt;&amp;#x3C;v-icon v-else-if=“(j + i * cols) &amp;#x3C; exp”
style=“color: orange”&gt;&lt;strong&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;&lt;/strong&gt;&amp;#x3C;v-icon v-else-if=“(j + i * cols) == exp” style=“color: green”&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;&amp;#x3C;v-icon v-else-if=“(j + i * cols) &amp;#x3C; high” style=“color: red”&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;&amp;#x3C;v-icon v-else** style=“color: pink”&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;**    &amp;#x3C;/div&gt;
&amp;#x3C;/td&gt;
&amp;#x3C;/tr&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;
&apos;&apos;&apos;).tag(sync=True)&lt;/p&gt;
&lt;p&gt;pw = PartyWidget()**Let’s break that down, looking at the bold-face parts especially. The first, Pythonic part of the class defines five &lt;code&gt;traitlets&lt;/code&gt; properties which we’re going to use to interactively change things. We use 10 rows and 15 columns here, giving a total of 150 seats. We can use the three other numbers &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;exp&lt;/code&gt; and &lt;code&gt;high&lt;/code&gt; for showing the expected number of seats estimates and the lower and higher uncertainty region boundaries.&lt;/p&gt;
&lt;p&gt;Then comes the Vue magic in some kind of generative dialect of HTML. We’re going to generate a table with rows and columns using the &lt;code&gt;v-for&lt;/code&gt; attribute which automatically generates a bunch of them.&lt;/p&gt;
&lt;p&gt;Then, inside the table cells, we use a bunch of fancy seat icons, &lt;code&gt;*mdi-seat*&lt;/code&gt;, with if/else conditionals with the &lt;code&gt;v-if&lt;/code&gt; and &lt;code&gt;v-else-if&lt;/code&gt; attributes. The point here is that we want to create different looking seats to indicate the expected number of seats and the lower and upper boundaries. We can simply use CSS style attributes for this.&lt;/p&gt;
&lt;p&gt;Finally, we create an instance of the class. With that in hand, we can now put our &lt;code&gt;on_toggle&lt;/code&gt; function to better use by modifying the PartyWidget &lt;code&gt;pw&lt;/code&gt;’s values on each trigger:&lt;/p&gt;
&lt;p&gt;def on_toggle(&lt;strong&gt;toggles):&lt;/strong&gt;    pw.low  = int(numbers[list(toggles.values())].ZetelsLaag.sum())
pw.exp  = int(numbers[list(toggles.values())].Zetels.sum())
pw.high = int(numbers[list(toggles.values())].ZetelsHoog.sum())And that’s it! Now when we &lt;code&gt;display(pw)&lt;/code&gt; our fancy new widget and the button grid with &lt;code&gt;interact_out&lt;/code&gt; as before, we get something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coalition polls for the people with Coalitiewijzer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;258&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-f8399c3a.GVXbs8L4_19Ggy0.webp&quot; srcset=&quot;&quot;&gt;
Fancy McSchmancyton!&lt;/p&gt;
&lt;p&gt;And what is even more amazing (as you can experience &lt;a href=&quot;https://coalitiewijzer.herokuapp.com/&quot;&gt;in the actual live app&lt;/a&gt;): the changing of CSS properties is animated! The colors smoothly change from one to the next when you click a button. The same goes for other properties like opacity and even rotation. All this comes for free with ipyvuetify (I guess with Vuetify itself as well).&lt;/p&gt;
&lt;h2 id=&quot;voilà&quot;&gt;Voilà&lt;/h2&gt;
&lt;p&gt;So, now we have a fancy interactive addition visualizer. However, it is in a notebook, which I do not want to share with my non-data scientist friends.&lt;/p&gt;
&lt;p&gt;Enter Voilà.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/voila-dashboards/voila/&quot;&gt;Voilà&lt;/a&gt; is essentially a Jupyter Notebook server, with one big difference: it &lt;em&gt;only displays the output&lt;/em&gt;** of running all the cells. Converting from a notebook to an actual app is just a matter of one command:&lt;/p&gt;
&lt;p&gt;voila your_notebook.ipynbJust like with Jupyter notebook, this starts up a server and opens a webpage in your browser showing the output of cells, including the widgets you created (if you put &lt;code&gt;display&lt;/code&gt; commands in).&lt;/p&gt;
&lt;p&gt;An active Python kernel is still running secretly in the background, though. This means you can still use the interactive functionality you setup between the widgets. You just cannot touch the code anymore. And this is exactly what we want when deploying our widgets as a user-facing interactive app.&lt;/p&gt;
&lt;p&gt;Since this Python kernel does all the magic of updating and connecting the widgets behind the scenes, unfortunately we cannot do without. I’m hoping one day there will be a static page output option, but I guess that basically requires a Python to Javascript or webassembly transpiler… &lt;a href=&quot;https://blog2.esciencecenter.nl/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;Could be lots of fun&lt;/a&gt;, but we’re not there yet, I’m afraid.&lt;/p&gt;
&lt;h2 id=&quot;deploying-on-heroku&quot;&gt;Deploying on Heroku&lt;/h2&gt;
&lt;p&gt;So, if we want to put this app on the web, we need a place to host the Voilà server. If you happen to run your own server, that’s great (&lt;a href=&quot;https://voila.readthedocs.io/en/stable/deploy.html#running-voila-on-a-private-server&quot;&gt;here’s the guide on how to setup Voilà to run from there&lt;/a&gt;). If you don’t, read on (or, again, read the Voilà guide itself, which is what I did).&lt;/p&gt;
&lt;p&gt;Deploying on Heroku is a really easy way to get online apps going quickly and free of charge (with limits, of course), which makes it ideal for testing. There’s even an official &lt;a href=&quot;https://voila.readthedocs.io/en/stable/deploy.html#deployment-on-heroku&quot;&gt;guide on how to deploy a Voilà server on Heroku&lt;/a&gt;. There’s just a few catches to be aware of.&lt;/p&gt;
&lt;p&gt;First, it’s good to notice this &lt;a href=&quot;https://devcenter.heroku.com/articles/python-pip#scientific-python-users&quot;&gt;really weird piece of Heroku documentation&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coalition polls for the people with Coalitiewijzer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;120&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-6b0211fc.BSVXvRNi_Uquy3.webp&quot; srcset=&quot;&quot;&gt;
“obscure” :DOkay, fine, I can pickle the necessary Peilingwijzer data and only use Python standard library functionality, instead of Pandas, numpy, matplotlib and some other weird and arcane packages that I’m sure nobody except me uses. I put this &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/update_numbers.py&quot;&gt;conversion process in this script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Second, I ran into &lt;a href=&quot;https://stackoverflow.com/questions/62618948/heroku-voila-app-error-process-exited-with-status-1&quot;&gt;a weird error&lt;/a&gt;, which was already documented earlier by someone on Stack Overflow. The Heroku app, despite the straightforward setup procedure, would not immediately run. Luckily the &lt;a href=&quot;https://github.com/voila-dashboards/voila-heroku&quot;&gt;solution was found in another repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So with those things in mind, after rewriting things to make use of as little scientific Python packages as possible putting the app on Heroku was a matter of following the steps in the &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/update_numbers.py&quot;&gt;Voilà Heroku deployment guide&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://devcenter.heroku.com/articles/getting-started-with-python#set-up&quot;&gt;Login using the Heroku CLI&lt;/a&gt; on your machine&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;runtime.txt&lt;/code&gt; file to your project/repo directory containing only a line with the Python runtime, which I set to &lt;code&gt;python-3.9.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;Procfile&lt;/code&gt; file to the directory containing the following line: &lt;code&gt;web: voila --port=$PORT --no-browser --enable_nbextensions=True your_notebook.ipynb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Commit these files, a requirements.txt file with Python dependencies and the notebook to a git repo, if you haven’t done so yet.&lt;/li&gt;
&lt;li&gt;Create a Heroku app and push your code to it:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;heroku create [appname]
git push heroku master&lt;a href=&quot;https://coalitiewijzer.herokuapp.com/&quot;&gt;And then, just like that, you are live&lt;/a&gt;! You can open the app in your browser using &lt;code&gt;heroku open&lt;/code&gt;, or just click the link. If you omit the app name in the &lt;code&gt;heroku create&lt;/code&gt; command, Heroku will randomly generate a name for you. The name can be important, since it determines your URL, which will be [appname].herokuapp.com. You can change it later on, though.&lt;/p&gt;
&lt;p&gt;Note that when you want to use a different clone of your repo to update your existing app (e.g. when coding on different machines), you have to reconnect Heroku to your app. If you would just run &lt;code&gt;heroku create&lt;/code&gt; again, it would create a new app. To connect the repo to the existing app, run&lt;/p&gt;
&lt;p&gt;heroku git:remote -a [appname]The &lt;code&gt;[appname]&lt;/code&gt; is the part of the app’s URL in front of herokuapp.com. You can also find it by running &lt;code&gt;heroku apps&lt;/code&gt; on your command line, which gives you a list of all your apps.&lt;/p&gt;
&lt;p&gt;So, if you hadn’t done so already, check out the resulting Coalitiewijzer app at &lt;a href=&quot;https://coalitiewijzer.herokuapp.com/&quot;&gt;https://coalitiewijzer.herokuapp.com/&lt;/a&gt; and let me know what you think!&lt;/p&gt;
&lt;p&gt;For those that don’t like discussing on Medium: &lt;a href=&quot;https://www.reddit.com/r/Python/comments/jrjegk/built_a_voila_webapp_from_jupyter_with_a_fancy/&quot;&gt;Reddit thread here&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/eScienceCenter/status/1325755219142201350&quot;&gt;Twitter here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This was my first time putting ipywidgets, Voilà and Heroku to use and I was really pleasantly surprised with how smooth all of them work. If you’re used to working in Jupyter notebooks, it’s an actual breeze to break out your exploration or visualization or other fun nugget of knowledge into something non-developers can also make good use of.&lt;/p&gt;
&lt;p&gt;It just so happens that this time I needed it to scratch a politics itch, but I can see this workflow being very useful for science communication as well. I’ll definitely be using it again. Let me know what you built with it!&lt;/p&gt;</description><pubDate>Tue, 10 Nov 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;build-interactive-web-apps-with-polling-data-voilà--heroku&quot;&gt;Build interactive web apps with polling data, Voilà &amp;#x26; Heroku&lt;/h2&gt;
&lt;p&gt;My first attempt at actual visualization was to make another grid, but this time consisting of 150 HTML widgets, one for each seat. Then we can adjust &lt;code&gt;on_toggle&lt;/code&gt; to modify the &lt;code&gt;value&lt;/code&gt; attribute of each HTML widget, which is the character it displays. This gives us a poor man’s ASCII based seats visualization (see the &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/explore_things.ipynb&quot;&gt;explore_things notebook on GitHub&lt;/a&gt; for the code). I was already pretty happy at this point…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coalition polls for the people with Coalitiewijzer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;221&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-beb03350.DhGoA2Ue_1gIqFT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;fancy-vuetify-widgets&quot;&gt;Fancy Vuetify widgets&lt;/h3&gt;
&lt;p&gt;However, to make sure I wasn’t reinventing the wheel in the form of a square block of granite, I asked [Maarten Breddels], who is strongly involved in ipywidgets development, whether he knew of any existing options in the landscape of available widgets.&lt;/p&gt;
&lt;p&gt;He helped me set up a really fancy seats widget using &lt;a href=&quot;https://ipyvuetify.readthedocs.io/&quot;&gt;ipyvuetify&lt;/a&gt;, an alternative widget library built by [Mario Buikhuizen] on top of ipywidgets using the &lt;a href=&quot;https://vuetifyjs.com/en/&quot;&gt;Vuetify&lt;/a&gt; Javascript UI library, a Vue library.&lt;/p&gt;
&lt;p&gt;I won’t go into Vue here, because I don’t know much about it myself, except that it is a web framework like React. Apparently, though, it is not that hard to write Vue template based widgets. Vue templates have their own programming syntax with for-loops, conditionals and other useful stuff. What Maarten then came up with was something like this:&lt;/p&gt;
&lt;p&gt;from ipyvuetify import VuetifyTemplate
import traitletsclass PartyWidget(VuetifyTemplate):
rows** = traitlets.Int(10).tag(sync=True)**    cols** = traitlets.Int(15).tag(sync=True)**    low** = traitlets.Int(0).tag(sync=True)**    exp** = traitlets.Int(0).tag(sync=True)**    high** = traitlets.Int(0).tag(sync=True)**    template = traitlets.Unicode(&apos;&apos;&apos;
&amp;#x3C;template&gt;
&amp;#x3C;div&gt;
&amp;#x3C;table&gt;&amp;#x3C;tr v-for=“i in rows”&lt;strong&gt;&gt;&lt;/strong&gt;&amp;#x3C;td v-for=“j in cols”&lt;strong&gt;&gt;&lt;/strong&gt;    &amp;#x3C;div&gt;&amp;#x3C;v-icon v-if=“(j + i * cols) &amp;#x3C; low”&lt;strong&gt;&gt;mdi-seat*&amp;#x3C;/v-icon&gt;&lt;/strong&gt;&amp;#x3C;v-icon v-else-if=“(j + i * cols) &amp;#x3C; exp”
style=“color: orange”&gt;&lt;strong&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;&lt;/strong&gt;&amp;#x3C;v-icon v-else-if=“(j + i * cols) == exp” style=“color: green”&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;&amp;#x3C;v-icon v-else-if=“(j + i * cols) &amp;#x3C; high” style=“color: red”&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;&amp;#x3C;v-icon v-else** style=“color: pink”&gt;&lt;em&gt;mdi-seat&lt;/em&gt;&amp;#x3C;/v-icon&gt;**    &amp;#x3C;/div&gt;
&amp;#x3C;/td&gt;
&amp;#x3C;/tr&gt;
&amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;
&apos;&apos;&apos;).tag(sync=True)&lt;/p&gt;
&lt;p&gt;pw = PartyWidget()**Let’s break that down, looking at the bold-face parts especially. The first, Pythonic part of the class defines five &lt;code&gt;traitlets&lt;/code&gt; properties which we’re going to use to interactively change things. We use 10 rows and 15 columns here, giving a total of 150 seats. We can use the three other numbers &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;exp&lt;/code&gt; and &lt;code&gt;high&lt;/code&gt; for showing the expected number of seats estimates and the lower and higher uncertainty region boundaries.&lt;/p&gt;
&lt;p&gt;Then comes the Vue magic in some kind of generative dialect of HTML. We’re going to generate a table with rows and columns using the &lt;code&gt;v-for&lt;/code&gt; attribute which automatically generates a bunch of them.&lt;/p&gt;
&lt;p&gt;Then, inside the table cells, we use a bunch of fancy seat icons, &lt;code&gt;*mdi-seat*&lt;/code&gt;, with if/else conditionals with the &lt;code&gt;v-if&lt;/code&gt; and &lt;code&gt;v-else-if&lt;/code&gt; attributes. The point here is that we want to create different looking seats to indicate the expected number of seats and the lower and upper boundaries. We can simply use CSS style attributes for this.&lt;/p&gt;
&lt;p&gt;Finally, we create an instance of the class. With that in hand, we can now put our &lt;code&gt;on_toggle&lt;/code&gt; function to better use by modifying the PartyWidget &lt;code&gt;pw&lt;/code&gt;’s values on each trigger:&lt;/p&gt;
&lt;p&gt;def on_toggle(&lt;strong&gt;toggles):&lt;/strong&gt;    pw.low  = int(numbers[list(toggles.values())].ZetelsLaag.sum())
pw.exp  = int(numbers[list(toggles.values())].Zetels.sum())
pw.high = int(numbers[list(toggles.values())].ZetelsHoog.sum())And that’s it! Now when we &lt;code&gt;display(pw)&lt;/code&gt; our fancy new widget and the button grid with &lt;code&gt;interact_out&lt;/code&gt; as before, we get something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coalition polls for the people with Coalitiewijzer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;258&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-f8399c3a.GVXbs8L4_19Ggy0.webp&quot; srcset=&quot;&quot;&gt;
Fancy McSchmancyton!&lt;/p&gt;
&lt;p&gt;And what is even more amazing (as you can experience &lt;a href=&quot;https://coalitiewijzer.herokuapp.com/&quot;&gt;in the actual live app&lt;/a&gt;): the changing of CSS properties is animated! The colors smoothly change from one to the next when you click a button. The same goes for other properties like opacity and even rotation. All this comes for free with ipyvuetify (I guess with Vuetify itself as well).&lt;/p&gt;
&lt;h2 id=&quot;voilà&quot;&gt;Voilà&lt;/h2&gt;
&lt;p&gt;So, now we have a fancy interactive addition visualizer. However, it is in a notebook, which I do not want to share with my non-data scientist friends.&lt;/p&gt;
&lt;p&gt;Enter Voilà.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/voila-dashboards/voila/&quot;&gt;Voilà&lt;/a&gt; is essentially a Jupyter Notebook server, with one big difference: it &lt;em&gt;only displays the output&lt;/em&gt;** of running all the cells. Converting from a notebook to an actual app is just a matter of one command:&lt;/p&gt;
&lt;p&gt;voila your_notebook.ipynbJust like with Jupyter notebook, this starts up a server and opens a webpage in your browser showing the output of cells, including the widgets you created (if you put &lt;code&gt;display&lt;/code&gt; commands in).&lt;/p&gt;
&lt;p&gt;An active Python kernel is still running secretly in the background, though. This means you can still use the interactive functionality you setup between the widgets. You just cannot touch the code anymore. And this is exactly what we want when deploying our widgets as a user-facing interactive app.&lt;/p&gt;
&lt;p&gt;Since this Python kernel does all the magic of updating and connecting the widgets behind the scenes, unfortunately we cannot do without. I’m hoping one day there will be a static page output option, but I guess that basically requires a Python to Javascript or webassembly transpiler… &lt;a href=&quot;https://blog2.esciencecenter.nl/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;Could be lots of fun&lt;/a&gt;, but we’re not there yet, I’m afraid.&lt;/p&gt;
&lt;h2 id=&quot;deploying-on-heroku&quot;&gt;Deploying on Heroku&lt;/h2&gt;
&lt;p&gt;So, if we want to put this app on the web, we need a place to host the Voilà server. If you happen to run your own server, that’s great (&lt;a href=&quot;https://voila.readthedocs.io/en/stable/deploy.html#running-voila-on-a-private-server&quot;&gt;here’s the guide on how to setup Voilà to run from there&lt;/a&gt;). If you don’t, read on (or, again, read the Voilà guide itself, which is what I did).&lt;/p&gt;
&lt;p&gt;Deploying on Heroku is a really easy way to get online apps going quickly and free of charge (with limits, of course), which makes it ideal for testing. There’s even an official &lt;a href=&quot;https://voila.readthedocs.io/en/stable/deploy.html#deployment-on-heroku&quot;&gt;guide on how to deploy a Voilà server on Heroku&lt;/a&gt;. There’s just a few catches to be aware of.&lt;/p&gt;
&lt;p&gt;First, it’s good to notice this &lt;a href=&quot;https://devcenter.heroku.com/articles/python-pip#scientific-python-users&quot;&gt;really weird piece of Heroku documentation&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Coalition polls for the people with Coalitiewijzer&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;120&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-6b0211fc.BSVXvRNi_Uquy3.webp&quot; srcset=&quot;&quot;&gt;
“obscure” :DOkay, fine, I can pickle the necessary Peilingwijzer data and only use Python standard library functionality, instead of Pandas, numpy, matplotlib and some other weird and arcane packages that I’m sure nobody except me uses. I put this &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/update_numbers.py&quot;&gt;conversion process in this script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Second, I ran into &lt;a href=&quot;https://stackoverflow.com/questions/62618948/heroku-voila-app-error-process-exited-with-status-1&quot;&gt;a weird error&lt;/a&gt;, which was already documented earlier by someone on Stack Overflow. The Heroku app, despite the straightforward setup procedure, would not immediately run. Luckily the &lt;a href=&quot;https://github.com/voila-dashboards/voila-heroku&quot;&gt;solution was found in another repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So with those things in mind, after rewriting things to make use of as little scientific Python packages as possible putting the app on Heroku was a matter of following the steps in the &lt;a href=&quot;https://github.com/egpbos/coalitiewijzer/blob/main/update_numbers.py&quot;&gt;Voilà Heroku deployment guide&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://devcenter.heroku.com/articles/getting-started-with-python#set-up&quot;&gt;Login using the Heroku CLI&lt;/a&gt; on your machine&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;runtime.txt&lt;/code&gt; file to your project/repo directory containing only a line with the Python runtime, which I set to &lt;code&gt;python-3.9.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;Procfile&lt;/code&gt; file to the directory containing the following line: &lt;code&gt;web: voila --port=$PORT --no-browser --enable_nbextensions=True your_notebook.ipynb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Commit these files, a requirements.txt file with Python dependencies and the notebook to a git repo, if you haven’t done so yet.&lt;/li&gt;
&lt;li&gt;Create a Heroku app and push your code to it:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;heroku create [appname]
git push heroku master&lt;a href=&quot;https://coalitiewijzer.herokuapp.com/&quot;&gt;And then, just like that, you are live&lt;/a&gt;! You can open the app in your browser using &lt;code&gt;heroku open&lt;/code&gt;, or just click the link. If you omit the app name in the &lt;code&gt;heroku create&lt;/code&gt; command, Heroku will randomly generate a name for you. The name can be important, since it determines your URL, which will be [appname].herokuapp.com. You can change it later on, though.&lt;/p&gt;
&lt;p&gt;Note that when you want to use a different clone of your repo to update your existing app (e.g. when coding on different machines), you have to reconnect Heroku to your app. If you would just run &lt;code&gt;heroku create&lt;/code&gt; again, it would create a new app. To connect the repo to the existing app, run&lt;/p&gt;
&lt;p&gt;heroku git:remote -a [appname]The &lt;code&gt;[appname]&lt;/code&gt; is the part of the app’s URL in front of herokuapp.com. You can also find it by running &lt;code&gt;heroku apps&lt;/code&gt; on your command line, which gives you a list of all your apps.&lt;/p&gt;
&lt;p&gt;So, if you hadn’t done so already, check out the resulting Coalitiewijzer app at &lt;a href=&quot;https://coalitiewijzer.herokuapp.com/&quot;&gt;https://coalitiewijzer.herokuapp.com/&lt;/a&gt; and let me know what you think!&lt;/p&gt;
&lt;p&gt;For those that don’t like discussing on Medium: &lt;a href=&quot;https://www.reddit.com/r/Python/comments/jrjegk/built_a_voila_webapp_from_jupyter_with_a_fancy/&quot;&gt;Reddit thread here&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/eScienceCenter/status/1325755219142201350&quot;&gt;Twitter here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This was my first time putting ipywidgets, Voilà and Heroku to use and I was really pleasantly surprised with how smooth all of them work. If you’re used to working in Jupyter notebooks, it’s an actual breeze to break out your exploration or visualization or other fun nugget of knowledge into something non-developers can also make good use of.&lt;/p&gt;
&lt;p&gt;It just so happens that this time I needed it to scratch a politics itch, but I can see this workflow being very useful for science communication as well. I’ll definitely be using it again. Let me know what you built with it!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/coalition-polls-for-the-people-with-coal-beb03350.DhGoA2Ue.png" medium="image"/><author>Patrick Bos</author></item><item><title>C++ web app with WebAssembly, Vega, Web Worker and React</title><link>https://blog2.esciencecenter.nl/posts/2020-10-27---c-web-app-with-webassembly-vega-web-worker-and-react</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-10-27---c-web-app-with-webassembly-vega-web-worker-and-react</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;To generate the Vega-Lite specification we can write a function like so&lt;/p&gt;
&lt;p&gt;To wrap the Vega-Lite visualization in React component we will use &lt;code&gt;useRef&lt;/code&gt; to get a DOM element as container and use &lt;code&gt;useEffect&lt;/code&gt; to call vegaEmbed when the iterations or container changes. The React component to render the visualization is&lt;/p&gt;
&lt;h2 id=&quot;pack-it-up&quot;&gt;Pack it up&lt;/h2&gt;
&lt;p&gt;The React components and React render call can be packed up all together in a JavaScript file called &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/kitchen-sink/app.js&quot;&gt;app.js&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The web applications needs a HTML page to fetch all the React and Vega dependencies, define a HTML tag for rendering the React app to and finally include the application JavaScript file.&lt;/p&gt;
&lt;p&gt;File: app.html*&lt;/p&gt;
&lt;p&gt;We’ll need a web server to display the HTML page in a web browser. For this, we’ll use the http.server module from Python 3 to host all files on port 8000, like so:&lt;/p&gt;
&lt;p&gt;python3 -m http.server 8000Visiting the page at &lt;a href=&quot;http://localhost:8000/app.html&quot;&gt;http://localhost:8000/app.html&lt;/a&gt; should give us a plot like&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/kitchen-sink/app.html)(Click&quot;&gt;https://nlesc-jcer.github.io/run-cpp-on-web/kitchen-sink/app.html)(Click&lt;/a&gt; on image to get interactive version)You can try out different initial guesses to get different amount of iterations. For example having initial guess located in a local minimum like &lt;code&gt;2&lt;/code&gt; will make the algorithm use many iterations to jump over the minimum.&lt;/p&gt;
&lt;h2 id=&quot;recap&quot;&gt;Recap&lt;/h2&gt;
&lt;p&gt;In this series of blog posts we introduced a lot of different technologies to able to take an algorithm written in C++ and make a interactive web application that will run fully in a web browser.&lt;/p&gt;
&lt;p&gt;All the source code shown is available at &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web&quot;&gt;https://github.com/NLESC-JCER/run-cpp-on-web&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hope you enjoyed this series of blogs and if you have suggestions or questions please post a comment below.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogere written as part of the “Passing XSAMS” project. To learn more about the project, check out its &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Tue, 27 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;To generate the Vega-Lite specification we can write a function like so&lt;/p&gt;
&lt;p&gt;To wrap the Vega-Lite visualization in React component we will use &lt;code&gt;useRef&lt;/code&gt; to get a DOM element as container and use &lt;code&gt;useEffect&lt;/code&gt; to call vegaEmbed when the iterations or container changes. The React component to render the visualization is&lt;/p&gt;
&lt;h2 id=&quot;pack-it-up&quot;&gt;Pack it up&lt;/h2&gt;
&lt;p&gt;The React components and React render call can be packed up all together in a JavaScript file called &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/kitchen-sink/app.js&quot;&gt;app.js&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The web applications needs a HTML page to fetch all the React and Vega dependencies, define a HTML tag for rendering the React app to and finally include the application JavaScript file.&lt;/p&gt;
&lt;p&gt;File: app.html*&lt;/p&gt;
&lt;p&gt;We’ll need a web server to display the HTML page in a web browser. For this, we’ll use the http.server module from Python 3 to host all files on port 8000, like so:&lt;/p&gt;
&lt;p&gt;python3 -m http.server 8000Visiting the page at &lt;a href=&quot;http://localhost:8000/app.html&quot;&gt;http://localhost:8000/app.html&lt;/a&gt; should give us a plot like&lt;/p&gt;
&lt;p&gt;](&lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/kitchen-sink/app.html)(Click&quot;&gt;https://nlesc-jcer.github.io/run-cpp-on-web/kitchen-sink/app.html)(Click&lt;/a&gt; on image to get interactive version)You can try out different initial guesses to get different amount of iterations. For example having initial guess located in a local minimum like &lt;code&gt;2&lt;/code&gt; will make the algorithm use many iterations to jump over the minimum.&lt;/p&gt;
&lt;h2 id=&quot;recap&quot;&gt;Recap&lt;/h2&gt;
&lt;p&gt;In this series of blog posts we introduced a lot of different technologies to able to take an algorithm written in C++ and make a interactive web application that will run fully in a web browser.&lt;/p&gt;
&lt;p&gt;All the source code shown is available at &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web&quot;&gt;https://github.com/NLESC-JCER/run-cpp-on-web&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hope you enjoyed this series of blogs and if you have suggestions or questions please post a comment below.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogere written as part of the “Passing XSAMS” project. To learn more about the project, check out its &lt;em&gt;&lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><author>eScience Editorial Team</author></item><item><title>How is the end of daylight saving time going to affect me?</title><link>https://blog2.esciencecenter.nl/posts/2020-10-22---how-is-the-end-of-daylight-saving-time-going-to-affect-me</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-10-22---how-is-the-end-of-daylight-saving-time-going-to-affect-me</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VGVs2sUcNP-lFLjO-c4642dd2.CzbvTntQ_6Pfi1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by insung yoon on Unsplash&lt;/p&gt;
&lt;p&gt;It happens every year. Twice. And it can be pretty annoying. I am talking about the clock shift to re-adapt our schedules to wintertime or summertime. But did you know that this October 25 may be the last time this happens? Well… at least if you are reading these lines from Europe.&lt;/p&gt;
&lt;h2 id=&quot;farewell-to-the-two-clocks&quot;&gt;Farewell to the (two) clocks&lt;/h2&gt;
&lt;p&gt;The European Parliament &lt;a href=&quot;https://oeil.secure.europarl.europa.eu/oeil/popups/ficheprocedure.do?lang=en&amp;#x26;reference=2018%2F0332%28COD%29&quot;&gt;decided to stop&lt;/a&gt; the practice of &lt;em&gt;“spring forward, fall back”&lt;/em&gt;. This decision has been backed by a &lt;a href=&quot;https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX%3A52018SC0406&amp;#x26;from=EN&quot;&gt;public consultation&lt;/a&gt; to 4.6 million Europeans, 84% of them were in favor of stopping the biyearly clock readjustment.&lt;/p&gt;
&lt;p&gt;The reasons to abandon the traditional clock readjustment are manifold. Most of us agree with the most obvious of all: it causes a couple of days of annoyance to get used to the new timetable. There is, additionally, some controversy about &lt;a href=&quot;https://doi.org/10.5547%2F01956574.39.2.thav&quot;&gt;how much energy is saved&lt;/a&gt;, plus some evidence about an &lt;a href=&quot;https://doi.org/10.1016/S1389-9457(00)00032-0&quot;&gt;increase in car crashes&lt;/a&gt; in the days after a clock change.&lt;/p&gt;
&lt;p&gt;The members of the European Union have been asked to choose between winter and summertime clocks, and stick to their choice during the whole year. The deadline for this decision is April 2021… and sticking permanently to one of these clocks is not an easy choice.&lt;/p&gt;
&lt;p&gt;From a sociopolitical point of view, one of the obvious concerns is the possibility of causing a de-synchronization between countries that currently share the same clock. It would not be very convenient, for instance, to use different timezones in The Netherlands and Belgium. Efficient coordination between the EU members will certainly require communication and diplomacy.&lt;/p&gt;
&lt;p&gt;But there is an even deeper problem. Changing the clocks reduces the undesirable effects of an astronomical phenomenon: that of the variability of sunlight hours during the year. To make it even more difficult, this variability depends not only on the day of the year but also on the location on Earth.&lt;/p&gt;
&lt;p&gt;Luckily, the study of the relationship between daylight duration, position, and date is one of the oldest objects of study. There are some early references in the Babylonian time, the topic was already covered in Ptolemy’s &lt;em&gt;Almagest&lt;/em&gt;, and it is part of the everyday life of sailors since, at least, the publication of the first nautical almanacs in the 1700s. Nowadays, all the knowledge we need is just a few clicks away.&lt;/p&gt;
&lt;h2 id=&quot;daylight-charts-and-how-to-read-them&quot;&gt;Daylight charts and how to read them&lt;/h2&gt;
&lt;p&gt;The easiest way to visualize this kind of information is by using a daylight chart. They look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1075&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3FqjKUwigVDSvM02muy99A-75be3bb6.D2_OnLzj_GHNuO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daylight chart corresponding to the city of Barcelona, Spain, in the year 2020. The abrupt changes correspond with the spring and autumn clock shifts. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nowadays, quick and simple access to astronomical databases makes it easier than ever to simulate daylight charts at any point in the world. In particular, I wrote &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;this code&lt;/a&gt; in R to generate such diagrams. It can be run as an interactive applet, either in &lt;a href=&quot;https://pabrod.shinyapps.io/cambio-de-hora/&quot;&gt;Shinyapps&lt;/a&gt; or &lt;a href=&quot;https://github.com/PabRod/daylight-charts/readme.md&quot;&gt;locally&lt;/a&gt;, to query for any city in the EU with a population over 100k. Additionally, I precalculated a collection of daylight charts for &lt;a href=&quot;https://github.com/PabRod/daylight-charts/tree/master/figs/nl&quot;&gt;Dutch&lt;/a&gt;, &lt;a href=&quot;https://github.com/PabRod/daylight-charts/tree/master/figs/es&quot;&gt;Spanish&lt;/a&gt;, and other &lt;a href=&quot;https://github.com/PabRod/daylight-charts/tree/master/figs/eu&quot;&gt;European&lt;/a&gt; towns with a population over 100k.&lt;/p&gt;
&lt;p&gt;By playing with these diagrams we can learn some lessons about the reasons for using two clocks, and we can also simulate possible new scenarios. For instance, we can compare the daylight charts of Barcelona with clock shift and with permanent summer clock:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;537&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LbW2hvwtIHIok0urCki4YA-407cbda5.Bb_z53MR_Z17Fn9y.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daylight charts of Barcelona with clock shift (left) and permanent summer clock (right). Note how the clock shift keeps the sunrise centered around 7:30. With permanent summer time, the sunrise in winter will happen after 9:00. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The three possible scenarios can be visualized in a more compact way using a single chart with different colors:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;900&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EY-C9YiELqJfFlfS8yGy9g-0946c5b1.B9uipH_f_q7EEh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In yellow, sunlight hours with clock shift (current situation). In blue, sunrise and sunset times using winter clock. In red, the same with summer clock. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just for fun, we can explore the effect of latitude (the position in the South-North line) by, for instance, comparing two of the southernmost and northernmost big towns in the EU:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fcHq8E9C2451Ql8LLT7WHw-4704b303.BrbW-l-d_ZXrYK6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Comparison of daylight charts in Santa Cruz de Tenerife, Canary Islands (28º N) and Stockholm, Sweden (59ºN). We notice that the further from the equator, the more irregular the sunlight is throughout the year. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Longitude, that is, the position in the direction West-East, also plays a role. This is the direction of the Earth’s rotation and, thus, we can imagine the sunrise “traveling” through it. Indeed, this the reason we have different timezones.&lt;/p&gt;
&lt;p&gt;Timezones are decided not only due to astronomical considerations but also due to commercial and political ones. Lots of them are actually wider than the distance the sun covers in one hour, and this causes interesting effects.&lt;/p&gt;
&lt;p&gt;Take a look at the map below. It shows the night advancing over Europe the day of the September equinox, together with the European timezones. Do you see something strange?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;582&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pj09DF2WUG0x0Y_fUg6DmA-44f8ef1f.C7NfSdKp_1CwW6G.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Line of sunset advancing over Europe on a day in mid-September. The different colors represent different timezones. Note that, particularly, the Central European Timezone (in dark green) is much wider than the distance the sunset covers in one hour. Source: &lt;a href=&quot;https://naukas.com/2013/10/15/espana-esta-que-se-sale-el-meridiano-y-la-hora-oficial/&quot;&gt;https://naukas.com/2013/10/15/espana-esta-que-se-sale-el-meridiano-y-la-hora-oficial/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Central European Timezone, for instance, is huge. The sun takes more than two hours to cover it. And remember, for all the people who live there, the clock shows the same time.&lt;/p&gt;
&lt;p&gt;Let’s imagine two Europeans, Mateusz and Breixo. Mateusz lives in Lublin, in the East of Poland, and Breixo lives in Tuy, in Northwestern Spain. They both leave the office where they work, simultaneously, when the clock reads 18:00, but their experience is very different. For Mateusz, 18:00 is almost night, while for Breixo it will still be clear daylight for two more hours. Something similar will happen with the sunrise: it will happen roughly two hours earlier for Mateusz than for Breixo. And all of this happens although their clocks are synchronized (actually, it happens &lt;strong&gt;because&lt;/strong&gt; their clocks are synchronized).&lt;/p&gt;
&lt;p&gt;Interestingly enough, Vânia, who lives in the Portuguese town of Valença do Minho, only one kilometer away from Breixo, is in a different timezone. So her clock will read one hour less than that of her neighbor Breixo when the night arrives, simultaneously, at both towns. Pretty confusing, right?&lt;/p&gt;
&lt;p&gt;We can see also these effects on our diagrams. In the one below we see an example with two of the most occidental/oriental cities in the CET timezone:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XmJMmrLlobteENfTgOqwog-4c0105d3.BHh7Z0Ec_10IS2b.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daylight chart for A Coruña, Spain, and Split, Croatia. Both cities lie at the same approximate latitude (43ºN), but are separated by 2000 km in the West-East direction. As a consequence, all astronomical events, including sunrise, happen in Split roughly 2 hours earlier than in A Coruña, although they lay in the same timezone (CET). Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A well-informed decision is a good decision. The socioeconomic aspects of this problem are pretty difficult to predict, but the astronomical ones, on the contrary, are almost as predictable as the movement of a clock. Whenever we can, let’s base our decisions on data.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The final version of this short essay was greatly improved by the suggestions and comments of Zeger van der Sterre, &lt;a href=&quot;https://medium.com/@lourensveen&quot;&gt;Lourens Veen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@egpbos&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@s.georgievska&quot;&gt;Sonja Georgievska&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@maartenvm&quot;&gt;Maarten van Meersbergen&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Thu, 22 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_VGVs2sUcNP-lFLjO-c4642dd2.CzbvTntQ_6Pfi1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by insung yoon on Unsplash&lt;/p&gt;
&lt;p&gt;It happens every year. Twice. And it can be pretty annoying. I am talking about the clock shift to re-adapt our schedules to wintertime or summertime. But did you know that this October 25 may be the last time this happens? Well… at least if you are reading these lines from Europe.&lt;/p&gt;
&lt;h2 id=&quot;farewell-to-the-two-clocks&quot;&gt;Farewell to the (two) clocks&lt;/h2&gt;
&lt;p&gt;The European Parliament &lt;a href=&quot;https://oeil.secure.europarl.europa.eu/oeil/popups/ficheprocedure.do?lang=en&amp;#x26;reference=2018%2F0332%28COD%29&quot;&gt;decided to stop&lt;/a&gt; the practice of &lt;em&gt;“spring forward, fall back”&lt;/em&gt;. This decision has been backed by a &lt;a href=&quot;https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX%3A52018SC0406&amp;#x26;from=EN&quot;&gt;public consultation&lt;/a&gt; to 4.6 million Europeans, 84% of them were in favor of stopping the biyearly clock readjustment.&lt;/p&gt;
&lt;p&gt;The reasons to abandon the traditional clock readjustment are manifold. Most of us agree with the most obvious of all: it causes a couple of days of annoyance to get used to the new timetable. There is, additionally, some controversy about &lt;a href=&quot;https://doi.org/10.5547%2F01956574.39.2.thav&quot;&gt;how much energy is saved&lt;/a&gt;, plus some evidence about an &lt;a href=&quot;https://doi.org/10.1016/S1389-9457(00)00032-0&quot;&gt;increase in car crashes&lt;/a&gt; in the days after a clock change.&lt;/p&gt;
&lt;p&gt;The members of the European Union have been asked to choose between winter and summertime clocks, and stick to their choice during the whole year. The deadline for this decision is April 2021… and sticking permanently to one of these clocks is not an easy choice.&lt;/p&gt;
&lt;p&gt;From a sociopolitical point of view, one of the obvious concerns is the possibility of causing a de-synchronization between countries that currently share the same clock. It would not be very convenient, for instance, to use different timezones in The Netherlands and Belgium. Efficient coordination between the EU members will certainly require communication and diplomacy.&lt;/p&gt;
&lt;p&gt;But there is an even deeper problem. Changing the clocks reduces the undesirable effects of an astronomical phenomenon: that of the variability of sunlight hours during the year. To make it even more difficult, this variability depends not only on the day of the year but also on the location on Earth.&lt;/p&gt;
&lt;p&gt;Luckily, the study of the relationship between daylight duration, position, and date is one of the oldest objects of study. There are some early references in the Babylonian time, the topic was already covered in Ptolemy’s &lt;em&gt;Almagest&lt;/em&gt;, and it is part of the everyday life of sailors since, at least, the publication of the first nautical almanacs in the 1700s. Nowadays, all the knowledge we need is just a few clicks away.&lt;/p&gt;
&lt;h2 id=&quot;daylight-charts-and-how-to-read-them&quot;&gt;Daylight charts and how to read them&lt;/h2&gt;
&lt;p&gt;The easiest way to visualize this kind of information is by using a daylight chart. They look like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1075&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3FqjKUwigVDSvM02muy99A-75be3bb6.D2_OnLzj_GHNuO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daylight chart corresponding to the city of Barcelona, Spain, in the year 2020. The abrupt changes correspond with the spring and autumn clock shifts. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nowadays, quick and simple access to astronomical databases makes it easier than ever to simulate daylight charts at any point in the world. In particular, I wrote &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;this code&lt;/a&gt; in R to generate such diagrams. It can be run as an interactive applet, either in &lt;a href=&quot;https://pabrod.shinyapps.io/cambio-de-hora/&quot;&gt;Shinyapps&lt;/a&gt; or &lt;a href=&quot;https://github.com/PabRod/daylight-charts/readme.md&quot;&gt;locally&lt;/a&gt;, to query for any city in the EU with a population over 100k. Additionally, I precalculated a collection of daylight charts for &lt;a href=&quot;https://github.com/PabRod/daylight-charts/tree/master/figs/nl&quot;&gt;Dutch&lt;/a&gt;, &lt;a href=&quot;https://github.com/PabRod/daylight-charts/tree/master/figs/es&quot;&gt;Spanish&lt;/a&gt;, and other &lt;a href=&quot;https://github.com/PabRod/daylight-charts/tree/master/figs/eu&quot;&gt;European&lt;/a&gt; towns with a population over 100k.&lt;/p&gt;
&lt;p&gt;By playing with these diagrams we can learn some lessons about the reasons for using two clocks, and we can also simulate possible new scenarios. For instance, we can compare the daylight charts of Barcelona with clock shift and with permanent summer clock:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;537&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LbW2hvwtIHIok0urCki4YA-407cbda5.Bb_z53MR_Z17Fn9y.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daylight charts of Barcelona with clock shift (left) and permanent summer clock (right). Note how the clock shift keeps the sunrise centered around 7:30. With permanent summer time, the sunrise in winter will happen after 9:00. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The three possible scenarios can be visualized in a more compact way using a single chart with different colors:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;900&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EY-C9YiELqJfFlfS8yGy9g-0946c5b1.B9uipH_f_q7EEh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In yellow, sunlight hours with clock shift (current situation). In blue, sunrise and sunset times using winter clock. In red, the same with summer clock. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just for fun, we can explore the effect of latitude (the position in the South-North line) by, for instance, comparing two of the southernmost and northernmost big towns in the EU:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fcHq8E9C2451Ql8LLT7WHw-4704b303.BrbW-l-d_ZXrYK6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Comparison of daylight charts in Santa Cruz de Tenerife, Canary Islands (28º N) and Stockholm, Sweden (59ºN). We notice that the further from the equator, the more irregular the sunlight is throughout the year. Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Longitude, that is, the position in the direction West-East, also plays a role. This is the direction of the Earth’s rotation and, thus, we can imagine the sunrise “traveling” through it. Indeed, this the reason we have different timezones.&lt;/p&gt;
&lt;p&gt;Timezones are decided not only due to astronomical considerations but also due to commercial and political ones. Lots of them are actually wider than the distance the sun covers in one hour, and this causes interesting effects.&lt;/p&gt;
&lt;p&gt;Take a look at the map below. It shows the night advancing over Europe the day of the September equinox, together with the European timezones. Do you see something strange?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;582&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pj09DF2WUG0x0Y_fUg6DmA-44f8ef1f.C7NfSdKp_1CwW6G.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Line of sunset advancing over Europe on a day in mid-September. The different colors represent different timezones. Note that, particularly, the Central European Timezone (in dark green) is much wider than the distance the sunset covers in one hour. Source: &lt;a href=&quot;https://naukas.com/2013/10/15/espana-esta-que-se-sale-el-meridiano-y-la-hora-oficial/&quot;&gt;https://naukas.com/2013/10/15/espana-esta-que-se-sale-el-meridiano-y-la-hora-oficial/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Central European Timezone, for instance, is huge. The sun takes more than two hours to cover it. And remember, for all the people who live there, the clock shows the same time.&lt;/p&gt;
&lt;p&gt;Let’s imagine two Europeans, Mateusz and Breixo. Mateusz lives in Lublin, in the East of Poland, and Breixo lives in Tuy, in Northwestern Spain. They both leave the office where they work, simultaneously, when the clock reads 18:00, but their experience is very different. For Mateusz, 18:00 is almost night, while for Breixo it will still be clear daylight for two more hours. Something similar will happen with the sunrise: it will happen roughly two hours earlier for Mateusz than for Breixo. And all of this happens although their clocks are synchronized (actually, it happens &lt;strong&gt;because&lt;/strong&gt; their clocks are synchronized).&lt;/p&gt;
&lt;p&gt;Interestingly enough, Vânia, who lives in the Portuguese town of Valença do Minho, only one kilometer away from Breixo, is in a different timezone. So her clock will read one hour less than that of her neighbor Breixo when the night arrives, simultaneously, at both towns. Pretty confusing, right?&lt;/p&gt;
&lt;p&gt;We can see also these effects on our diagrams. In the one below we see an example with two of the most occidental/oriental cities in the CET timezone:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;525&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XmJMmrLlobteENfTgOqwog-4c0105d3.BHh7Z0Ec_10IS2b.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Daylight chart for A Coruña, Spain, and Split, Croatia. Both cities lie at the same approximate latitude (43ºN), but are separated by 2000 km in the West-East direction. As a consequence, all astronomical events, including sunrise, happen in Split roughly 2 hours earlier than in A Coruña, although they lay in the same timezone (CET). Source: &lt;a href=&quot;https://github.com/PabRod/daylight-charts&quot;&gt;https://github.com/PabRod/daylight-charts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A well-informed decision is a good decision. The socioeconomic aspects of this problem are pretty difficult to predict, but the astronomical ones, on the contrary, are almost as predictable as the movement of a clock. Whenever we can, let’s base our decisions on data.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The final version of this short essay was greatly improved by the suggestions and comments of Zeger van der Sterre, &lt;a href=&quot;https://medium.com/@lourensveen&quot;&gt;Lourens Veen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/stefan-verhoeven-bsc/&quot;&gt;Stefan Verhoeven&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@egpbos&quot;&gt;Patrick Bos&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@s.georgievska&quot;&gt;Sonja Georgievska&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@maartenvm&quot;&gt;Maarten van Meersbergen&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_3FqjKUwigVDSvM02muy99A-75be3bb6.D2_OnLzj.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Help! My C++ web app is not responding</title><link>https://blog2.esciencecenter.nl/posts/2020-10-09---help-my-c-web-app-is-not-responding</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-10-09---help-my-c-web-app-is-not-responding</guid><description>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In an &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;earlier blogpost&lt;/a&gt; we discussed how to run C++ code on the web using JavaScript. We created a web app that executed some C++ code and then showed the result in the browser. While the page was running the C++ code, the page was blocked and unresponsive. This was not noticeable, because the computation done in the code was very quick. An unresponsive User Interface (UI) becomes a problem when we are performing tasks that take a bit longer to run.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;How to prevent blocking when running long running tasks in C++?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this blog post, we will use web workers to solve this problem by offloading tasks to another thread.&lt;/p&gt;
&lt;h2 id=&quot;long-running-tasks-with-web-worker&quot;&gt;Long-running tasks with web worker&lt;/h2&gt;
&lt;p&gt;Let’s have a look at the code we ended up with in the &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;first blog&lt;/a&gt; of the series. When loading the page, the WebAssembly code is executed, after which the page can finish rendering. Because the WebAssembly code was very quick, this was fine. For the current blog, we assume we have a longer running task. We create such a task artificially, by adding a few seconds of &lt;code&gt;sleep&lt;/code&gt; in the &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/web-worker/newtonraphson.cpp&quot;&gt;C++ code&lt;/a&gt;. Like in the first post of the series, we compile the C++ code to create WebAssembly code. The example page with our slow task can be found &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/web-worker/example-blocking.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Notice that we also added a slider to the page. This slider simply serves to illustrate UI unresponsiveness — it has no attached function. Notice that while the WebAssembly code is still running, the slider is completely blocked. If this was an actual web app and not just a demo, the blocked UI would surely annoy users and possibly make working with the app cumbersome and impractical. We can easily solve this, and keep the UI responsive at all times, using web workers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;509&quot; height=&quot;163&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GFkQlI6sOZUxjhbEE8U5UQ-0fc27ea2.C073jd4K_1jywBO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Blocked UI while code is running.&lt;/p&gt;
&lt;h2 id=&quot;web-workers&quot;&gt;Web workers&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API&quot;&gt;web worker&lt;/a&gt; is an object that handles execution of a piece of code in another thread.&lt;/p&gt;
&lt;p&gt;The way the page communicates with the worker object is through sending messages. The page will send a message to the worker to start doing work, and the message will include all data that the worker needs. The worker then starts executing the task, using only the data that was in the message. When finished, the worker needs to communicate the results back to the web app. It will do this by sending a message, so the web app knows when to update.&lt;/p&gt;
&lt;h2 id=&quot;the-resulting-page&quot;&gt;The resulting page&lt;/h2&gt;
&lt;p&gt;The code snippet below shows the web page that uses a web worker. Notice the creation of the &lt;code&gt;Worker&lt;/code&gt; object, posting of the message, as well as the instructions for handling of any returned messages containing results.&lt;/p&gt;
&lt;p&gt;The web worker code only contains handling of the incoming message. The web worker unpacks the message, does the root finding calculation, and packs the results in a new message that it will send back.&lt;/p&gt;
&lt;p&gt;The code for the worker in &lt;code&gt;worker.js&lt;/code&gt; is:&lt;/p&gt;
&lt;p&gt;The figure below illustrates what is happening in parallel in the two threads.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;666&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__Knkh9aTq85_WNvyZjRPlQ-ad4c9f5c.CBM67MGz_Z1tSPLi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can see the code in action &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/web-worker/example-web-worker.html&quot;&gt;here&lt;/a&gt;. The calculation still takes the same time to perform, but as you will notice, the slider remains responsive.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;508&quot; height=&quot;158&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_efp-XCZJWs0yNveDPrq38w-bdc1dd9c.BcldFPYW_Z12E1tA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Responsive UI thanks to offloading the root finding procedure to the web worker.&lt;/p&gt;
&lt;h2 id=&quot;recap-and-what-next&quot;&gt;Recap and what next?&lt;/h2&gt;
&lt;p&gt;In this blog post, we learned how to keep a web app from freezing while executing computationally intensive C++ code. We learned how to create a web worker and how to use the web worker in a simple web app.&lt;/p&gt;
&lt;p&gt;Now you can take this web app a step further by reading some of the other blogs in this series, for example &lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;how to interact with your app using forms&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;how to spice up your app up with visualizations&lt;/a&gt;. A final blog shows you &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;how to combine all of the above in a single web app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Looking for the first blog and introduction to this series? &lt;a href=&quot;https://blog.esciencecenter.nl/efd78c08469-using-c-in-a-web-app-with-webassembly&quot;&gt;This blog post&lt;/a&gt; will show you how to get started running your C++ on the web using WebAssembly.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thank you to our proof reader&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-5565-7577&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Fri, 09 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In an &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;earlier blogpost&lt;/a&gt; we discussed how to run C++ code on the web using JavaScript. We created a web app that executed some C++ code and then showed the result in the browser. While the page was running the C++ code, the page was blocked and unresponsive. This was not noticeable, because the computation done in the code was very quick. An unresponsive User Interface (UI) becomes a problem when we are performing tasks that take a bit longer to run.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;How to prevent blocking when running long running tasks in C++?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this blog post, we will use web workers to solve this problem by offloading tasks to another thread.&lt;/p&gt;
&lt;h2 id=&quot;long-running-tasks-with-web-worker&quot;&gt;Long-running tasks with web worker&lt;/h2&gt;
&lt;p&gt;Let’s have a look at the code we ended up with in the &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;first blog&lt;/a&gt; of the series. When loading the page, the WebAssembly code is executed, after which the page can finish rendering. Because the WebAssembly code was very quick, this was fine. For the current blog, we assume we have a longer running task. We create such a task artificially, by adding a few seconds of &lt;code&gt;sleep&lt;/code&gt; in the &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/web-worker/newtonraphson.cpp&quot;&gt;C++ code&lt;/a&gt;. Like in the first post of the series, we compile the C++ code to create WebAssembly code. The example page with our slow task can be found &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/web-worker/example-blocking.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Notice that we also added a slider to the page. This slider simply serves to illustrate UI unresponsiveness — it has no attached function. Notice that while the WebAssembly code is still running, the slider is completely blocked. If this was an actual web app and not just a demo, the blocked UI would surely annoy users and possibly make working with the app cumbersome and impractical. We can easily solve this, and keep the UI responsive at all times, using web workers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;509&quot; height=&quot;163&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GFkQlI6sOZUxjhbEE8U5UQ-0fc27ea2.C073jd4K_1jywBO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Blocked UI while code is running.&lt;/p&gt;
&lt;h2 id=&quot;web-workers&quot;&gt;Web workers&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API&quot;&gt;web worker&lt;/a&gt; is an object that handles execution of a piece of code in another thread.&lt;/p&gt;
&lt;p&gt;The way the page communicates with the worker object is through sending messages. The page will send a message to the worker to start doing work, and the message will include all data that the worker needs. The worker then starts executing the task, using only the data that was in the message. When finished, the worker needs to communicate the results back to the web app. It will do this by sending a message, so the web app knows when to update.&lt;/p&gt;
&lt;h2 id=&quot;the-resulting-page&quot;&gt;The resulting page&lt;/h2&gt;
&lt;p&gt;The code snippet below shows the web page that uses a web worker. Notice the creation of the &lt;code&gt;Worker&lt;/code&gt; object, posting of the message, as well as the instructions for handling of any returned messages containing results.&lt;/p&gt;
&lt;p&gt;The web worker code only contains handling of the incoming message. The web worker unpacks the message, does the root finding calculation, and packs the results in a new message that it will send back.&lt;/p&gt;
&lt;p&gt;The code for the worker in &lt;code&gt;worker.js&lt;/code&gt; is:&lt;/p&gt;
&lt;p&gt;The figure below illustrates what is happening in parallel in the two threads.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;666&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__Knkh9aTq85_WNvyZjRPlQ-ad4c9f5c.CBM67MGz_Z1tSPLi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can see the code in action &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/web-worker/example-web-worker.html&quot;&gt;here&lt;/a&gt;. The calculation still takes the same time to perform, but as you will notice, the slider remains responsive.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;508&quot; height=&quot;158&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_efp-XCZJWs0yNveDPrq38w-bdc1dd9c.BcldFPYW_Z12E1tA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Responsive UI thanks to offloading the root finding procedure to the web worker.&lt;/p&gt;
&lt;h2 id=&quot;recap-and-what-next&quot;&gt;Recap and what next?&lt;/h2&gt;
&lt;p&gt;In this blog post, we learned how to keep a web app from freezing while executing computationally intensive C++ code. We learned how to create a web worker and how to use the web worker in a simple web app.&lt;/p&gt;
&lt;p&gt;Now you can take this web app a step further by reading some of the other blogs in this series, for example &lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;how to interact with your app using forms&lt;/a&gt; and &lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;how to spice up your app up with visualizations&lt;/a&gt;. A final blog shows you &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;how to combine all of the above in a single web app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Looking for the first blog and introduction to this series? &lt;a href=&quot;https://blog.esciencecenter.nl/efd78c08469-using-c-in-a-web-app-with-webassembly&quot;&gt;This blog post&lt;/a&gt; will show you how to get started running your C++ on the web using WebAssembly.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thank you to our proof reader&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-5565-7577&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_GFkQlI6sOZUxjhbEE8U5UQ-0fc27ea2.C073jd4K.gif" medium="image"/><author>eScience Editorial Team</author></item><item><title>Interact with your C++ web app using React forms</title><link>https://blog2.esciencecenter.nl/posts/2020-10-09---interact-with-your-c-web-app-using-react-forms</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-10-09---interact-with-your-c-web-app-using-react-forms</guid><description>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;previous blog post&lt;/a&gt;, we compiled the C++ algorithm into WebAssembly. In the current blog post, we will create a web application using &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;. The web application will have a web form that allows us to change the parameters of the algorithm.&lt;/p&gt;
&lt;p&gt;We feel your pain: there are too many things to learn, too many skills to get, but too little time available — which reminds me of our extraordinary friend &lt;a href=&quot;https://www.imdb.com/title/tt0374900/&quot;&gt;Napoleon Dynamite&lt;/a&gt;. This blog post will guide you through the process of making a React web application without getting lost.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;658&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_XHTFs5--uJCCcQuI-9cccbcb9.DVTzmuKc_Z1K5bYU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you haven’t met Napoleon yet, click here to see how he was struggling with his skills. Screenshot from Napoleon Dynamite movie.&lt;/p&gt;
&lt;h2 id=&quot;react-web-application&quot;&gt;React web application&lt;/h2&gt;
&lt;p&gt;The web application we developed so far needs to update the entire page to display the results. Even for small changes in the web page, this has to happen. Thanks to modern web browsers and JavaScript, Single Page Applications (SPAs) can update only required elements in the web page. We will use one of the most popular web frameworks, React, to develop the SPA. We chose React over vanilla JavaScript because building a web application is made easier by letting React deal with all the magic behind the scenes. &lt;a href=&quot;https://www.freecodecamp.org/news/do-we-still-need-javascript-frameworks-42576735949b/&quot;&gt;This blog post&lt;/a&gt; may help you to understand why we made this choice.&lt;/p&gt;
&lt;p&gt;The form in the web application will collect the user inputs and uses them to initialize the algorithm. When the form is submitted, a WebAssembly code starts the calculation and the result is rendered. With this architecture, the application only needs cheap static file hosting to host the HTML, JavaScript, and WebAssembly files. The algorithm will be running in the web browser on the end-user’s machine instead of a server.&lt;/p&gt;
&lt;h3 id=&quot;the-html-code&quot;&gt;The HTML code&lt;/h3&gt;
&lt;p&gt;To render the React application we need an HTML element as a container. We will give it the identifier &lt;strong&gt;container&lt;/strong&gt; which will use later when we implement the &lt;strong&gt;React&lt;/strong&gt; application.&lt;/p&gt;
&lt;p&gt;We will keep the HTML code very minimal. The code will contain three essential elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt; element to set the title and to load the required external dependencies (JavaScript libraries).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt; element to display the result&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;script&gt;&lt;/script&gt; elements to load the Javascript application and the &lt;code&gt;NewtonRaphson&lt;/code&gt; class.&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;
&lt;/strong&gt;&lt;/li&gt;&lt;strong&gt;
&lt;/strong&gt;&lt;/ul&gt;&lt;strong&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We use the same &lt;code&gt;newtonraphson.js&lt;/code&gt; and &lt;code&gt;newtonraphson.wasm&lt;/code&gt; files as in the &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/webassembly/README.md&quot;&gt;first post&lt;/a&gt; of this series. Make sure you download &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/react/newtonraphson.js&quot;&gt;newtonraphson.js&lt;/a&gt; and &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/react/newtonraphson.wasm&quot;&gt;newtonraphson.wasm&lt;/a&gt; files from GitHub.&lt;/p&gt;
&lt;p&gt;The complete HTML code will look like this:&lt;/p&gt;
&lt;h3 id=&quot;javascript-code-react&quot;&gt;JavaScript code (React)&lt;/h3&gt;
&lt;p&gt;Similarly, we will split the JavaScript code into sections and build up the React application from React components.&lt;/p&gt;
&lt;p&gt;Let’s start with the header part. We will define a JavaScript function that returns the header element which will be rendered by the web browser when the user visits the page.&lt;/p&gt;
&lt;p&gt;The return statement of this function looks weird, right? It is indeed not HTML. React uses a syntax extension called &lt;a href=&quot;https://reactjs.org/docs/introducing-jsx.html&quot;&gt;JSX&lt;/a&gt; to describe the UI. With the magical conversion of &lt;a href=&quot;https://babeljs.io/docs/en/next/babel-standalone.html&quot;&gt;Babel&lt;/a&gt; we can convert JSX into JavaScript code. After this conversion the generated JavaScript code will look like:&lt;/p&gt;
&lt;p&gt;In order for the header element to be rendered we need to tell &lt;strong&gt;ReactDOM&lt;/strong&gt; which element it should render and where it should be displayed. Do you still remember the &lt;strong&gt;container&lt;/strong&gt; &lt;code&gt;div&lt;/code&gt; we defined in the HTML part?&lt;/p&gt;
&lt;p&gt;The complete code should look like this:&lt;/p&gt;
&lt;p&gt;When the page is rendered, the generated HTML code will be like:&lt;/p&gt;
&lt;h2 id=&quot;adding-the-web-form&quot;&gt;Adding the web form&lt;/h2&gt;
&lt;p&gt;The web application in our example should have a form with &lt;code&gt;tolerance&lt;/code&gt; and &lt;code&gt;initial_guess&lt;/code&gt; input fields, as well as a submit button. The form in JSX can be written in the following way:&lt;/p&gt;
&lt;p&gt;The form tag has an &lt;code&gt;onSubmit&lt;/code&gt; property, which is set to a function ( &lt;code&gt;handleSubmit&lt;/code&gt;) that will handle the form submission. The input tag has a &lt;code&gt;value&lt;/code&gt; property to set the variable ( &lt;code&gt;tolerance&lt;/code&gt; and &lt;code&gt;initial_guess&lt;/code&gt;) and it also has an &lt;code&gt;onChange&lt;/code&gt; property to set the function ( &lt;code&gt;onToleranceChange&lt;/code&gt; and &lt;code&gt;onGuessChange&lt;/code&gt;) which will be triggered when the user changes the value.&lt;/p&gt;
&lt;p&gt;Let’s implement the &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;onChange&lt;/code&gt; for the &lt;code&gt;tolerance&lt;/code&gt; input. To store the value we will use the &lt;a href=&quot;https://reactjs.org/docs/hooks-state.html&quot;&gt;React useState hook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The argument of the &lt;code&gt;useState&lt;/code&gt; function is the initial value. The &lt;code&gt;tolerance&lt;/code&gt; variable contains the current value for tolerance and &lt;code&gt;setTolerance&lt;/code&gt; is a function to set the &lt;code&gt;tolerance&lt;/code&gt; to a new value. The same logic is also used for the &lt;code&gt;initial_guess&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;The input tag in the form will call the &lt;code&gt;onChange&lt;/code&gt; function with an event object. We need to extract the user input from the event and pass it to &lt;code&gt;setTolerance&lt;/code&gt; or &lt;code&gt;setGuess&lt;/code&gt;. The value should be a number, so we use &lt;code&gt;Number()&lt;/code&gt; to cast the string from the event to a number.&lt;/p&gt;
&lt;p&gt;We are now ready to implement the &lt;code&gt;handleSubmit&lt;/code&gt; function which will process the submitted form data. The function will get an event object, similar to the &lt;code&gt;onChange&lt;/code&gt; of the input tag. Normally when you submit a form, the form fields will be sent to the server, but we want to perform the calculation in the browser, so we have to disable the default action with &lt;code&gt;preventDefault()&lt;/code&gt;. We will then construct a WebAssembly module as we did in &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/webassembly/README.md&quot;&gt;a previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We need a place to store the result of the calculation ( &lt;code&gt;root&lt;/code&gt; value), we will use &lt;code&gt;useState&lt;/code&gt; function again. The initial value of the result is set to &lt;code&gt;undefined&lt;/code&gt; as the result is only known after the calculation has been completed.&lt;/p&gt;
&lt;p&gt;When the calculation is done it will store the result value ( &lt;code&gt;root&lt;/code&gt;) using &lt;code&gt;setRoot&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To render the result we can use a React Component which has &lt;code&gt;root&lt;/code&gt; as a property. When the calculation has not been done yet, it will render &lt;code&gt;Not submitted&lt;/code&gt;. We will show the &lt;code&gt;root&lt;/code&gt; property value once it is set.&lt;/p&gt;
&lt;p&gt;Finally we can render the &lt;code&gt;App&lt;/code&gt; component to the HTML container with &lt;code&gt;id&lt;/code&gt; equal to &lt;code&gt;container&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can combine the heading, form and result components and all the states and &lt;code&gt;handleSubmit&lt;/code&gt; function into the &lt;code&gt;App&lt;/code&gt; React component and its rendering and save it as &lt;code&gt;app.js&lt;/code&gt;. You can find the resulting code &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/react/app.js&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Like before, we also need to host the files in a web server with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;754&quot; height=&quot;222&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_smvfh5MifrSGsY10-8c73001a.6WsYx5Pj_Z1bngGr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The final page if everything works.&lt;/p&gt;
&lt;p&gt;Visit &lt;a href=&quot;http://localhost:8000/app.html&quot;&gt;http://localhost:8000/app.html&lt;/a&gt; to see the root answer, or go to &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/react/app.html&quot;&gt;GitHub pages&lt;/a&gt; to see a hosted version of the example app.&lt;/p&gt;
&lt;h2 id=&quot;extra-notes&quot;&gt;Extra notes&lt;/h2&gt;
&lt;p&gt;The code supplied here should not be used in production as converting JSX in the web browser is slow. It’s better to use &lt;a href=&quot;http://create-react-app.dev/&quot;&gt;Create React App&lt;/a&gt;, which gives you an infrastructure to perform the transformation offline.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By writing React components we were able to create an interactive page with a form that executes the WebAssembly module compiled from the C++ code we introduced in the &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;first blog&lt;/a&gt; of the series.&lt;/p&gt;
&lt;p&gt;We went over JSX, props, state, and components, which together constitute the core building blocks of a React web application.&lt;/p&gt;
&lt;p&gt;In other blogs of the series that might be of interest we cover&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;Using C++ in a web app with WebAssembly&lt;/a&gt;: How to turn C++ code into a web app.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;Help! My C++ web app is not responding&lt;/a&gt;: How to use web workers to perform computations without blocking the user interface.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;Spice up your C++ web app with visualizations&lt;/a&gt;: Plotting data from the C++ web app using web visualization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll wrap up the series in a &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;final blog&lt;/a&gt; that combines the topics of the whole series in a full-featured web application.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, leave a comment and give us a clap!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thank you to our proof reader&lt;/em&gt; &lt;a href=&quot;https://github.com/DAANBOER&quot;&gt;&lt;em&gt;Daan Boer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;&lt;/strong&gt;</description><pubDate>Fri, 09 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;previous blog post&lt;/a&gt;, we compiled the C++ algorithm into WebAssembly. In the current blog post, we will create a web application using &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;. The web application will have a web form that allows us to change the parameters of the algorithm.&lt;/p&gt;
&lt;p&gt;We feel your pain: there are too many things to learn, too many skills to get, but too little time available — which reminds me of our extraordinary friend &lt;a href=&quot;https://www.imdb.com/title/tt0374900/&quot;&gt;Napoleon Dynamite&lt;/a&gt;. This blog post will guide you through the process of making a React web application without getting lost.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;658&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_XHTFs5--uJCCcQuI-9cccbcb9.DVTzmuKc_Z1K5bYU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you haven’t met Napoleon yet, click here to see how he was struggling with his skills. Screenshot from Napoleon Dynamite movie.&lt;/p&gt;
&lt;h2 id=&quot;react-web-application&quot;&gt;React web application&lt;/h2&gt;
&lt;p&gt;The web application we developed so far needs to update the entire page to display the results. Even for small changes in the web page, this has to happen. Thanks to modern web browsers and JavaScript, Single Page Applications (SPAs) can update only required elements in the web page. We will use one of the most popular web frameworks, React, to develop the SPA. We chose React over vanilla JavaScript because building a web application is made easier by letting React deal with all the magic behind the scenes. &lt;a href=&quot;https://www.freecodecamp.org/news/do-we-still-need-javascript-frameworks-42576735949b/&quot;&gt;This blog post&lt;/a&gt; may help you to understand why we made this choice.&lt;/p&gt;
&lt;p&gt;The form in the web application will collect the user inputs and uses them to initialize the algorithm. When the form is submitted, a WebAssembly code starts the calculation and the result is rendered. With this architecture, the application only needs cheap static file hosting to host the HTML, JavaScript, and WebAssembly files. The algorithm will be running in the web browser on the end-user’s machine instead of a server.&lt;/p&gt;
&lt;h3 id=&quot;the-html-code&quot;&gt;The HTML code&lt;/h3&gt;
&lt;p&gt;To render the React application we need an HTML element as a container. We will give it the identifier &lt;strong&gt;container&lt;/strong&gt; which will use later when we implement the &lt;strong&gt;React&lt;/strong&gt; application.&lt;/p&gt;
&lt;p&gt;We will keep the HTML code very minimal. The code will contain three essential elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt; element to set the title and to load the required external dependencies (JavaScript libraries).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div&gt; element to display the result&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;script&gt;&lt;/script&gt; elements to load the Javascript application and the &lt;code&gt;NewtonRaphson&lt;/code&gt; class.&lt;/strong&gt;&lt;/p&gt;&lt;strong&gt;
&lt;/strong&gt;&lt;/li&gt;&lt;strong&gt;
&lt;/strong&gt;&lt;/ul&gt;&lt;strong&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We use the same &lt;code&gt;newtonraphson.js&lt;/code&gt; and &lt;code&gt;newtonraphson.wasm&lt;/code&gt; files as in the &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/webassembly/README.md&quot;&gt;first post&lt;/a&gt; of this series. Make sure you download &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/react/newtonraphson.js&quot;&gt;newtonraphson.js&lt;/a&gt; and &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/react/newtonraphson.wasm&quot;&gt;newtonraphson.wasm&lt;/a&gt; files from GitHub.&lt;/p&gt;
&lt;p&gt;The complete HTML code will look like this:&lt;/p&gt;
&lt;h3 id=&quot;javascript-code-react&quot;&gt;JavaScript code (React)&lt;/h3&gt;
&lt;p&gt;Similarly, we will split the JavaScript code into sections and build up the React application from React components.&lt;/p&gt;
&lt;p&gt;Let’s start with the header part. We will define a JavaScript function that returns the header element which will be rendered by the web browser when the user visits the page.&lt;/p&gt;
&lt;p&gt;The return statement of this function looks weird, right? It is indeed not HTML. React uses a syntax extension called &lt;a href=&quot;https://reactjs.org/docs/introducing-jsx.html&quot;&gt;JSX&lt;/a&gt; to describe the UI. With the magical conversion of &lt;a href=&quot;https://babeljs.io/docs/en/next/babel-standalone.html&quot;&gt;Babel&lt;/a&gt; we can convert JSX into JavaScript code. After this conversion the generated JavaScript code will look like:&lt;/p&gt;
&lt;p&gt;In order for the header element to be rendered we need to tell &lt;strong&gt;ReactDOM&lt;/strong&gt; which element it should render and where it should be displayed. Do you still remember the &lt;strong&gt;container&lt;/strong&gt; &lt;code&gt;div&lt;/code&gt; we defined in the HTML part?&lt;/p&gt;
&lt;p&gt;The complete code should look like this:&lt;/p&gt;
&lt;p&gt;When the page is rendered, the generated HTML code will be like:&lt;/p&gt;
&lt;h2 id=&quot;adding-the-web-form&quot;&gt;Adding the web form&lt;/h2&gt;
&lt;p&gt;The web application in our example should have a form with &lt;code&gt;tolerance&lt;/code&gt; and &lt;code&gt;initial_guess&lt;/code&gt; input fields, as well as a submit button. The form in JSX can be written in the following way:&lt;/p&gt;
&lt;p&gt;The form tag has an &lt;code&gt;onSubmit&lt;/code&gt; property, which is set to a function ( &lt;code&gt;handleSubmit&lt;/code&gt;) that will handle the form submission. The input tag has a &lt;code&gt;value&lt;/code&gt; property to set the variable ( &lt;code&gt;tolerance&lt;/code&gt; and &lt;code&gt;initial_guess&lt;/code&gt;) and it also has an &lt;code&gt;onChange&lt;/code&gt; property to set the function ( &lt;code&gt;onToleranceChange&lt;/code&gt; and &lt;code&gt;onGuessChange&lt;/code&gt;) which will be triggered when the user changes the value.&lt;/p&gt;
&lt;p&gt;Let’s implement the &lt;code&gt;value&lt;/code&gt; and &lt;code&gt;onChange&lt;/code&gt; for the &lt;code&gt;tolerance&lt;/code&gt; input. To store the value we will use the &lt;a href=&quot;https://reactjs.org/docs/hooks-state.html&quot;&gt;React useState hook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The argument of the &lt;code&gt;useState&lt;/code&gt; function is the initial value. The &lt;code&gt;tolerance&lt;/code&gt; variable contains the current value for tolerance and &lt;code&gt;setTolerance&lt;/code&gt; is a function to set the &lt;code&gt;tolerance&lt;/code&gt; to a new value. The same logic is also used for the &lt;code&gt;initial_guess&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;The input tag in the form will call the &lt;code&gt;onChange&lt;/code&gt; function with an event object. We need to extract the user input from the event and pass it to &lt;code&gt;setTolerance&lt;/code&gt; or &lt;code&gt;setGuess&lt;/code&gt;. The value should be a number, so we use &lt;code&gt;Number()&lt;/code&gt; to cast the string from the event to a number.&lt;/p&gt;
&lt;p&gt;We are now ready to implement the &lt;code&gt;handleSubmit&lt;/code&gt; function which will process the submitted form data. The function will get an event object, similar to the &lt;code&gt;onChange&lt;/code&gt; of the input tag. Normally when you submit a form, the form fields will be sent to the server, but we want to perform the calculation in the browser, so we have to disable the default action with &lt;code&gt;preventDefault()&lt;/code&gt;. We will then construct a WebAssembly module as we did in &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/webassembly/README.md&quot;&gt;a previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We need a place to store the result of the calculation ( &lt;code&gt;root&lt;/code&gt; value), we will use &lt;code&gt;useState&lt;/code&gt; function again. The initial value of the result is set to &lt;code&gt;undefined&lt;/code&gt; as the result is only known after the calculation has been completed.&lt;/p&gt;
&lt;p&gt;When the calculation is done it will store the result value ( &lt;code&gt;root&lt;/code&gt;) using &lt;code&gt;setRoot&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To render the result we can use a React Component which has &lt;code&gt;root&lt;/code&gt; as a property. When the calculation has not been done yet, it will render &lt;code&gt;Not submitted&lt;/code&gt;. We will show the &lt;code&gt;root&lt;/code&gt; property value once it is set.&lt;/p&gt;
&lt;p&gt;Finally we can render the &lt;code&gt;App&lt;/code&gt; component to the HTML container with &lt;code&gt;id&lt;/code&gt; equal to &lt;code&gt;container&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can combine the heading, form and result components and all the states and &lt;code&gt;handleSubmit&lt;/code&gt; function into the &lt;code&gt;App&lt;/code&gt; React component and its rendering and save it as &lt;code&gt;app.js&lt;/code&gt;. You can find the resulting code &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/react/app.js&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Like before, we also need to host the files in a web server with&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;754&quot; height=&quot;222&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_smvfh5MifrSGsY10-8c73001a.6WsYx5Pj_Z1bngGr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The final page if everything works.&lt;/p&gt;
&lt;p&gt;Visit &lt;a href=&quot;http://localhost:8000/app.html&quot;&gt;http://localhost:8000/app.html&lt;/a&gt; to see the root answer, or go to &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/react/app.html&quot;&gt;GitHub pages&lt;/a&gt; to see a hosted version of the example app.&lt;/p&gt;
&lt;h2 id=&quot;extra-notes&quot;&gt;Extra notes&lt;/h2&gt;
&lt;p&gt;The code supplied here should not be used in production as converting JSX in the web browser is slow. It’s better to use &lt;a href=&quot;http://create-react-app.dev/&quot;&gt;Create React App&lt;/a&gt;, which gives you an infrastructure to perform the transformation offline.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By writing React components we were able to create an interactive page with a form that executes the WebAssembly module compiled from the C++ code we introduced in the &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;first blog&lt;/a&gt; of the series.&lt;/p&gt;
&lt;p&gt;We went over JSX, props, state, and components, which together constitute the core building blocks of a React web application.&lt;/p&gt;
&lt;p&gt;In other blogs of the series that might be of interest we cover&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;Using C++ in a web app with WebAssembly&lt;/a&gt;: How to turn C++ code into a web app.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;Help! My C++ web app is not responding&lt;/a&gt;: How to use web workers to perform computations without blocking the user interface.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;Spice up your C++ web app with visualizations&lt;/a&gt;: Plotting data from the C++ web app using web visualization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll wrap up the series in a &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;final blog&lt;/a&gt; that combines the topics of the whole series in a full-featured web application.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, leave a comment and give us a clap!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thank you to our proof reader&lt;/em&gt; &lt;a href=&quot;https://github.com/DAANBOER&quot;&gt;&lt;em&gt;Daan Boer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;&lt;/strong&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_XHTFs5--uJCCcQuI-9cccbcb9.DVTzmuKc.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Spice up your C++ web app with visualizations</title><link>https://blog2.esciencecenter.nl/posts/2020-10-09---spice-up-your-c-web-app-with-visualizations</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-10-09---spice-up-your-c-web-app-with-visualizations</guid><description>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;previous blog&lt;/a&gt; we found the root of an equation using the Newton-Raphson algorithm implemented in C++ and compiled to a WebAsssembly module. In this blog, we’re going to expand on that by visualizing the iterations that Newton-Raphson used to get from the initial guess to the estimate of the root.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2097&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_q33p383lsb3jlUV9-ca283010.CJQRcRqz_Z1V5IMO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Visualization allows us to track what’s going on under the hood of our program. Image courtesy of Nenad Stojkovic via flickr.&lt;/p&gt;
&lt;h2 id=&quot;iterations&quot;&gt;Iterations&lt;/h2&gt;
&lt;p&gt;The Newton-Raphson algorithm approximates the value of the target equation’s root in a series of iterations. We capture the data of each iteration using the following &lt;code&gt;struct&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt;: x value, starting with the value of &lt;code&gt;initial_guess&lt;/code&gt; and ending with the estimate of the &lt;code&gt;equation&lt;/code&gt; ‘s root&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y&lt;/code&gt;: result of passing &lt;code&gt;x&lt;/code&gt; through &lt;code&gt;equation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slope&lt;/code&gt;: result of passing &lt;code&gt;x&lt;/code&gt; through &lt;code&gt;derivative&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Extending the &lt;code&gt;NewtonRaphson&lt;/code&gt; class accordingly yields the following header file:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;newtonraphson.hpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;do&lt;/code&gt; loop in &lt;code&gt;newtonraphson.cpp&lt;/code&gt; is updated to include a &lt;code&gt;push_back&lt;/code&gt; to the &lt;code&gt;iterations&lt;/code&gt; vector. This way, we can record the value of relevant variables in each cycle, as follows:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;newtonraphson.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Before we go into the Emscripten world, let’s first test our C++ code. We can check if the iteration property is populated correctly, by extending the command line interface we made in the &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;previous blog&lt;/a&gt; as follows:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;cli.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Compile it with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;./&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;186.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 128.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.45&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.55&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;52.99&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 59.29&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.89&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.65&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13.97&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 29.63&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.47&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.18&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.89&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 17.83&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.02&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.28&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 14.40&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.02&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 14.01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last iteration has &lt;code&gt;x = -1.00&lt;/code&gt;, which is what we expected.&lt;/p&gt;
&lt;h2 id=&quot;bindings&quot;&gt;Bindings&lt;/h2&gt;
&lt;p&gt;Emscripten can handle simple types like &lt;code&gt;float&lt;/code&gt; and &lt;code&gt;int&lt;/code&gt;, but needs help exposing more complex types to JavaScript like the &lt;code&gt;iterations&lt;/code&gt; property. We need to use &lt;code&gt;value_object&lt;/code&gt; to expose the &lt;code&gt;Iteration&lt;/code&gt; &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;register_vector&lt;/code&gt; as the &lt;code&gt;iterations&lt;/code&gt; property type.&lt;/p&gt;
&lt;p&gt;So the bindings look like this:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;bindings.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We can now compile our C++ code to a WebAssembly module with Emscripten using &lt;code&gt;emcc&lt;/code&gt; command, exactly &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;like we did before&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;emcc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;I.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;js &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Oz&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MODULARIZE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;EXPORT_NAME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;createModule &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--bind \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp bindings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get the iteration data in JavaScript we use the following code&lt;/p&gt;
&lt;p&gt;Let’s have a look at the data we want to plot, by logging it to the console with &lt;code&gt;console.log(JSON.stringify(iterations, null, 2))&lt;/code&gt;, which should return the following data:&lt;/p&gt;
&lt;p&gt;Great, that looks very similar to the output we got from the command line.&lt;/p&gt;
&lt;h2 id=&quot;vega-lite-specification&quot;&gt;Vega-Lite specification&lt;/h2&gt;
&lt;p&gt;There &lt;a href=&quot;https://github.com/sorrycc/awesome-javascript#data-visualization&quot;&gt;many ways to do visualizations&lt;/a&gt; on the web. One of our favorites is &lt;a href=&quot;https://vega.github.io/vega-lite/&quot;&gt;Vega-Lite&lt;/a&gt;, a JavaScript library which describes a plot using a JSON document called a &lt;em&gt;specification&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The root finding algorithm tries to find the &lt;code&gt;x&lt;/code&gt; where &lt;code&gt;y&lt;/code&gt; is zero using a series of iterations. Let’s plot the iteration &lt;code&gt;index&lt;/code&gt; against the &lt;code&gt;y&lt;/code&gt; found in each iteration to see how quickly it converged to an answer.&lt;/p&gt;
&lt;p&gt;The generic structure of our Vega-Lite specification looks like this:&lt;/p&gt;
&lt;p&gt;To render a specification we need to use the &lt;code&gt;vegaEmbed(element, spec)&lt;/code&gt; method which accepts an HTML element and a Vega-Lite specification.&lt;/p&gt;
&lt;p&gt;Combining the three snippets above (get iteration data, Vega specification and vegaEmbed) and filling in their respective details yields an HTML document with the complete web app:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;scatter.html&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We’ll need a web server to display the HTML page in a web browser. For this, we’ll use the &lt;code&gt;http.server&lt;/code&gt; module from Python 3 again to host all files on port 8000, like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we visit the web page at &lt;a href=&quot;http://localhost:8000/scatter.html&quot;&gt;http://localhost:8000/scatter.html&lt;/a&gt;, we will be greeted by the following plot. We can zoom with the mouse wheel and pan by dragging. Hovering over a point shows a tooltip with relevant data at that point.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;888&quot; height=&quot;695&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_iP7zrZjQTIoAX2Zq-a9c14462.Q3UBIzG9_Z7LnFF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Click on image to get interactive version)&lt;/p&gt;
&lt;h2 id=&quot;advanced-plot&quot;&gt;Advanced plot&lt;/h2&gt;
&lt;p&gt;In the first blog of this series we plotted the equation and root as&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;857&quot; height=&quot;880&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_RUHNAgWlcRCfGzf1-8a8b79de.BjAjlaJh_2u6jK4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It would be nice to write a specification of this plot together with the iterations that the root finding algorithm went through. Vega-Lite can superimpose one chart on top of another with the keyword. Let’s construct each layer separately and then superimpose them at the end.&lt;/p&gt;
&lt;p&gt;The 2x³ — 4x² + 6 equation is plotted by using a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/data.html#sequence&quot;&gt;sequence generator&lt;/a&gt; to generate a range of &lt;code&gt;x&lt;/code&gt; values and a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/calculate.html&quot;&gt;formula transform&lt;/a&gt; is used to calculate the &lt;code&gt;y&lt;/code&gt; values.&lt;/p&gt;
&lt;p&gt;To show where the root is, we draw a dotted vertical line using a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/rule.html&quot;&gt;rule marker&lt;/a&gt; at &lt;code&gt;x = -1&lt;/code&gt; and label it &lt;code&gt;root&lt;/code&gt; with a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/text.html&quot;&gt;text marker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When we plot the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; of each iteration we can no longer see the order of iterations, so we will use a text marker above each circle to indicate which iteration it belongs to.&lt;/p&gt;
&lt;p&gt;Superimpose the equation line, root ruler, and iteration scatter into a single visualization with:&lt;/p&gt;
&lt;p&gt;The HTML page with all JavaScript put together to make a composite plot is available &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/vega/app.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Visiting the page should give us a plot like&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;883&quot; height=&quot;695&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_b72R67dWgF3M1Igc-32392a5a.DqrD48sd_2dCGNi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Click on image to get interactive version)&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;In this blog we have learned how to get complex data types from a WebAssembly module using Emscripten bindings and how to write a Vega-Lite specifications to get interactive visualizations.&lt;/p&gt;
&lt;p&gt;Other blogs of the series that might be of interest&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;Help! My C++ web app is not responding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;Interact with your C++ web app using React forms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll wrap up the series in a &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;final blog&lt;/a&gt; that combines the topics of the whole series in a full-featured web application.&lt;/p&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, leave a comment and give us a clap!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Fri, 09 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;previous blog&lt;/a&gt; we found the root of an equation using the Newton-Raphson algorithm implemented in C++ and compiled to a WebAsssembly module. In this blog, we’re going to expand on that by visualizing the iterations that Newton-Raphson used to get from the initial guess to the estimate of the root.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2097&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_q33p383lsb3jlUV9-ca283010.CJQRcRqz_Z1V5IMO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Visualization allows us to track what’s going on under the hood of our program. Image courtesy of Nenad Stojkovic via flickr.&lt;/p&gt;
&lt;h2 id=&quot;iterations&quot;&gt;Iterations&lt;/h2&gt;
&lt;p&gt;The Newton-Raphson algorithm approximates the value of the target equation’s root in a series of iterations. We capture the data of each iteration using the following &lt;code&gt;struct&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x&lt;/code&gt;: x value, starting with the value of &lt;code&gt;initial_guess&lt;/code&gt; and ending with the estimate of the &lt;code&gt;equation&lt;/code&gt; ‘s root&lt;/li&gt;
&lt;li&gt;&lt;code&gt;y&lt;/code&gt;: result of passing &lt;code&gt;x&lt;/code&gt; through &lt;code&gt;equation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slope&lt;/code&gt;: result of passing &lt;code&gt;x&lt;/code&gt; through &lt;code&gt;derivative&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Extending the &lt;code&gt;NewtonRaphson&lt;/code&gt; class accordingly yields the following header file:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;newtonraphson.hpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;do&lt;/code&gt; loop in &lt;code&gt;newtonraphson.cpp&lt;/code&gt; is updated to include a &lt;code&gt;push_back&lt;/code&gt; to the &lt;code&gt;iterations&lt;/code&gt; vector. This way, we can record the value of relevant variables in each cycle, as follows:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;newtonraphson.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Before we go into the Emscripten world, let’s first test our C++ code. We can check if the iteration property is populated correctly, by extending the command line interface we made in the &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;previous blog&lt;/a&gt; as follows:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;cli.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Compile it with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;./&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;186.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 128.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.45&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.55&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;52.99&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 59.29&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.89&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.65&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13.97&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 29.63&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.47&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.18&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2.89&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 17.83&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.02&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.28&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 14.40&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.02&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;index &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.00&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; slope &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 14.01&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; delta_x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0.00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last iteration has &lt;code&gt;x = -1.00&lt;/code&gt;, which is what we expected.&lt;/p&gt;
&lt;h2 id=&quot;bindings&quot;&gt;Bindings&lt;/h2&gt;
&lt;p&gt;Emscripten can handle simple types like &lt;code&gt;float&lt;/code&gt; and &lt;code&gt;int&lt;/code&gt;, but needs help exposing more complex types to JavaScript like the &lt;code&gt;iterations&lt;/code&gt; property. We need to use &lt;code&gt;value_object&lt;/code&gt; to expose the &lt;code&gt;Iteration&lt;/code&gt; &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;register_vector&lt;/code&gt; as the &lt;code&gt;iterations&lt;/code&gt; property type.&lt;/p&gt;
&lt;p&gt;So the bindings look like this:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;bindings.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We can now compile our C++ code to a WebAssembly module with Emscripten using &lt;code&gt;emcc&lt;/code&gt; command, exactly &lt;a href=&quot;https://medium.com/@eScienceCenter/using-c-in-a-web-app-with-webassembly-efd78c08469&quot;&gt;like we did before&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;emcc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;I.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;js &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Oz&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MODULARIZE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;EXPORT_NAME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;createModule &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--bind \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp bindings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get the iteration data in JavaScript we use the following code&lt;/p&gt;
&lt;p&gt;Let’s have a look at the data we want to plot, by logging it to the console with &lt;code&gt;console.log(JSON.stringify(iterations, null, 2))&lt;/code&gt;, which should return the following data:&lt;/p&gt;
&lt;p&gt;Great, that looks very similar to the output we got from the command line.&lt;/p&gt;
&lt;h2 id=&quot;vega-lite-specification&quot;&gt;Vega-Lite specification&lt;/h2&gt;
&lt;p&gt;There &lt;a href=&quot;https://github.com/sorrycc/awesome-javascript#data-visualization&quot;&gt;many ways to do visualizations&lt;/a&gt; on the web. One of our favorites is &lt;a href=&quot;https://vega.github.io/vega-lite/&quot;&gt;Vega-Lite&lt;/a&gt;, a JavaScript library which describes a plot using a JSON document called a &lt;em&gt;specification&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The root finding algorithm tries to find the &lt;code&gt;x&lt;/code&gt; where &lt;code&gt;y&lt;/code&gt; is zero using a series of iterations. Let’s plot the iteration &lt;code&gt;index&lt;/code&gt; against the &lt;code&gt;y&lt;/code&gt; found in each iteration to see how quickly it converged to an answer.&lt;/p&gt;
&lt;p&gt;The generic structure of our Vega-Lite specification looks like this:&lt;/p&gt;
&lt;p&gt;To render a specification we need to use the &lt;code&gt;vegaEmbed(element, spec)&lt;/code&gt; method which accepts an HTML element and a Vega-Lite specification.&lt;/p&gt;
&lt;p&gt;Combining the three snippets above (get iteration data, Vega specification and vegaEmbed) and filling in their respective details yields an HTML document with the complete web app:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;scatter.html&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We’ll need a web server to display the HTML page in a web browser. For this, we’ll use the &lt;code&gt;http.server&lt;/code&gt; module from Python 3 again to host all files on port 8000, like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we visit the web page at &lt;a href=&quot;http://localhost:8000/scatter.html&quot;&gt;http://localhost:8000/scatter.html&lt;/a&gt;, we will be greeted by the following plot. We can zoom with the mouse wheel and pan by dragging. Hovering over a point shows a tooltip with relevant data at that point.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;888&quot; height=&quot;695&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_iP7zrZjQTIoAX2Zq-a9c14462.Q3UBIzG9_Z7LnFF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Click on image to get interactive version)&lt;/p&gt;
&lt;h2 id=&quot;advanced-plot&quot;&gt;Advanced plot&lt;/h2&gt;
&lt;p&gt;In the first blog of this series we plotted the equation and root as&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;857&quot; height=&quot;880&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_RUHNAgWlcRCfGzf1-8a8b79de.BjAjlaJh_2u6jK4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It would be nice to write a specification of this plot together with the iterations that the root finding algorithm went through. Vega-Lite can superimpose one chart on top of another with the keyword. Let’s construct each layer separately and then superimpose them at the end.&lt;/p&gt;
&lt;p&gt;The 2x³ — 4x² + 6 equation is plotted by using a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/data.html#sequence&quot;&gt;sequence generator&lt;/a&gt; to generate a range of &lt;code&gt;x&lt;/code&gt; values and a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/calculate.html&quot;&gt;formula transform&lt;/a&gt; is used to calculate the &lt;code&gt;y&lt;/code&gt; values.&lt;/p&gt;
&lt;p&gt;To show where the root is, we draw a dotted vertical line using a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/rule.html&quot;&gt;rule marker&lt;/a&gt; at &lt;code&gt;x = -1&lt;/code&gt; and label it &lt;code&gt;root&lt;/code&gt; with a &lt;a href=&quot;https://vega.github.io/vega-lite/docs/text.html&quot;&gt;text marker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When we plot the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; of each iteration we can no longer see the order of iterations, so we will use a text marker above each circle to indicate which iteration it belongs to.&lt;/p&gt;
&lt;p&gt;Superimpose the equation line, root ruler, and iteration scatter into a single visualization with:&lt;/p&gt;
&lt;p&gt;The HTML page with all JavaScript put together to make a composite plot is available &lt;a href=&quot;https://github.com/NLESC-JCER/run-cpp-on-web/blob/master/vega/app.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Visiting the page should give us a plot like&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;883&quot; height=&quot;695&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_b72R67dWgF3M1Igc-32392a5a.DqrD48sd_2dCGNi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(Click on image to get interactive version)&lt;/p&gt;
&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;In this blog we have learned how to get complex data types from a WebAssembly module using Emscripten bindings and how to write a Vega-Lite specifications to get interactive visualizations.&lt;/p&gt;
&lt;p&gt;Other blogs of the series that might be of interest&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;Help! My C++ web app is not responding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;Interact with your C++ web app using React forms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll wrap up the series in a &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;final blog&lt;/a&gt; that combines the topics of the whole series in a full-featured web application.&lt;/p&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, leave a comment and give us a clap!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_q33p383lsb3jlUV9-ca283010.CJQRcRqz.jpg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Using C++ in a web app with WebAssembly</title><link>https://blog2.esciencecenter.nl/posts/2020-10-09---using-c-in-a-web-app-with-webassembly</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-10-09---using-c-in-a-web-app-with-webassembly</guid><description>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let’s say you have some C++ code laying around that you would like to make available to a wider audience, by putting it on the web as a ready to use web tool. Until recently, this used to be pretty difficult, and may even have required reimplementation of the software in JavaScript, the programming language that browsers use.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wouldn’t it be great if you could run your existing C++ code on the web with only minor effort?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That way, loads more people would be able to see your results, interact with your algorithm, and apply it for their own purposes.&lt;/p&gt;
&lt;p&gt;In this blog, we’ll show you how to take a simple algorithm written in C++ and make it available as a web application. Subsequent blogs in this series will expand on the current one by laying out more advanced topics, specifically how to &lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;make the app interactive&lt;/a&gt;, how to &lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;visualize the results&lt;/a&gt;, and how to &lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;deal with long running tasks&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;root-finding&quot;&gt;Root finding&lt;/h2&gt;
&lt;p&gt;So today’s aim is to have a simple web app that determines the root of a mathematical function &lt;em&gt;2x³ — 4x² + 6&lt;/em&gt;, i.e. the value of &lt;em&gt;x&lt;/em&gt; where &lt;em&gt;y = 0&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;857&quot; height=&quot;880&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_RUHNAgWlcRCfGzf1-8a8b79de.BjAjlaJh_2u6jK4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Function 2x³ — 4x² + 6.&lt;/p&gt;
&lt;p&gt;For this, we’ll use an iterative method known as the &lt;a href=&quot;https://www.youtube.com/watch?v=cOmAk82cr9M&quot;&gt;&lt;em&gt;Newton-Raphson&lt;/em&gt; root finding method&lt;/a&gt;. Remember Newton? Quiet fellow, fabulous hair? Yes, &lt;em&gt;that&lt;/em&gt; Newton. The way Newton-Raphson works is, you give it the equation whose root you want to find, along with the derivative of that equation. Then you take an &lt;code&gt;initial_guess&lt;/code&gt; of what you think the value of the root could be, then let the method iterate towards the solution. The solution is approximate within a &lt;code&gt;tolerance&lt;/code&gt;, which you can also set. Anyway, the algorithm is written C++, but &lt;strong&gt;with some trickery, we’ll be able to use that C++ code from the browser, without the need to port it first&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1275&quot; height=&quot;1777&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_GL19nE2yCZ-loY6y-2b0130c2.CGMtxH0u_ZFBCi1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Newton (and his hair). Image courtesy of Wikimedia Commons.&lt;/p&gt;
&lt;p&gt;Now before you say &lt;em&gt;“That’ll be so much slower than running it native!”&lt;/em&gt; or &lt;em&gt;“C++ from the browser? Impossible!”&lt;/em&gt;, just hold your horses for a sec. With the right tools, it is possible to run C++ code in the browser, with an acceptable performance penalty. For example, Gabriel Cuvillier was able to run the video game &lt;em&gt;Doom 3&lt;/em&gt; &lt;a href=&quot;http://wasm.continuation-labs.com/d3demo/&quot;&gt;in the browser&lt;/a&gt;. He was able to do this by compiling the game’s source code into WebAssembly, a low-level language that browsers can run. And if it works for video games, it will likely work for your research software, too.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;910&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_WILEEGqVA7Izb05c-277ca307.CDJdkOwM_23fGz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Hold your horses. Image courtesy of Luciano Marelli via pixabay.&lt;/p&gt;
&lt;h2 id=&quot;what-well-need&quot;&gt;What we’ll need&lt;/h2&gt;
&lt;p&gt;OK, now that you’re fully on board with this, let’s get to it. Here’s a list of what we need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We are going to write a small HTML page, so you will need basic knowledge of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics&quot;&gt;HTML&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript&quot;&gt;JavaScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Some C++ code to illustrate the process. We’ll use our Newton-Raphson C++ code.&lt;/li&gt;
&lt;li&gt;A program ==that== can take our existing C++ code and compile it into a WebAssembly module. For this, we’ll use &lt;a href=&quot;https://emscripten.org/&quot;&gt;Emscripten&lt;/a&gt; ’s &lt;code&gt;emcc&lt;/code&gt; compiler, the most popular C++ to WebAssembly compiler of the bunch.&lt;/li&gt;
&lt;li&gt;To use the WebAssembly functionality from JavaScript, a binding is required. The binding will map C++ constructs to their JavaScript equivalent and back. For this, we’ll use &lt;a href=&quot;https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#embind&quot;&gt;embind&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A web server to serve our files. We’ll use Python 3’s &lt;code&gt;http.server&lt;/code&gt;, but other web servers work equally well.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;tying-it-all-together&quot;&gt;Tying it all together&lt;/h2&gt;
&lt;h3 id=&quot;the-c-code&quot;&gt;The C++ code&lt;/h3&gt;
&lt;p&gt;Here is the equation whose root we want to find, along with its derivative, since that’s what Newton-Raphson requires:&lt;/p&gt;
&lt;p&gt;File: problem.hpp&lt;/p&gt;
&lt;p&gt;File: problem.cpp&lt;/p&gt;
&lt;p&gt;The snippet below shows the contents of the file &lt;code&gt;newtonraphson.hpp&lt;/code&gt;. It is the header file for the Newton-Raphson iterative root finding algorithm. It defines a class named &lt;code&gt;NewtonRaphson&lt;/code&gt;. Besides the constructor method &lt;code&gt;NewtonRaphson(float tolerance_in)&lt;/code&gt;, &lt;code&gt;NewtonRaphson&lt;/code&gt; has one other public method, &lt;code&gt;solve&lt;/code&gt;, which takes a &lt;code&gt;float&lt;/code&gt;, and returns another &lt;code&gt;float&lt;/code&gt;. Furthermore, &lt;code&gt;NewtonRaphson&lt;/code&gt; also has a private member, &lt;code&gt;tolerance&lt;/code&gt; of type &lt;code&gt;float&lt;/code&gt;, which is used to store the class instance’s private data.&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;newtonraphson.hpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;newtonraphson.cpp&lt;/code&gt; contains the corresponding implementation:&lt;/p&gt;
&lt;p&gt;File: newtonraphson.cpp&lt;/p&gt;
&lt;p&gt;From this definition, &lt;code&gt;NewtonRaphson&lt;/code&gt; instances need to be initialized with a value for &lt;code&gt;tolerance_in&lt;/code&gt;, which is then stored as the private member &lt;code&gt;tolerance&lt;/code&gt;. Once the object instance has been constructed, users can call its &lt;code&gt;solve&lt;/code&gt; method to iteratively find &lt;code&gt;equation&lt;/code&gt; ‘s root, with &lt;code&gt;equation&lt;/code&gt; and its &lt;code&gt;derivative&lt;/code&gt; being imported from &lt;code&gt;problem.hpp&lt;/code&gt; via the &lt;code&gt;include&lt;/code&gt; line near the top.&lt;/p&gt;
&lt;h3 id=&quot;check-on-command-line&quot;&gt;Check on command line&lt;/h3&gt;
&lt;p&gt;The following code is a minimal command line program that we can use to check if everything is working correctly:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;cli.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Our command line program can be compiled with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Subsequently running it should give the following output:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;./&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the root is &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we’re ready to move on to the WebAssembly part.&lt;/p&gt;
&lt;h3 id=&quot;binding&quot;&gt;Binding&lt;/h3&gt;
&lt;p&gt;To use the Newton-Raphson code from JavaScript, we’ll need to define the &lt;em&gt;bindings&lt;/em&gt; file. The binding allows compiled code to be called from JavaScript. For our Newton-Raphson code, the binding file looks like this:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;bindings.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The binding file uses &lt;code&gt;embind&lt;/code&gt; &lt;a href=&quot;https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#classes&quot;&gt;binding statements&lt;/a&gt; to expose the &lt;code&gt;NewtonRaphson&lt;/code&gt; class, its constructor method, as well as its public method &lt;code&gt;solve&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;compiling-to-webassembly&quot;&gt;Compiling to WebAssembly&lt;/h3&gt;
&lt;p&gt;First we need to &lt;a href=&quot;https://emscripten.org/docs/getting_started/downloads.html&quot;&gt;download and install&lt;/a&gt; Emscripten to get the compiler. The Newton-Raphson source and its binding can be compiled into a WebAssembly module with Emscripten’s &lt;code&gt;emcc&lt;/code&gt; compiler, as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;emcc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;I.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;js &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Oz&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MODULARIZE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;EXPORT_NAME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;createModule &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--bind \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp bindings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will generate a WebAssembly module &lt;code&gt;newtonraphson.wasm&lt;/code&gt;, along with a JavaScript file &lt;code&gt;newtonraphson.js&lt;/code&gt;. We also export the &lt;code&gt;createModule&lt;/code&gt; JavaScript function in the compile command so it can be used to load and initialize the WebAssembly ==module==. Using the &lt;code&gt;newtonraphson.js&lt;/code&gt; JavaScript library, we can find the root of the mathematical function, and subsequently display its value with the following HTML:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;index.html&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;hosting-the-app-with-a-web-server&quot;&gt;Hosting the app with a web server&lt;/h3&gt;
&lt;p&gt;We’ll need a web server to display the HTML page in a web browser. For this, we’ll use the &lt;a href=&quot;https://docs.python.org/3/library/http.server.html&quot;&gt;http.server&lt;/a&gt; module from Python 3 to host all files in the current directory on port 8000, like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# change to directory with index.html and newtonraphson.* files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the figure at the top of the article, the root of the equation should be at &lt;code&gt;x = -1.00&lt;/code&gt;. Visit &lt;a href=&quot;http://localhost:8000/&quot;&gt;http://localhost:8000/&lt;/a&gt; to see if your browser shows the correct result.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;212&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_sgmpFtqMZRHKIBW4-19d2b6c1.lHGtXvuX_28fnXD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The resulting page if everything works. See the live version of the app on GitHub pages.&lt;/p&gt;
&lt;h2 id=&quot;recap&quot;&gt;Recap&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;We wrote a simple algorithm in C++&lt;/li&gt;
&lt;li&gt;We defined the JavaScript interface by writing Emscripten bindings&lt;/li&gt;
&lt;li&gt;We compiled the algorithm and bindings to a WebAssembly module with Emscripten compiler&lt;/li&gt;
&lt;li&gt;We ran the algorithm in a web browser using some JavaScript to talk to the WebAssembly module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The nice thing about this solution is that we don’t need expensive infrastructure to perform computation as the computation is done in the user’s web browser — we just need somewhere to host the files.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where to go from here?&lt;/h2&gt;
&lt;p&gt;In upcoming blogs we will cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;Help! My C++ web app is not responding&lt;/a&gt;: how to perform computations without blocking the user interface.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;Interact with your C++ web app using React forms&lt;/a&gt;: how to let the user supply their own input values for &lt;code&gt;tolerance&lt;/code&gt; and &lt;code&gt;initial_guess&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;Spice up your C++ web app with visualizations&lt;/a&gt;: how to visualize data from the algorithm.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll wrap up the series in &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;a final blog&lt;/a&gt; that combines the topics of the whole series in a full-featured web application. If you’re curious what that’s going to look like, make sure to check out the &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/kitchen-sink/app.html&quot;&gt;live demo&lt;/a&gt; on GitHub Pages.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, leave a comment and give us a clap!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Thank you to our proof readers&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-8002-5459&quot;&gt;&lt;em&gt;Jan van Dijk&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://github.com/DAANBOER&quot;&gt;&lt;em&gt;Daan Boer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-6311-1168&quot;&gt;&lt;em&gt;Lourens Veen&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-6033-960X&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Fri, 09 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-0989-929X&quot;&gt;&lt;em&gt;Faruk Diblen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-6306-6937&quot;&gt;&lt;em&gt;Adam Belloum&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5529-5761&quot;&gt;&lt;em&gt;Christiaan Meijer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let’s say you have some C++ code laying around that you would like to make available to a wider audience, by putting it on the web as a ready to use web tool. Until recently, this used to be pretty difficult, and may even have required reimplementation of the software in JavaScript, the programming language that browsers use.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wouldn’t it be great if you could run your existing C++ code on the web with only minor effort?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That way, loads more people would be able to see your results, interact with your algorithm, and apply it for their own purposes.&lt;/p&gt;
&lt;p&gt;In this blog, we’ll show you how to take a simple algorithm written in C++ and make it available as a web application. Subsequent blogs in this series will expand on the current one by laying out more advanced topics, specifically how to &lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;make the app interactive&lt;/a&gt;, how to &lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;visualize the results&lt;/a&gt;, and how to &lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;deal with long running tasks&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;root-finding&quot;&gt;Root finding&lt;/h2&gt;
&lt;p&gt;So today’s aim is to have a simple web app that determines the root of a mathematical function &lt;em&gt;2x³ — 4x² + 6&lt;/em&gt;, i.e. the value of &lt;em&gt;x&lt;/em&gt; where &lt;em&gt;y = 0&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;857&quot; height=&quot;880&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_RUHNAgWlcRCfGzf1-8a8b79de.BjAjlaJh_2u6jK4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Function 2x³ — 4x² + 6.&lt;/p&gt;
&lt;p&gt;For this, we’ll use an iterative method known as the &lt;a href=&quot;https://www.youtube.com/watch?v=cOmAk82cr9M&quot;&gt;&lt;em&gt;Newton-Raphson&lt;/em&gt; root finding method&lt;/a&gt;. Remember Newton? Quiet fellow, fabulous hair? Yes, &lt;em&gt;that&lt;/em&gt; Newton. The way Newton-Raphson works is, you give it the equation whose root you want to find, along with the derivative of that equation. Then you take an &lt;code&gt;initial_guess&lt;/code&gt; of what you think the value of the root could be, then let the method iterate towards the solution. The solution is approximate within a &lt;code&gt;tolerance&lt;/code&gt;, which you can also set. Anyway, the algorithm is written C++, but &lt;strong&gt;with some trickery, we’ll be able to use that C++ code from the browser, without the need to port it first&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1275&quot; height=&quot;1777&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_GL19nE2yCZ-loY6y-2b0130c2.CGMtxH0u_ZFBCi1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Newton (and his hair). Image courtesy of Wikimedia Commons.&lt;/p&gt;
&lt;p&gt;Now before you say &lt;em&gt;“That’ll be so much slower than running it native!”&lt;/em&gt; or &lt;em&gt;“C++ from the browser? Impossible!”&lt;/em&gt;, just hold your horses for a sec. With the right tools, it is possible to run C++ code in the browser, with an acceptable performance penalty. For example, Gabriel Cuvillier was able to run the video game &lt;em&gt;Doom 3&lt;/em&gt; &lt;a href=&quot;http://wasm.continuation-labs.com/d3demo/&quot;&gt;in the browser&lt;/a&gt;. He was able to do this by compiling the game’s source code into WebAssembly, a low-level language that browsers can run. And if it works for video games, it will likely work for your research software, too.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;910&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_WILEEGqVA7Izb05c-277ca307.CDJdkOwM_23fGz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Hold your horses. Image courtesy of Luciano Marelli via pixabay.&lt;/p&gt;
&lt;h2 id=&quot;what-well-need&quot;&gt;What we’ll need&lt;/h2&gt;
&lt;p&gt;OK, now that you’re fully on board with this, let’s get to it. Here’s a list of what we need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We are going to write a small HTML page, so you will need basic knowledge of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/HTML_basics&quot;&gt;HTML&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript&quot;&gt;JavaScript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Some C++ code to illustrate the process. We’ll use our Newton-Raphson C++ code.&lt;/li&gt;
&lt;li&gt;A program ==that== can take our existing C++ code and compile it into a WebAssembly module. For this, we’ll use &lt;a href=&quot;https://emscripten.org/&quot;&gt;Emscripten&lt;/a&gt; ’s &lt;code&gt;emcc&lt;/code&gt; compiler, the most popular C++ to WebAssembly compiler of the bunch.&lt;/li&gt;
&lt;li&gt;To use the WebAssembly functionality from JavaScript, a binding is required. The binding will map C++ constructs to their JavaScript equivalent and back. For this, we’ll use &lt;a href=&quot;https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#embind&quot;&gt;embind&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A web server to serve our files. We’ll use Python 3’s &lt;code&gt;http.server&lt;/code&gt;, but other web servers work equally well.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;tying-it-all-together&quot;&gt;Tying it all together&lt;/h2&gt;
&lt;h3 id=&quot;the-c-code&quot;&gt;The C++ code&lt;/h3&gt;
&lt;p&gt;Here is the equation whose root we want to find, along with its derivative, since that’s what Newton-Raphson requires:&lt;/p&gt;
&lt;p&gt;File: problem.hpp&lt;/p&gt;
&lt;p&gt;File: problem.cpp&lt;/p&gt;
&lt;p&gt;The snippet below shows the contents of the file &lt;code&gt;newtonraphson.hpp&lt;/code&gt;. It is the header file for the Newton-Raphson iterative root finding algorithm. It defines a class named &lt;code&gt;NewtonRaphson&lt;/code&gt;. Besides the constructor method &lt;code&gt;NewtonRaphson(float tolerance_in)&lt;/code&gt;, &lt;code&gt;NewtonRaphson&lt;/code&gt; has one other public method, &lt;code&gt;solve&lt;/code&gt;, which takes a &lt;code&gt;float&lt;/code&gt;, and returns another &lt;code&gt;float&lt;/code&gt;. Furthermore, &lt;code&gt;NewtonRaphson&lt;/code&gt; also has a private member, &lt;code&gt;tolerance&lt;/code&gt; of type &lt;code&gt;float&lt;/code&gt;, which is used to store the class instance’s private data.&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;newtonraphson.hpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;newtonraphson.cpp&lt;/code&gt; contains the corresponding implementation:&lt;/p&gt;
&lt;p&gt;File: newtonraphson.cpp&lt;/p&gt;
&lt;p&gt;From this definition, &lt;code&gt;NewtonRaphson&lt;/code&gt; instances need to be initialized with a value for &lt;code&gt;tolerance_in&lt;/code&gt;, which is then stored as the private member &lt;code&gt;tolerance&lt;/code&gt;. Once the object instance has been constructed, users can call its &lt;code&gt;solve&lt;/code&gt; method to iteratively find &lt;code&gt;equation&lt;/code&gt; ‘s root, with &lt;code&gt;equation&lt;/code&gt; and its &lt;code&gt;derivative&lt;/code&gt; being imported from &lt;code&gt;problem.hpp&lt;/code&gt; via the &lt;code&gt;include&lt;/code&gt; line near the top.&lt;/p&gt;
&lt;h3 id=&quot;check-on-command-line&quot;&gt;Check on command line&lt;/h3&gt;
&lt;p&gt;The following code is a minimal command line program that we can use to check if everything is working correctly:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;cli.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Our command line program can be compiled with:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;g&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Subsequently running it should give the following output:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;./&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cli&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; value &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the root is &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1.00&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we’re ready to move on to the WebAssembly part.&lt;/p&gt;
&lt;h3 id=&quot;binding&quot;&gt;Binding&lt;/h3&gt;
&lt;p&gt;To use the Newton-Raphson code from JavaScript, we’ll need to define the &lt;em&gt;bindings&lt;/em&gt; file. The binding allows compiled code to be called from JavaScript. For our Newton-Raphson code, the binding file looks like this:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;bindings.cpp&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The binding file uses &lt;code&gt;embind&lt;/code&gt; &lt;a href=&quot;https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#classes&quot;&gt;binding statements&lt;/a&gt; to expose the &lt;code&gt;NewtonRaphson&lt;/code&gt; class, its constructor method, as well as its public method &lt;code&gt;solve&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;compiling-to-webassembly&quot;&gt;Compiling to WebAssembly&lt;/h3&gt;
&lt;p&gt;First we need to &lt;a href=&quot;https://emscripten.org/docs/getting_started/downloads.html&quot;&gt;download and install&lt;/a&gt; Emscripten to get the compiler. The Newton-Raphson source and its binding can be compiled into a WebAssembly module with Emscripten’s &lt;code&gt;emcc&lt;/code&gt; compiler, as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;emcc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;I.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;js &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Oz&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MODULARIZE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;EXPORT_NAME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;createModule &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--bind \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; problem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp newtonraphson&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp bindings&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will generate a WebAssembly module &lt;code&gt;newtonraphson.wasm&lt;/code&gt;, along with a JavaScript file &lt;code&gt;newtonraphson.js&lt;/code&gt;. We also export the &lt;code&gt;createModule&lt;/code&gt; JavaScript function in the compile command so it can be used to load and initialize the WebAssembly ==module==. Using the &lt;code&gt;newtonraphson.js&lt;/code&gt; JavaScript library, we can find the root of the mathematical function, and subsequently display its value with the following HTML:&lt;/p&gt;
&lt;p&gt;File: &lt;em&gt;index.html&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;hosting-the-app-with-a-web-server&quot;&gt;Hosting the app with a web server&lt;/h3&gt;
&lt;p&gt;We’ll need a web server to display the HTML page in a web browser. For this, we’ll use the &lt;a href=&quot;https://docs.python.org/3/library/http.server.html&quot;&gt;http.server&lt;/a&gt; module from Python 3 to host all files in the current directory on port 8000, like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# change to directory with index.html and newtonraphson.* files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python3 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m http&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;server &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the figure at the top of the article, the root of the equation should be at &lt;code&gt;x = -1.00&lt;/code&gt;. Visit &lt;a href=&quot;http://localhost:8000/&quot;&gt;http://localhost:8000/&lt;/a&gt; to see if your browser shows the correct result.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;212&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_sgmpFtqMZRHKIBW4-19d2b6c1.lHGtXvuX_28fnXD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The resulting page if everything works. See the live version of the app on GitHub pages.&lt;/p&gt;
&lt;h2 id=&quot;recap&quot;&gt;Recap&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;We wrote a simple algorithm in C++&lt;/li&gt;
&lt;li&gt;We defined the JavaScript interface by writing Emscripten bindings&lt;/li&gt;
&lt;li&gt;We compiled the algorithm and bindings to a WebAssembly module with Emscripten compiler&lt;/li&gt;
&lt;li&gt;We ran the algorithm in a web browser using some JavaScript to talk to the WebAssembly module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The nice thing about this solution is that we don’t need expensive infrastructure to perform computation as the computation is done in the user’s web browser — we just need somewhere to host the files.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch-with-us&quot;&gt;Get in touch with us&lt;/h2&gt;
&lt;p&gt;This blog was written by the Generalization Team of the Netherlands eScience Center. The team consists of Stefan Verhoeven, Faruk Diblen, Jurriaan H. Spaaks, Adam Belloum and Christiaan Meijer. Feel free to get in touch with the generalization team at &lt;a href=&quot;mailto:generalization@esciencecenter.nl&quot;&gt;generalization@esciencecenter.nl&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where to go from here?&lt;/h2&gt;
&lt;p&gt;In upcoming blogs we will cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/help-my-c-web-app-is-not-responding-b930ca3034ad&quot;&gt;Help! My C++ web app is not responding&lt;/a&gt;: how to perform computations without blocking the user interface.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/interact-with-your-c-web-app-using-react-forms-543e676a7634&quot;&gt;Interact with your C++ web app using React forms&lt;/a&gt;: how to let the user supply their own input values for &lt;code&gt;tolerance&lt;/code&gt; and &lt;code&gt;initial_guess&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@eScienceCenter/spice-up-your-c-web-app-with-visualizations-bcc1e888ec25&quot;&gt;Spice up your C++ web app with visualizations&lt;/a&gt;: how to visualize data from the algorithm.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ll wrap up the series in &lt;a href=&quot;https://medium.com/@eScienceCenter/c-web-app-with-webassembly-vega-web-worker-and-react-1e5b750c88df&quot;&gt;a final blog&lt;/a&gt; that combines the topics of the whole series in a full-featured web application. If you’re curious what that’s going to look like, make sure to check out the &lt;a href=&quot;https://nlesc-jcer.github.io/run-cpp-on-web/kitchen-sink/app.html&quot;&gt;live demo&lt;/a&gt; on GitHub Pages.&lt;/p&gt;
&lt;p&gt;If you enjoyed this article, leave a comment and give us a clap!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These blogs were written as part of the “Passing XSAMS” project. To learn more about the project, check out its&lt;/em&gt; &lt;a href=&quot;https://www.esciencecenter.nl/projects/passing-xsams/&quot;&gt;&lt;em&gt;project page&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Thank you to our proof readers&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0001-8002-5459&quot;&gt;&lt;em&gt;Jan van Dijk&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://github.com/DAANBOER&quot;&gt;&lt;em&gt;Daan Boer&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-6311-1168&quot;&gt;&lt;em&gt;Lourens Veen&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-6033-960X&quot;&gt;&lt;em&gt;Patrick Bos&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_RUHNAgWlcRCfGzf1-8a8b79de.BjAjlaJh.webp" medium="image"/><author>eScience Editorial Team</author></item><item><title>Use-after-free? No more with Valgrind</title><link>https://blog2.esciencecenter.nl/posts/2020-09-28---use-after-free-no-more-with-valgrind</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-09-28---use-after-free-no-more-with-valgrind</guid><description>&lt;p&gt;In my long career as a code detective, I have seen it all. I have travelled the high Cs, found Rubies and wrestled Pythons, and walked the alleyways of Fortran at night. Of course, as with any job most cases are run-of-the-mill, but some of them are not. Those are the ones you remember. The ones you tell your grandchildren about, if you live to tell the tale.&lt;/p&gt;
&lt;p&gt;This is the story of a programming mistake that caused a C++ program to crash, and how it was fixed using &lt;a href=&quot;https://valgrind.org/&quot;&gt;Valgrind&lt;/a&gt;. It features mysterious artefacts, C++ memory management, and fixing and avoiding mistakes in (scientific) software. I hope it will teach you something about use-after-free issues, and inspire you to try Valgrind for memory debugging next time you have a similar problem. Let’s dive right in, shall we?&lt;/p&gt;
&lt;h2 id=&quot;the-curious-case-of-the-crashing-simulation&quot;&gt;The Curious Case of the Crashing Simulation&lt;/h2&gt;
&lt;p&gt;It was a dark and stormy ni…no wait, it was actually a sunny afternoon in spring, when I received an email from a scientist named Pavel. Pavel is a postdoc at the University of Amsterdam and the Erasmus University Medical Center in Rotterdam, and he was working on porting a rather complicated computer simulation of something called an &lt;a href=&quot;https://en.wikipedia.org/wiki/Restenosis&quot;&gt;In-Stent Restenosis&lt;/a&gt; to &lt;a href=&quot;https://github.com/multiscale/muscle3&quot;&gt;MUSCLE3&lt;/a&gt;. His program was crashing. And he suspected the problem was with MUSCLE3. Which I created and currently maintain. Which would mean… &lt;em&gt;DUH-DUH-DUUUUUH&lt;/em&gt; (organ sound effect) &lt;em&gt;THERE WAS A MISTAKE IN MY CODE&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;By the way, why can’t you include sound effects in blog posts? I think blog posts are much better with sound effects. Someone should fix this. Meanwhile, here’s an image depicting the horror:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;An ink drawing of a face with its eyes and mouth wide open in horror. It is flanked by raised arms on both sides.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;982&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_g4Uw0OcyPSJMyeKP-89e7e8c7.D3nu8NeI_ZgkqUt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“The Scream” Undated drawing by Edvard Munch (via Wikipedia )&lt;/p&gt;
&lt;p&gt;Anyway, yes, there was a mistake in MUSCLE3. But to explain the problem, I need to explain what MUSCLE3 does first. MUSCLE3 is a coupling system for multiscale simulations. In a multiscale simulation, a part of the world is simulated in which multiple processes take place, and where some of those processes are much smaller and/or faster than others.&lt;/p&gt;
&lt;p&gt;In this particular simulation, there are some slow-growing cells (simulated using agents), and some fast-moving blood (simulated using computational fluid dynamics). This is not that relevant, but it is fortunate, because what’s a hard-boiled detective story without some fast-moving blood? Anyway, each process is simulated by a separate computer program, and the programs exchange information by sending messages back and forth. This communication is one of the things MUSCLE3 helps with. And now Pavel was saying that whenever he received a large message, his simulation crashed.&lt;/p&gt;
&lt;p&gt;Messages in MUSCLE3 contain data, and that data can be of a range of types, including the standard built-in types such as strings and integers, but also lists, dictionaries, and grids (arrays) of numbers. You don’t need to tell MUSCLE3 what you’re going to send, you just build a &lt;code&gt;Message&lt;/code&gt; object containing whatever kind of data you want to send, and pass it to MUSCLE3, and on the other side the receiver receives a &lt;code&gt;Message&lt;/code&gt; object containing the same data.&lt;/p&gt;
&lt;p&gt;For a dynamic language like Python, this is all simple enough, but, dear reader, this case would prove to be much more complicated. Pavel’s model was not written in Python. It was written in… &lt;em&gt;DUH-DUH-DUUUUUH&lt;/em&gt; C++!&lt;/p&gt;
&lt;p&gt;See? I told you, sound effects. They make things better.&lt;/p&gt;
&lt;p&gt;Anyway, C++ is a statically typed language. C++ programs are &lt;em&gt;compiled&lt;/em&gt; into an executable file, which is then run in a second step. In C++, each variable can only store values of a particular type (e.g. strings, or integers), and that type must be known when the program is compiled. Of course, we don’t know the type of the data in a message until we receive that message, which happens when the program is running, which comes &lt;em&gt;after&lt;/em&gt; it is compiled. So there is a problem.&lt;/p&gt;
&lt;p&gt;To solve this, the C++ API of MUSCLE3 has a &lt;code&gt;Data&lt;/code&gt; class. Variables of type &lt;code&gt;Data&lt;/code&gt; can contain an object of any type that MUSCLE3 can send and receive. In your C++ code, you can ask the &lt;code&gt;Data&lt;/code&gt; object which type of data it contains, and extract an object of that type. If the data is a grid (for instance because the sender is a Python program that sent you a NumPy array), then you can obtain a pointer to the raw array of elements using the &lt;code&gt;elements()&lt;/code&gt; member function of &lt;code&gt;Data&lt;/code&gt; (C++ doesn’t have a standard multi-dimensional array class, so this is the best we can do).&lt;/p&gt;
&lt;p&gt;That is exactly what Pavel did: he called that function, then copied the elements into another data structure. And then his program crashed. At least, it crashed if the grid was large, a test program receiving a small test grid with only a handful of elements worked fine. Which makes no sense, because MUSCLE3 treats large and small grids exactly the same.&lt;/p&gt;
&lt;p&gt;And thus, our mystery. Why did it crash? Why only for large grids? How should it be fixed? How do we keep this from happening again in the future?&lt;/p&gt;
&lt;h2 id=&quot;detective-its-what-you-are-not-what-you-do&quot;&gt;Detective. It’s what you are, not what you do.&lt;/h2&gt;
&lt;p&gt;It was time to get to work. I collected my hat and put on my trench coat, then dialled in the combination on my wall safe. This job would require some tools. My gaze swept across my collection, carefully assembled over the years. On the left, there were two boxes of print statements. One contained a large pile of cheap plastic mass-produced ones, the other was a velvet-lined display case showcasing a set of two exquisite hand-made examples, made in Japan during the Kamakura period and razor-sharp. While the pride of my collection, and the pinnacle of debugging tools in their time, I would need something more modern for this.&lt;/p&gt;
&lt;p&gt;Next were the linters. They would only protect me from Python formatting issues however. Useless, in this case. A debugger then, maybe? My safe contained a perfectly good copy of gdb, but the truth is that it’s kind of uncomfortable to use. Also, it’s more suited to logic problems than to finding the cause of crashes. I put it aside for now.&lt;/p&gt;
&lt;p&gt;I moved on to a shiny white box. AddressSanitizer it said on the top, in colourful letters. That could work. I’d never liked the sterility of it however. It was too neat, too perfect. A tool of the Empire. No. No, for this job, I would need the final box. A steel chest rather, decorated with ancient runic symbols and adorned with the word &lt;em&gt;Valgrind&lt;/em&gt; in large, Gothic script. Gateway to Valhalla, the great hall where brave programmers go after they retire to await Ragnarök, the end of times when hardware issues and compiler bugs arise for one final epic debugging session before the Great Simulation is rebooted. Yes, Valgrind. I took the chest, put it on my desk, opened it. Removed the gleaming artefact, and put it in my pocket. I was ready to go.&lt;/p&gt;
&lt;p&gt;(If the above procedure sounds a bit over-the-top, &lt;code&gt;apt-get install valgrind&lt;/code&gt; will work just fine as well.)&lt;/p&gt;
&lt;p&gt;It was only a short walk to the site of the crime, a &lt;a href=&quot;https://github.com/multiscale/muscle3&quot;&gt;large building&lt;/a&gt; with the word &lt;code&gt;git&lt;/code&gt; on a sign at the entrance. I walked in and asked the receptionist to see MUSCLE3. She gave me a nasty look. Understandable, given the fact that I look ridiculous in a hat, and that no one has worn a beige trench coat since the 1980’s unless they were a dirty old man. But, having explained that I was in fact a detective, I was waved on and soon found myself in a room with a series of filing cabinets. It was time to start my investigation.&lt;/p&gt;
&lt;p&gt;First, I looked at a cabinet labelled &lt;code&gt;libmuscle/cpp/src/libmuscle/tests&lt;/code&gt;. I knew that there had to be a test which tested that grids could be sent and received. In fact there was; a file conveniently named &lt;code&gt;test_data.cpp&lt;/code&gt; contained a large number of tests for &lt;code&gt;Data&lt;/code&gt; objects, including ones for various aspects of using grids. One of those did exactly what Pavel did. I ran the tests to be sure, and they passed just fine.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;120&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ms)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_serialisation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_serialisation (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;55&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ms)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, the test only used a small grid. I modified it to use a larger grid. Re-ran the tests. And sure enough…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Segmentation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fault (core dumped)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, I had verified that indeed there had been a crime, erm, that there was a mistake in my code. But where? It was time to deploy Valgrind. I modified the &lt;code&gt;Makefile&lt;/code&gt; that runs the tests to run &lt;code&gt;valgrind &amp;#x3C;test_executable&gt;&lt;/code&gt; instead of just &lt;code&gt;&amp;#x3C;test_executable&gt;&lt;/code&gt;. Having thus installed the Valgrind onto the filing cabinet, I took cover behind another cabinet filled with Fortran code (heavy, voluminous, and in this case auto-generated and therefore expendable) and restarted the test suite.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;An arch-shaped angular metal object with a letter V and two viking heads on it sits on top of a wooden cabinet.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_oGKL4SYDYiHd9ggSmp_mpw-7c311286.ChVArLxo_ZqH1yL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Valgrind in action&lt;/p&gt;
&lt;p&gt;As the first tests ran, a bluish light filled the room and the ancient artefact started vibrating, emitting a faint hum of approval. Then, suddenly, a horrifying screech emanated from it.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Invalid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; read &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13F848&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::CmpHelperEQ&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1444&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1368DF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::EqHelper&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::Compare&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1472&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1288B1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle_mcp_data_grid_Test&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestBody&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (test_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;526&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1A21E6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleSehExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x19C810&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x17BBBB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x17C518&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestInfo::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x17CB9B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestCase::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x187987&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl::RunAllTests&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1A32F8&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bool testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleSehExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x19D576&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bool testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x18640F&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTest::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Address&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0x6488628&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bytes inside a block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;262&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;152&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x4C30D3B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valgrind&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vgpreload_memcheck&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;amd64&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;linux&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13317B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chunk_list&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chunk_list&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;127&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13554D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x152D7D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void __gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;new_allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (new_allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;140&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x152D50&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator_traits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (alloc_traits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;487&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1520AA&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Sp_counted_ptr_inplace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone, std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_M_dispose&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;535&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13A385&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Sp_counted_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_M_release&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;154&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x135CCC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_count&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;684&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1345AF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone, (__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1123&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1345CB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;93&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x14E99D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (stl_construct&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;98&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x14DE43&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Destroy_aux&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (stl_construct&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;108&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; was alloc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x4C2FB0F&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; malloc (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valgrind&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vgpreload_memcheck&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;amd64&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;linux&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13335A&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocate_expand(unsigned long) (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;281&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x133280&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocate_align(unsigned long, unsigned long) (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;245&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x157F74&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;visit_bin(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned int) (create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;133&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x165DC3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_helper&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;execute(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (parse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;584&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x162A3D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_helper&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;execute(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (parse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1027&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x160F33&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_return msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_imp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (parse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1044&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1587F5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_imp(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object_type, unsigned long, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_limit const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (unpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;331&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x16C6BE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object_type, unsigned long, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_limit const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (unpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;141&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x16C766&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, bool (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object_type, unsigned long, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_limit const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (unpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;182&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x16C5D8&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_data(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long) (data_pack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1563C4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::DataConstRef::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const (data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;722&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It ended quickly, fortunately, and was replaced again by the soothing hum. When that too had faded away, I emerged from my shelter and approached the filing cabinet. The Valgrind felt warm to the touch, but it appeared to be intact. I took out my magnifying glass and inspected the symbols on its side.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Invalid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; read &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13F848&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::CmpHelperEQ&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1444&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1368DF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::EqHelper&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::Compare&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1472&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1288B1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle_mcp_data_grid_Test&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestBody&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (test_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;526&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Invalid read of size 4. Apparently, the test had attempted to read a 4-byte variable in a memory location where there was none. I followed the backtrace, through some Google Test-related functions to my &lt;code&gt;test_data.cpp&lt;/code&gt;. Line 526 was where the invalid read had occurred. I checked the test’s code. Bingo. Exactly the place where the grid elements were accessed. I seemed to be on to something.&lt;/p&gt;
&lt;p&gt;At this point, there were several possible causes of the crash. Clearly, the pointer returned by the call to &lt;code&gt;elements()&lt;/code&gt; was bad, pointing to some memory that did not contain the requested elements. I read on.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Address&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0x6488628&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bytes inside a block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;262&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;152&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; was alloc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1563C4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::DataConstRef::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const (data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;722&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That, in fact, told me enough to find the problem. But to understand what went wrong, we need to dive into the implementation of the &lt;code&gt;Data&lt;/code&gt; class for a bit.&lt;/p&gt;
&lt;h2 id=&quot;how-to-lose-your-users-data&quot;&gt;How to lose your users’ data&lt;/h2&gt;
&lt;p&gt;To send objects from one program to another, MUSCLE3 uses a binary data format called MessagePack. A MessagePack-encoded object is an array of bytes, which can be decoded to determine the type and value of the encoded value. For example, a message consisting of a single byte with value &lt;code&gt;33&lt;/code&gt; represents an integer with value 33. A single byte with value &lt;code&gt;195&lt;/code&gt; represents the Boolean value True, and &lt;code&gt;167 77 85 83 67 76 69 51&lt;/code&gt; encodes the string MUSCLE3 (167 starts a 7-byte string, and then there are the 7 characters’ ASCII values).&lt;/p&gt;
&lt;p&gt;MessagePack has fixed ways of encoding all the common basic types, as well as dictionaries and lists, but it doesn’t do (multidimensional) arrays. Fortunately, it has an extension mechanism, which lets you send an array of bytes accompanied by a one-byte tag that specifies what kind of object it represents. You are then free to represent your object as an array of bytes in any way you like. A common trick is to simply use MessagePack again to encode a dictionary or list containing some values which together represent the object. This is how MUSCLE3 sends grids.&lt;/p&gt;
&lt;p&gt;When MUSCLE3 receives a message, it calls an internal function to decode the received array of bytes. This function in turn calls the MessagePack library, which returns a library-specific object that represents the decoded value. This object is wrapped in a &lt;code&gt;Data&lt;/code&gt; object, and eventually returned to the user. When the user then asks this &lt;code&gt;Data&lt;/code&gt; object whether it contains a &lt;code&gt;Grid&lt;/code&gt;, it inspects its MessagePack-object to see whether it represents an extension type with the correct tag. If you ask for the elements, it has to actually decode the bytes still. It uses MessagePack to do that, creating another &lt;code&gt;Data&lt;/code&gt; object containing a dictionary that has the shape of the array and the elements (the difference between &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;DataConstRef&lt;/code&gt; is beyond the scope of this blog, you can consider them the same here).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    auto ext &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mp_obj_&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    auto oh &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack(ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (oh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::MAP&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        throw std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;runtime_error(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;Invalid grid format. Bug in MUSCLE 3?&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);    auto zone &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;make_shared&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        mcp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_data(zone, ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once it has this &lt;code&gt;Data&lt;/code&gt; object, &lt;code&gt;elements()&lt;/code&gt; can extract the location of the elements from it and return the location to the user as a pointer of the appropriate type:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elements&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_a_grid_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        throw std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;runtime_error(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;Tried to get grid data, but this object is not&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot; a grid or not of the correct type.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    char const &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data_bytes &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;as_byte_array&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return reinterpret_cast&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(data_bytes);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Valgrind said the following about this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Address&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0x6488628&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bytes inside a block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;262&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;152&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; was alloc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1563C4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::DataConstRef::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const (data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;722&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that the pointer returned by &lt;code&gt;elements()&lt;/code&gt; points to a variable that used to exist, but that had been deleted by the time the pointer was used by the test case. It also says that the deleted variable was created on the last line of the &lt;code&gt;grid_dict_()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;That makes it clear what happened: &lt;code&gt;elements()&lt;/code&gt; calls &lt;code&gt;grid_dict_()&lt;/code&gt;, which creates (as noted by Valgrind) and returns a &lt;code&gt;Data&lt;/code&gt; object containing the elements. A pointer to the elements is extracted (the &lt;code&gt;[&quot;data&quot;].as_byte_array()&lt;/code&gt; part in &lt;code&gt;elements()&lt;/code&gt;), and then, since it’s a temporary value and it’s not assigned to anything, the &lt;code&gt;Data&lt;/code&gt; object returned by &lt;code&gt;grid_dict_()&lt;/code&gt; is cleaned up. This deletes the dictionary including the elements from memory, leaving the pointer to point to something which no longer exists. The pointer is then returned to the user, who tries to access the nonexistent data, causing the program to crash (or not, sometimes).&lt;/p&gt;
&lt;p&gt;Accessing a variable which no longer exists is called a &lt;em&gt;use after free&lt;/em&gt; error and it can, but doesn’t have to, crash your program. Here’s why. The memory in your computer is divided up into blocks called segments, and each running program is assigned a data segment to work with. If it needs more memory, it can &lt;a href=&quot;https://linux.die.net/man/2/sbrk&quot;&gt;ask the operating system to increase the size of its data segment&lt;/a&gt;, and if it doesn’t need the extra memory any more, it can ask to shrink its data segment again so that other running programs can use the memory. If a program tries to read or write to memory outside of a segment assigned to it, the CPU will block the operation and then the operating system will shut down the program, citing a &lt;em&gt;segmentation fault&lt;/em&gt; or &lt;em&gt;segmentation violation&lt;/em&gt; (colloquially, a &lt;em&gt;segfault&lt;/em&gt;). It does this to protect other running programs, which would get messed up if their data is overwritten by their errant colleague.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8SlZc56wbJqiw0AZmh0o_A-e222a716.Dh7zCyxb_Z2jK80M.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An errant colleague trying to overwrite your data. At this point you may want to call a detective! Photo by Andrea Piacquadio from Pexels.&lt;/p&gt;
&lt;p&gt;Resizing the data segment is done by the C++ standard library behind the scenes, so you don’t have to do it by hand, you can just &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; variables (or better, use &lt;code&gt;std::make_unique()&lt;/code&gt; and &lt;code&gt;std::make_shared()&lt;/code&gt;). The standard library typically doesn’t change the size of the data segment every time you create or delete a variable, as it’s quite expensive to do so. It’s quite common for programs to create and delete small variables all the time, so it makes sense to hold on to a bit of spare memory. However, if a large enough amount is freed, it should be given back to the operating system for use by someone else, so that’s what the standard library typically does.&lt;/p&gt;
&lt;p&gt;This is probably the explanation for why the test only crashes if the test grid is large: the small grid is still inside our data segment, and although its memory has been marked as available, it hasn’t been overwritten or returned to the OS, so that the pointer returned by &lt;code&gt;elements()&lt;/code&gt; still works even if it’s technically invalid. The segment checking system is not intended to detect mistakes inside a program like this, it’s just there to protect programs from each other. So we get away with it, and the test passes. For the larger grid, the memory has been returned to the OS, so it does trigger a segfault, but it’s somewhat accidental.&lt;/p&gt;
&lt;p&gt;When you run a program with Valgrind’s memcheck (which is what we did here), it actually redirects the calls to create, delete and access variables that the program makes away from the standard library, and to its memcheck tool. This does a lot of extra checking and bookkeeping, allowing it to detect invalid accesses within the program and tell you what happened. All these extra checks do slow down your program a lot, so you don’t want to run under Valgrind all the time, but when you have an issue like this, it’s well worth a bit of a wait if needed. As we saw above, it does a pretty good job showing what’s going wrong, and it’s not so easy to find these kinds of mistakes with other tools.&lt;/p&gt;
&lt;h2 id=&quot;fixing-the-problem&quot;&gt;Fixing the problem&lt;/h2&gt;
&lt;p&gt;Satisfied with these results, I removed the Valgrind from the test cabinet and returned it to my coat pocket. It had proven its worth once again. I wasn’t done however, as the mistake still needed to be rectified. I pulled up a chair to another filing cabinet, this one labeled &lt;code&gt;libmuscle/cpp/src/libmuscle&lt;/code&gt;, and pulled up the &lt;code&gt;data.cpp&lt;/code&gt; file to consider my options.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;Data&lt;/code&gt; object actually contains two things: the MessagePack object representing the data, and a MessagePack &lt;em&gt;zone&lt;/em&gt; object. Zones are used by MessagePack to manage memory. If you decode, say, a dictionary, then you get MessagePack objects for the dictionary itself, and also for each key and value, recursively. That’s a lot of objects, so MessagePack puts them all together into a zone. When you’re done with the data, you just delete the zone, cleaning them all up in one go. This is not as easy as automatic memory management, but it is much more efficient.&lt;/p&gt;
&lt;p&gt;Now, our problem is that we create a second &lt;code&gt;Data&lt;/code&gt; object containing the grid dictionary, and that we need to put it somewhere where it will continue to exist for as long as the user accesses the pointer returned by &lt;code&gt;elements()&lt;/code&gt;. MUSCLE3 promises the user that that pointer is valid for as long as the &lt;code&gt;Data&lt;/code&gt; object representing the grid exists, so we need to somehow attach the decoded elements to the grid’s &lt;code&gt;Data&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;One option is to put the elements in the main &lt;code&gt;Data&lt;/code&gt; object’s zone. That will keep them around, but it becomes an issue if the user calls &lt;code&gt;elements()&lt;/code&gt; multiple times, maybe in a loop. On every call, a new &lt;code&gt;Data&lt;/code&gt; object will be created for the dictionary and added to the zone, so we keep using more and more memory. It’ll eventually be freed again, but if it’s a large grid, then we may run out of memory before that. So that’s not great.&lt;/p&gt;
&lt;p&gt;A second option would be to add a pointer-to- &lt;code&gt;Data&lt;/code&gt; to the &lt;code&gt;Data&lt;/code&gt; class, which could be used to store the dictionary &lt;code&gt;Data&lt;/code&gt; object if the &lt;code&gt;Data&lt;/code&gt; object represents a grid. That way, we would only have to decode once, and any subsequent calls to &lt;code&gt;elements()&lt;/code&gt; or &lt;code&gt;shape()&lt;/code&gt; could used the cached object. And using a smart pointer would automatically delete the dictionary &lt;code&gt;Data&lt;/code&gt; object when the grid &lt;code&gt;Data&lt;/code&gt; object is deleted. The downside to this is that it makes &lt;code&gt;Data&lt;/code&gt; objects larger, which could cost some performance even for &lt;code&gt;Data&lt;/code&gt; objects that don’t contain a grid.&lt;/p&gt;
&lt;p&gt;Finally, since the MessagePack format is not so complicated, it would also be possible to make custom decoding routines which decode the grid in one stage, so that there is no need for a second &lt;code&gt;Data&lt;/code&gt; object at all. This could also help to reduce copying, thus improving performance further. That’s a lot of work however.&lt;/p&gt;
&lt;p&gt;At the moment, the focus for MUSCLE3 is on making things work, and on making the life of the users easy. Performance is not crucial, because in multiscale models (unlike in scale-overlapping multiphysics models) communication performance is rarely the bottleneck. I want to spend my time on solving problems for users, but not problems they don’t have. Since the first option could actually make things worse, and the third option is expensive, &lt;a href=&quot;https://github.com/multiscale/muscle3/commit/281c75b8907da5b2d5150c36472705e0916cc2bd&quot;&gt;I chose the second option&lt;/a&gt;. It’s not the prettiest solution, but it will do. If performance does become an issue in the future, then I can always come back and revisit.&lt;/p&gt;
&lt;p&gt;Having fixed the problem, there was one more thing to do: keep similar problems from appearing in the future. Mistakes in software are inevitable, as it’s made by humans and nobody’s perfect. But whenever we discover a mistake, it helps to see if there’s an easy way to avoid doing the same thing in the future, so that over time the software gets better and better. In this case, I added a check for Valgrind to the build system, and it will now run all the tests under Valgrind if it is installed. I also modified the continuous integration container to install Valgrind. This didn’t uncover any other memory management issues in MUSCLE3, but if I make another mistake like this in the future, then there’s a good chance that the tooling will catch it before it ends up with the users.&lt;/p&gt;
&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;My job done, it was time to go home. I grabbed my coat and my hat, verified that the Valgrind was still securely in my pocket, turned off the lights, and carefully closed the door behind me. It was late. The hallways were deserted, the reception desk downstairs vacant. I opened the after-hours side door and stepped out onto the street, into the golden light of a beautiful spring evening. Life was good. I turned towards home, pulled my hat a bit deeper over my eyes to keep the sun out, and started walking, detective-at-ease. I ignored the funny looks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_nAya0dMSUBd58C_5c8ML_g-e8f5424d.CY8gRSSn_Z1l8tn9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Dewang Gupta on Unsplash&lt;/p&gt;</description><pubDate>Mon, 28 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In my long career as a code detective, I have seen it all. I have travelled the high Cs, found Rubies and wrestled Pythons, and walked the alleyways of Fortran at night. Of course, as with any job most cases are run-of-the-mill, but some of them are not. Those are the ones you remember. The ones you tell your grandchildren about, if you live to tell the tale.&lt;/p&gt;
&lt;p&gt;This is the story of a programming mistake that caused a C++ program to crash, and how it was fixed using &lt;a href=&quot;https://valgrind.org/&quot;&gt;Valgrind&lt;/a&gt;. It features mysterious artefacts, C++ memory management, and fixing and avoiding mistakes in (scientific) software. I hope it will teach you something about use-after-free issues, and inspire you to try Valgrind for memory debugging next time you have a similar problem. Let’s dive right in, shall we?&lt;/p&gt;
&lt;h2 id=&quot;the-curious-case-of-the-crashing-simulation&quot;&gt;The Curious Case of the Crashing Simulation&lt;/h2&gt;
&lt;p&gt;It was a dark and stormy ni…no wait, it was actually a sunny afternoon in spring, when I received an email from a scientist named Pavel. Pavel is a postdoc at the University of Amsterdam and the Erasmus University Medical Center in Rotterdam, and he was working on porting a rather complicated computer simulation of something called an &lt;a href=&quot;https://en.wikipedia.org/wiki/Restenosis&quot;&gt;In-Stent Restenosis&lt;/a&gt; to &lt;a href=&quot;https://github.com/multiscale/muscle3&quot;&gt;MUSCLE3&lt;/a&gt;. His program was crashing. And he suspected the problem was with MUSCLE3. Which I created and currently maintain. Which would mean… &lt;em&gt;DUH-DUH-DUUUUUH&lt;/em&gt; (organ sound effect) &lt;em&gt;THERE WAS A MISTAKE IN MY CODE&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;By the way, why can’t you include sound effects in blog posts? I think blog posts are much better with sound effects. Someone should fix this. Meanwhile, here’s an image depicting the horror:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;An ink drawing of a face with its eyes and mouth wide open in horror. It is flanked by raised arms on both sides.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;982&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_g4Uw0OcyPSJMyeKP-89e7e8c7.D3nu8NeI_ZgkqUt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“The Scream” Undated drawing by Edvard Munch (via Wikipedia )&lt;/p&gt;
&lt;p&gt;Anyway, yes, there was a mistake in MUSCLE3. But to explain the problem, I need to explain what MUSCLE3 does first. MUSCLE3 is a coupling system for multiscale simulations. In a multiscale simulation, a part of the world is simulated in which multiple processes take place, and where some of those processes are much smaller and/or faster than others.&lt;/p&gt;
&lt;p&gt;In this particular simulation, there are some slow-growing cells (simulated using agents), and some fast-moving blood (simulated using computational fluid dynamics). This is not that relevant, but it is fortunate, because what’s a hard-boiled detective story without some fast-moving blood? Anyway, each process is simulated by a separate computer program, and the programs exchange information by sending messages back and forth. This communication is one of the things MUSCLE3 helps with. And now Pavel was saying that whenever he received a large message, his simulation crashed.&lt;/p&gt;
&lt;p&gt;Messages in MUSCLE3 contain data, and that data can be of a range of types, including the standard built-in types such as strings and integers, but also lists, dictionaries, and grids (arrays) of numbers. You don’t need to tell MUSCLE3 what you’re going to send, you just build a &lt;code&gt;Message&lt;/code&gt; object containing whatever kind of data you want to send, and pass it to MUSCLE3, and on the other side the receiver receives a &lt;code&gt;Message&lt;/code&gt; object containing the same data.&lt;/p&gt;
&lt;p&gt;For a dynamic language like Python, this is all simple enough, but, dear reader, this case would prove to be much more complicated. Pavel’s model was not written in Python. It was written in… &lt;em&gt;DUH-DUH-DUUUUUH&lt;/em&gt; C++!&lt;/p&gt;
&lt;p&gt;See? I told you, sound effects. They make things better.&lt;/p&gt;
&lt;p&gt;Anyway, C++ is a statically typed language. C++ programs are &lt;em&gt;compiled&lt;/em&gt; into an executable file, which is then run in a second step. In C++, each variable can only store values of a particular type (e.g. strings, or integers), and that type must be known when the program is compiled. Of course, we don’t know the type of the data in a message until we receive that message, which happens when the program is running, which comes &lt;em&gt;after&lt;/em&gt; it is compiled. So there is a problem.&lt;/p&gt;
&lt;p&gt;To solve this, the C++ API of MUSCLE3 has a &lt;code&gt;Data&lt;/code&gt; class. Variables of type &lt;code&gt;Data&lt;/code&gt; can contain an object of any type that MUSCLE3 can send and receive. In your C++ code, you can ask the &lt;code&gt;Data&lt;/code&gt; object which type of data it contains, and extract an object of that type. If the data is a grid (for instance because the sender is a Python program that sent you a NumPy array), then you can obtain a pointer to the raw array of elements using the &lt;code&gt;elements()&lt;/code&gt; member function of &lt;code&gt;Data&lt;/code&gt; (C++ doesn’t have a standard multi-dimensional array class, so this is the best we can do).&lt;/p&gt;
&lt;p&gt;That is exactly what Pavel did: he called that function, then copied the elements into another data structure. And then his program crashed. At least, it crashed if the grid was large, a test program receiving a small test grid with only a handful of elements worked fine. Which makes no sense, because MUSCLE3 treats large and small grids exactly the same.&lt;/p&gt;
&lt;p&gt;And thus, our mystery. Why did it crash? Why only for large grids? How should it be fixed? How do we keep this from happening again in the future?&lt;/p&gt;
&lt;h2 id=&quot;detective-its-what-you-are-not-what-you-do&quot;&gt;Detective. It’s what you are, not what you do.&lt;/h2&gt;
&lt;p&gt;It was time to get to work. I collected my hat and put on my trench coat, then dialled in the combination on my wall safe. This job would require some tools. My gaze swept across my collection, carefully assembled over the years. On the left, there were two boxes of print statements. One contained a large pile of cheap plastic mass-produced ones, the other was a velvet-lined display case showcasing a set of two exquisite hand-made examples, made in Japan during the Kamakura period and razor-sharp. While the pride of my collection, and the pinnacle of debugging tools in their time, I would need something more modern for this.&lt;/p&gt;
&lt;p&gt;Next were the linters. They would only protect me from Python formatting issues however. Useless, in this case. A debugger then, maybe? My safe contained a perfectly good copy of gdb, but the truth is that it’s kind of uncomfortable to use. Also, it’s more suited to logic problems than to finding the cause of crashes. I put it aside for now.&lt;/p&gt;
&lt;p&gt;I moved on to a shiny white box. AddressSanitizer it said on the top, in colourful letters. That could work. I’d never liked the sterility of it however. It was too neat, too perfect. A tool of the Empire. No. No, for this job, I would need the final box. A steel chest rather, decorated with ancient runic symbols and adorned with the word &lt;em&gt;Valgrind&lt;/em&gt; in large, Gothic script. Gateway to Valhalla, the great hall where brave programmers go after they retire to await Ragnarök, the end of times when hardware issues and compiler bugs arise for one final epic debugging session before the Great Simulation is rebooted. Yes, Valgrind. I took the chest, put it on my desk, opened it. Removed the gleaming artefact, and put it in my pocket. I was ready to go.&lt;/p&gt;
&lt;p&gt;(If the above procedure sounds a bit over-the-top, &lt;code&gt;apt-get install valgrind&lt;/code&gt; will work just fine as well.)&lt;/p&gt;
&lt;p&gt;It was only a short walk to the site of the crime, a &lt;a href=&quot;https://github.com/multiscale/muscle3&quot;&gt;large building&lt;/a&gt; with the word &lt;code&gt;git&lt;/code&gt; on a sign at the entrance. I walked in and asked the receptionist to see MUSCLE3. She gave me a nasty look. Understandable, given the fact that I look ridiculous in a hat, and that no one has worn a beige trench coat since the 1980’s unless they were a dirty old man. But, having explained that I was in fact a detective, I was waved on and soon found myself in a room with a series of filing cabinets. It was time to start my investigation.&lt;/p&gt;
&lt;p&gt;First, I looked at a cabinet labelled &lt;code&gt;libmuscle/cpp/src/libmuscle/tests&lt;/code&gt;. I knew that there had to be a test which tested that grids could be sent and received. In fact there was; a file conveniently named &lt;code&gt;test_data.cpp&lt;/code&gt; contained a large number of tests for &lt;code&gt;Data&lt;/code&gt; objects, including ones for various aspects of using grids. One of those did exactly what Pavel did. I ran the tests to be sure, and they passed just fine.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;120&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ms)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_serialisation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OK&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_serialisation (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;55&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ms)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, the test only used a small grid. I modified it to use a larger grid. Re-ran the tests. And sure enough…&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Segmentation&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fault (core dumped)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, I had verified that indeed there had been a crime, erm, that there was a mistake in my code. But where? It was time to deploy Valgrind. I modified the &lt;code&gt;Makefile&lt;/code&gt; that runs the tests to run &lt;code&gt;valgrind &amp;#x3C;test_executable&gt;&lt;/code&gt; instead of just &lt;code&gt;&amp;#x3C;test_executable&gt;&lt;/code&gt;. Having thus installed the Valgrind onto the filing cabinet, I took cover behind another cabinet filled with Fortran code (heavy, voluminous, and in this case auto-generated and therefore expendable) and restarted the test suite.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;An arch-shaped angular metal object with a letter V and two viking heads on it sits on top of a wooden cabinet.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_oGKL4SYDYiHd9ggSmp_mpw-7c311286.ChVArLxo_ZqH1yL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Valgrind in action&lt;/p&gt;
&lt;p&gt;As the first tests ran, a bluish light filled the room and the ancient artefact started vibrating, emitting a faint hum of approval. Then, suddenly, a horrifying screech emanated from it.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Invalid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; read &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13F848&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::CmpHelperEQ&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1444&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1368DF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::EqHelper&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::Compare&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1472&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1288B1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle_mcp_data_grid_Test&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestBody&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (test_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;526&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1A21E6&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleSehExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x19C810&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, void (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x17BBBB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::Test::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x17C518&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestInfo::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x17CB9B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestCase::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x187987&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl::RunAllTests&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1A32F8&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bool testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleSehExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x19D576&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bool testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::HandleExceptionsInMethodIfSupported&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTestImpl::*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x18640F&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::UnitTest::Run&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (in muscle3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;tests&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;test_data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Address&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0x6488628&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bytes inside a block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;262&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;152&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x4C30D3B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valgrind&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vgpreload_memcheck&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;amd64&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;linux&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13317B&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chunk_list&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chunk_list&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;127&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13554D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x152D7D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void __gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;new_allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (new_allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;140&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x152D50&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator_traits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (alloc_traits&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;487&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1520AA&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Sp_counted_ptr_inplace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone, std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, (__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_M_dispose&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;535&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13A385&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Sp_counted_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_M_release&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;154&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x135CCC&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_count&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_count&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;684&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1345AF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone, (__gnu_cxx&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Lock_policy)&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr_base&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1123&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1345CB&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::~&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;93&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x14E99D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (stl_construct&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;98&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x14DE43&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; void std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;_Destroy_aux&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;__destroy&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (stl_construct&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;108&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; was alloc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x4C2FB0F&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; malloc (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;valgrind&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;vgpreload_memcheck&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;amd64&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;linux&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;so)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13335A&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocate_expand(unsigned long) (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;281&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x133280&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;allocate_align(unsigned long, unsigned long) (cpp11_zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;245&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x157F74&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;visit_bin(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned int) (create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;133&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x165DC3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;context&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_helper&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;execute(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (parse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;584&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x162A3D&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_helper&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;execute(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (parse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1027&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x160F33&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_return msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse_imp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;create_object_visitor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (parse&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1044&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1587F5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_imp(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object_type, unsigned long, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_limit const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (unpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;331&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x16C6BE&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, unsigned long&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, bool (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object_type, unsigned long, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_limit const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (unpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;141&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x16C766&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long, bool (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)(msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;object_type, unsigned long, void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;), void&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_limit const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (unpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;182&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x16C5D8&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;mcp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_data(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;shared_ptr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, unsigned long) (data_pack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;13&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1563C4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::DataConstRef::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const (data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;722&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It ended quickly, fortunately, and was replaced again by the soothing hum. When that too had faded away, I emerged from my shelter and approached the filing cabinet. The Valgrind felt warm to the touch, but it appeared to be intact. I took out my magnifying glass and inspected the symbols on its side.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[ &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ] libmuscle_mcp_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Invalid&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; read &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; at &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x13F848&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::CmpHelperEQ&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1444&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1368DF&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::AssertionResult&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; testing&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::EqHelper&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::Compare&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;int, int&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, char const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, int const&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) (gtest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1472&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1288B1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle_mcp_data_grid_Test&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::TestBody&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (test_data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;526&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Invalid read of size 4. Apparently, the test had attempted to read a 4-byte variable in a memory location where there was none. I followed the backtrace, through some Google Test-related functions to my &lt;code&gt;test_data.cpp&lt;/code&gt;. Line 526 was where the invalid read had occurred. I checked the test’s code. Bingo. Exactly the place where the grid elements were accessed. I seemed to be on to something.&lt;/p&gt;
&lt;p&gt;At this point, there were several possible causes of the crash. Clearly, the pointer returned by the call to &lt;code&gt;elements()&lt;/code&gt; was bad, pointing to some memory that did not contain the requested elements. I read on.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Address&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0x6488628&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bytes inside a block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;262&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;152&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; was alloc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1563C4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::DataConstRef::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const (data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;722&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That, in fact, told me enough to find the problem. But to understand what went wrong, we need to dive into the implementation of the &lt;code&gt;Data&lt;/code&gt; class for a bit.&lt;/p&gt;
&lt;h2 id=&quot;how-to-lose-your-users-data&quot;&gt;How to lose your users’ data&lt;/h2&gt;
&lt;p&gt;To send objects from one program to another, MUSCLE3 uses a binary data format called MessagePack. A MessagePack-encoded object is an array of bytes, which can be decoded to determine the type and value of the encoded value. For example, a message consisting of a single byte with value &lt;code&gt;33&lt;/code&gt; represents an integer with value 33. A single byte with value &lt;code&gt;195&lt;/code&gt; represents the Boolean value True, and &lt;code&gt;167 77 85 83 67 76 69 51&lt;/code&gt; encodes the string MUSCLE3 (167 starts a 7-byte string, and then there are the 7 characters’ ASCII values).&lt;/p&gt;
&lt;p&gt;MessagePack has fixed ways of encoding all the common basic types, as well as dictionaries and lists, but it doesn’t do (multidimensional) arrays. Fortunately, it has an extension mechanism, which lets you send an array of bytes accompanied by a one-byte tag that specifies what kind of object it represents. You are then free to represent your object as an array of bytes in any way you like. A common trick is to simply use MessagePack again to encode a dictionary or list containing some values which together represent the object. This is how MUSCLE3 sends grids.&lt;/p&gt;
&lt;p&gt;When MUSCLE3 receives a message, it calls an internal function to decode the received array of bytes. This function in turn calls the MessagePack library, which returns a library-specific object that represents the decoded value. This object is wrapped in a &lt;code&gt;Data&lt;/code&gt; object, and eventually returned to the user. When the user then asks this &lt;code&gt;Data&lt;/code&gt; object whether it contains a &lt;code&gt;Grid&lt;/code&gt;, it inspects its MessagePack-object to see whether it represents an extension type with the correct tag. If you ask for the elements, it has to actually decode the bytes still. It uses MessagePack to do that, creating another &lt;code&gt;Data&lt;/code&gt; object containing a dictionary that has the shape of the array and the elements (the difference between &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;DataConstRef&lt;/code&gt; is beyond the scope of this blog, you can consider them the same here).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    auto ext &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mp_obj_&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    auto oh &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack(ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);    &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (oh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::MAP&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        throw std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;runtime_error(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;Invalid grid format. Bug in MUSCLE 3?&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);    auto zone &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;make_shared&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;msgpack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;zone&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;        mcp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unpack_data(zone, ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, ext&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once it has this &lt;code&gt;Data&lt;/code&gt; object, &lt;code&gt;elements()&lt;/code&gt; can extract the location of the elements from it and return the location to the user as a pointer of the appropriate type:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DataConstRef&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elements&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_a_grid_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        throw std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;runtime_error(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot;Tried to get grid data, but this object is not&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;            &quot; a grid or not of the correct type.&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    char const &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data_bytes &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;as_byte_array&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    return reinterpret_cast&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Element&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(data_bytes);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Valgrind said the following about this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Address&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0x6488628&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bytes inside a block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; size &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;262&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;152&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; free&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Block&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; was alloc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d at&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; by &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0x1563C4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; libmuscle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::DataConstRef::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;grid_dict_&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const (data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;722&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19383&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means that the pointer returned by &lt;code&gt;elements()&lt;/code&gt; points to a variable that used to exist, but that had been deleted by the time the pointer was used by the test case. It also says that the deleted variable was created on the last line of the &lt;code&gt;grid_dict_()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;That makes it clear what happened: &lt;code&gt;elements()&lt;/code&gt; calls &lt;code&gt;grid_dict_()&lt;/code&gt;, which creates (as noted by Valgrind) and returns a &lt;code&gt;Data&lt;/code&gt; object containing the elements. A pointer to the elements is extracted (the &lt;code&gt;[&quot;data&quot;].as_byte_array()&lt;/code&gt; part in &lt;code&gt;elements()&lt;/code&gt;), and then, since it’s a temporary value and it’s not assigned to anything, the &lt;code&gt;Data&lt;/code&gt; object returned by &lt;code&gt;grid_dict_()&lt;/code&gt; is cleaned up. This deletes the dictionary including the elements from memory, leaving the pointer to point to something which no longer exists. The pointer is then returned to the user, who tries to access the nonexistent data, causing the program to crash (or not, sometimes).&lt;/p&gt;
&lt;p&gt;Accessing a variable which no longer exists is called a &lt;em&gt;use after free&lt;/em&gt; error and it can, but doesn’t have to, crash your program. Here’s why. The memory in your computer is divided up into blocks called segments, and each running program is assigned a data segment to work with. If it needs more memory, it can &lt;a href=&quot;https://linux.die.net/man/2/sbrk&quot;&gt;ask the operating system to increase the size of its data segment&lt;/a&gt;, and if it doesn’t need the extra memory any more, it can ask to shrink its data segment again so that other running programs can use the memory. If a program tries to read or write to memory outside of a segment assigned to it, the CPU will block the operation and then the operating system will shut down the program, citing a &lt;em&gt;segmentation fault&lt;/em&gt; or &lt;em&gt;segmentation violation&lt;/em&gt; (colloquially, a &lt;em&gt;segfault&lt;/em&gt;). It does this to protect other running programs, which would get messed up if their data is overwritten by their errant colleague.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8SlZc56wbJqiw0AZmh0o_A-e222a716.Dh7zCyxb_Z2jK80M.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An errant colleague trying to overwrite your data. At this point you may want to call a detective! Photo by Andrea Piacquadio from Pexels.&lt;/p&gt;
&lt;p&gt;Resizing the data segment is done by the C++ standard library behind the scenes, so you don’t have to do it by hand, you can just &lt;code&gt;new&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; variables (or better, use &lt;code&gt;std::make_unique()&lt;/code&gt; and &lt;code&gt;std::make_shared()&lt;/code&gt;). The standard library typically doesn’t change the size of the data segment every time you create or delete a variable, as it’s quite expensive to do so. It’s quite common for programs to create and delete small variables all the time, so it makes sense to hold on to a bit of spare memory. However, if a large enough amount is freed, it should be given back to the operating system for use by someone else, so that’s what the standard library typically does.&lt;/p&gt;
&lt;p&gt;This is probably the explanation for why the test only crashes if the test grid is large: the small grid is still inside our data segment, and although its memory has been marked as available, it hasn’t been overwritten or returned to the OS, so that the pointer returned by &lt;code&gt;elements()&lt;/code&gt; still works even if it’s technically invalid. The segment checking system is not intended to detect mistakes inside a program like this, it’s just there to protect programs from each other. So we get away with it, and the test passes. For the larger grid, the memory has been returned to the OS, so it does trigger a segfault, but it’s somewhat accidental.&lt;/p&gt;
&lt;p&gt;When you run a program with Valgrind’s memcheck (which is what we did here), it actually redirects the calls to create, delete and access variables that the program makes away from the standard library, and to its memcheck tool. This does a lot of extra checking and bookkeeping, allowing it to detect invalid accesses within the program and tell you what happened. All these extra checks do slow down your program a lot, so you don’t want to run under Valgrind all the time, but when you have an issue like this, it’s well worth a bit of a wait if needed. As we saw above, it does a pretty good job showing what’s going wrong, and it’s not so easy to find these kinds of mistakes with other tools.&lt;/p&gt;
&lt;h2 id=&quot;fixing-the-problem&quot;&gt;Fixing the problem&lt;/h2&gt;
&lt;p&gt;Satisfied with these results, I removed the Valgrind from the test cabinet and returned it to my coat pocket. It had proven its worth once again. I wasn’t done however, as the mistake still needed to be rectified. I pulled up a chair to another filing cabinet, this one labeled &lt;code&gt;libmuscle/cpp/src/libmuscle&lt;/code&gt;, and pulled up the &lt;code&gt;data.cpp&lt;/code&gt; file to consider my options.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;Data&lt;/code&gt; object actually contains two things: the MessagePack object representing the data, and a MessagePack &lt;em&gt;zone&lt;/em&gt; object. Zones are used by MessagePack to manage memory. If you decode, say, a dictionary, then you get MessagePack objects for the dictionary itself, and also for each key and value, recursively. That’s a lot of objects, so MessagePack puts them all together into a zone. When you’re done with the data, you just delete the zone, cleaning them all up in one go. This is not as easy as automatic memory management, but it is much more efficient.&lt;/p&gt;
&lt;p&gt;Now, our problem is that we create a second &lt;code&gt;Data&lt;/code&gt; object containing the grid dictionary, and that we need to put it somewhere where it will continue to exist for as long as the user accesses the pointer returned by &lt;code&gt;elements()&lt;/code&gt;. MUSCLE3 promises the user that that pointer is valid for as long as the &lt;code&gt;Data&lt;/code&gt; object representing the grid exists, so we need to somehow attach the decoded elements to the grid’s &lt;code&gt;Data&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;One option is to put the elements in the main &lt;code&gt;Data&lt;/code&gt; object’s zone. That will keep them around, but it becomes an issue if the user calls &lt;code&gt;elements()&lt;/code&gt; multiple times, maybe in a loop. On every call, a new &lt;code&gt;Data&lt;/code&gt; object will be created for the dictionary and added to the zone, so we keep using more and more memory. It’ll eventually be freed again, but if it’s a large grid, then we may run out of memory before that. So that’s not great.&lt;/p&gt;
&lt;p&gt;A second option would be to add a pointer-to- &lt;code&gt;Data&lt;/code&gt; to the &lt;code&gt;Data&lt;/code&gt; class, which could be used to store the dictionary &lt;code&gt;Data&lt;/code&gt; object if the &lt;code&gt;Data&lt;/code&gt; object represents a grid. That way, we would only have to decode once, and any subsequent calls to &lt;code&gt;elements()&lt;/code&gt; or &lt;code&gt;shape()&lt;/code&gt; could used the cached object. And using a smart pointer would automatically delete the dictionary &lt;code&gt;Data&lt;/code&gt; object when the grid &lt;code&gt;Data&lt;/code&gt; object is deleted. The downside to this is that it makes &lt;code&gt;Data&lt;/code&gt; objects larger, which could cost some performance even for &lt;code&gt;Data&lt;/code&gt; objects that don’t contain a grid.&lt;/p&gt;
&lt;p&gt;Finally, since the MessagePack format is not so complicated, it would also be possible to make custom decoding routines which decode the grid in one stage, so that there is no need for a second &lt;code&gt;Data&lt;/code&gt; object at all. This could also help to reduce copying, thus improving performance further. That’s a lot of work however.&lt;/p&gt;
&lt;p&gt;At the moment, the focus for MUSCLE3 is on making things work, and on making the life of the users easy. Performance is not crucial, because in multiscale models (unlike in scale-overlapping multiphysics models) communication performance is rarely the bottleneck. I want to spend my time on solving problems for users, but not problems they don’t have. Since the first option could actually make things worse, and the third option is expensive, &lt;a href=&quot;https://github.com/multiscale/muscle3/commit/281c75b8907da5b2d5150c36472705e0916cc2bd&quot;&gt;I chose the second option&lt;/a&gt;. It’s not the prettiest solution, but it will do. If performance does become an issue in the future, then I can always come back and revisit.&lt;/p&gt;
&lt;p&gt;Having fixed the problem, there was one more thing to do: keep similar problems from appearing in the future. Mistakes in software are inevitable, as it’s made by humans and nobody’s perfect. But whenever we discover a mistake, it helps to see if there’s an easy way to avoid doing the same thing in the future, so that over time the software gets better and better. In this case, I added a check for Valgrind to the build system, and it will now run all the tests under Valgrind if it is installed. I also modified the continuous integration container to install Valgrind. This didn’t uncover any other memory management issues in MUSCLE3, but if I make another mistake like this in the future, then there’s a good chance that the tooling will catch it before it ends up with the users.&lt;/p&gt;
&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;My job done, it was time to go home. I grabbed my coat and my hat, verified that the Valgrind was still securely in my pocket, turned off the lights, and carefully closed the door behind me. It was late. The hallways were deserted, the reception desk downstairs vacant. I opened the after-hours side door and stepped out onto the street, into the golden light of a beautiful spring evening. Life was good. I turned towards home, pulled my hat a bit deeper over my eyes to keep the sun out, and started walking, detective-at-ease. I ignored the funny looks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_nAya0dMSUBd58C_5c8ML_g-e8f5424d.CY8gRSSn_Z1l8tn9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Dewang Gupta on Unsplash&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_g4Uw0OcyPSJMyeKP-89e7e8c7.D3nu8NeI.jpg" medium="image"/><author>Lourens Veen</author></item><item><title>Machine learning for research — use it or refuse it? Two flowcharts to help you decide.</title><link>https://blog2.esciencecenter.nl/posts/2020-09-01---machine-learning-for-research-use-it-or-refuse-it-two-flowch</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-09-01---machine-learning-for-research-use-it-or-refuse-it-two-flowch</guid><description>&lt;h2 id=&quot;machine-learning-in-particular-deep-learning-started-to-become-extremely-hot-510-years-ago-now-this-trend-has-fully-reached-most-academic-fields-outside-computer-science-as-well-but-will-it-also-help-you-with-your-research-question&quot;&gt;Machine learning (in particular deep learning) started to become extremely hot 5–10 years ago. Now, this trend has fully reached most academic fields outside computer science as well. But will it also help you with your research question?&lt;/h2&gt;
&lt;p&gt;It is important to notice that this point of “outperforming current measures”* is broader than only achieving higher accuracy. Often machine learning can also provide faster, more scalable solutions. In big data times, that can make a huge difference.&lt;/p&gt;
&lt;h2 id=&quot;part-2--will-it-make-sense-for-your-particular-problemdata&quot;&gt;Part 2 — Will it make sense for your particular problem/data?&lt;/h2&gt;
&lt;p&gt;Now we reach the difficult part.
If you have never applied any machine learning yourself, this seems near-impossible to answer. The second best thing you can do (first best thing again is: talk to someone experienced with machine learning!**), is to search for related work where machine learning was applied. This is tedious, and you might have to dig your way through mountains of jargon and unnecessarily complex and incomprehensible papers. Going through this pain, however, will hopefully give you a more &lt;strong&gt;realistic&lt;/strong&gt; picture of what you can obtain with the type and amount of data you have. Otherwise, those incredibly shiny results that make the headlines can easily cause unrealistic expectations. As an orientation, have a look at the flowchart below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning for research — use it or refuse it? Two flowcharts to help you decide.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;999&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-for-research-use-it-or--f9966393.-fBK-ogb_2ikJ26.webp&quot; srcset=&quot;&quot;&gt;
Quick check if you are onto something with you machine learning idea. Don’t forget, it’s a flowchart, not an expert. If you come across any question where your answer is neither Yes or No, but “I don’t know”, you unfortunately have to suffer a bit more and read another 5 related blog posts, tutorials, or papers (the latter if you like suffering). Or, maybe I repeat myself…, just talk to someone with more experience in machine learning. **Hint: **People that have experience with machine learning tend to drink coffee. If they don’t, they drink tea. Asking someone with machine learning experience to discuss an idea over a cup of coffee/tea will probably help to finish this flowchart. [by Florian Huber, &lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/&quot;&gt;CC BY 4.0&lt;/a&gt;, see &lt;a href=&quot;https://zenodo.org/record/4010272&quot;&gt;https://zenodo.org/record/4010272&lt;/a&gt; for high-res pdf]If you are serious about using machine learning for your research — maybe you are applying for funding, or deciding on future steps in you project, or looking for new collaborations? — better spend some time to gain a basic intuition on how machine learning could help with your problem. Don’t worry, you don’t have to become a machine learning expert yourself, but I imagine you also don’t want your next proposals to sound like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“We have data (or hope to have it), and then we want to do magic (which we simply call deep learning).”&lt;/p&gt;
&lt;h2 id=&quot;a-little-magic-at-the-end&quot;&gt;A little magic at the end&lt;/h2&gt;
&lt;p&gt;OK then. No magical solutions from deep learning. Still, I am convinced that there is plenty of opportunity to enhance scientific research through machine learning. **Yes, it can be hard to do right.
And no, it is no silver bullet.
But it is a whole lot of fun to do! And even if it doesn’t achieve what was hoped for, it will give you new insights about your data and your research question.
And sometimes… well… sometimes… there are those rare moments when you press &lt;code&gt;enter&lt;/code&gt; and then start to see this &lt;em&gt;magical glittering&lt;/em&gt; that seems to come from your screen.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch&quot;&gt;Get in touch&lt;/h2&gt;
&lt;p&gt;I hope you find this quick guide helpful. If you do, please share it, clap for it, or even better: use it for your upcoming machine learning journey!
And get in touch if you have any comments or questions.&lt;/p&gt;
&lt;p&gt;If you are based at a Dutch research institution and have a research question where you have hope that machine learning could help improve things, speed up things, or give access to bigger datasets, but feel that you need additional feedback on your ideas: feel free to get in touch with the machine learning team at the [Netherlands eScience Center]: &lt;em&gt;&lt;a href=&quot;mailto:machine-learning@esciencecenter.nl&quot;&gt;machine-learning@esciencecenter.nl&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You also find me on twitter: &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;me_datapoint**&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Special thanks to [Patrick Bos,] [Sonja Georgievska,] [Tom Bakker,] [Carlos Martinez-Ortiz] and [Pablo Rodríguez-Sánchez] for helpful comments and discussions.&lt;/p&gt;</description><pubDate>Tue, 01 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;machine-learning-in-particular-deep-learning-started-to-become-extremely-hot-510-years-ago-now-this-trend-has-fully-reached-most-academic-fields-outside-computer-science-as-well-but-will-it-also-help-you-with-your-research-question&quot;&gt;Machine learning (in particular deep learning) started to become extremely hot 5–10 years ago. Now, this trend has fully reached most academic fields outside computer science as well. But will it also help you with your research question?&lt;/h2&gt;
&lt;p&gt;It is important to notice that this point of “outperforming current measures”* is broader than only achieving higher accuracy. Often machine learning can also provide faster, more scalable solutions. In big data times, that can make a huge difference.&lt;/p&gt;
&lt;h2 id=&quot;part-2--will-it-make-sense-for-your-particular-problemdata&quot;&gt;Part 2 — Will it make sense for your particular problem/data?&lt;/h2&gt;
&lt;p&gt;Now we reach the difficult part.
If you have never applied any machine learning yourself, this seems near-impossible to answer. The second best thing you can do (first best thing again is: talk to someone experienced with machine learning!**), is to search for related work where machine learning was applied. This is tedious, and you might have to dig your way through mountains of jargon and unnecessarily complex and incomprehensible papers. Going through this pain, however, will hopefully give you a more &lt;strong&gt;realistic&lt;/strong&gt; picture of what you can obtain with the type and amount of data you have. Otherwise, those incredibly shiny results that make the headlines can easily cause unrealistic expectations. As an orientation, have a look at the flowchart below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning for research — use it or refuse it? Two flowcharts to help you decide.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;999&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-for-research-use-it-or--f9966393.-fBK-ogb_2ikJ26.webp&quot; srcset=&quot;&quot;&gt;
Quick check if you are onto something with you machine learning idea. Don’t forget, it’s a flowchart, not an expert. If you come across any question where your answer is neither Yes or No, but “I don’t know”, you unfortunately have to suffer a bit more and read another 5 related blog posts, tutorials, or papers (the latter if you like suffering). Or, maybe I repeat myself…, just talk to someone with more experience in machine learning. **Hint: **People that have experience with machine learning tend to drink coffee. If they don’t, they drink tea. Asking someone with machine learning experience to discuss an idea over a cup of coffee/tea will probably help to finish this flowchart. [by Florian Huber, &lt;a href=&quot;https://creativecommons.org/licenses/by/4.0/&quot;&gt;CC BY 4.0&lt;/a&gt;, see &lt;a href=&quot;https://zenodo.org/record/4010272&quot;&gt;https://zenodo.org/record/4010272&lt;/a&gt; for high-res pdf]If you are serious about using machine learning for your research — maybe you are applying for funding, or deciding on future steps in you project, or looking for new collaborations? — better spend some time to gain a basic intuition on how machine learning could help with your problem. Don’t worry, you don’t have to become a machine learning expert yourself, but I imagine you also don’t want your next proposals to sound like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“We have data (or hope to have it), and then we want to do magic (which we simply call deep learning).”&lt;/p&gt;
&lt;h2 id=&quot;a-little-magic-at-the-end&quot;&gt;A little magic at the end&lt;/h2&gt;
&lt;p&gt;OK then. No magical solutions from deep learning. Still, I am convinced that there is plenty of opportunity to enhance scientific research through machine learning. **Yes, it can be hard to do right.
And no, it is no silver bullet.
But it is a whole lot of fun to do! And even if it doesn’t achieve what was hoped for, it will give you new insights about your data and your research question.
And sometimes… well… sometimes… there are those rare moments when you press &lt;code&gt;enter&lt;/code&gt; and then start to see this &lt;em&gt;magical glittering&lt;/em&gt; that seems to come from your screen.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch&quot;&gt;Get in touch&lt;/h2&gt;
&lt;p&gt;I hope you find this quick guide helpful. If you do, please share it, clap for it, or even better: use it for your upcoming machine learning journey!
And get in touch if you have any comments or questions.&lt;/p&gt;
&lt;p&gt;If you are based at a Dutch research institution and have a research question where you have hope that machine learning could help improve things, speed up things, or give access to bigger datasets, but feel that you need additional feedback on your ideas: feel free to get in touch with the machine learning team at the [Netherlands eScience Center]: &lt;em&gt;&lt;a href=&quot;mailto:machine-learning@esciencecenter.nl&quot;&gt;machine-learning@esciencecenter.nl&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You also find me on twitter: &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;me_datapoint**&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Special thanks to [Patrick Bos,] [Sonja Georgievska,] [Tom Bakker,] [Carlos Martinez-Ortiz] and [Pablo Rodríguez-Sánchez] for helpful comments and discussions.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/machine-learning-for-research-use-it-or--f9966393.-fBK-ogb.png" medium="image"/><author>Florian Huber</author></item><item><title>Machine learningAI for Research — use it or refuse it</title><link>https://blog2.esciencecenter.nl/posts/2020-09-01---machine-learningai-for-research-use-it-or-refuse-it</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-09-01---machine-learningai-for-research-use-it-or-refuse-it</guid><description>&lt;h2 id=&quot;machine-learning-in-particular-deep-learning-started-to-become-extremely-hot-510-years-ago-now-this-trend-has-fully-reached-most-academic-fields-outside-computer-science-as-well-but-will-it-also-help-you-with-your-research-question&quot;&gt;Machine learning (in particular deep learning) started to become extremely hot 5–10 years ago. Now, this trend has fully reached most academic fields outside computer science as well. But will it also help you with your research question?&lt;/h2&gt;
&lt;p&gt;Clearly, machine learning is a broad and complex field. So there is no simple answer to whether it makes sense to aim for applying machine learning for your specific problem. If you have never applied machine learning tools yourself, honestly, the best you can do is grab your data and your research question and sit together with someone with plenty of hands-on experience in machine learning, preferably on related topics (or join &lt;a href=&quot;https://blog.esciencecenter.nl/workshop-machine-learning-for-research-2020-39c4fc8218e8&quot;&gt;events such as this one&lt;/a&gt;). But if you don’t have the luxury to know such a person, try this short guide (and better not what you see in the cartoon below).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1231&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QAhUoMJk3ocCBlzK1TKvzQ-e23d3602.CpXhBJ1x_ZvIXEb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Machine learning (deep learning in particular) is often expected to do near-magical things with data and/or techniques that are hardly suitable for such wonders.[cartoon by Florian Huber, CC BY 4.0 ]&lt;/p&gt;
&lt;h2 id=&quot;part-1--is-it-worth-considering&quot;&gt;Part 1 — Is it worth considering?&lt;/h2&gt;
&lt;p&gt;To start, try getting a clear idea of what a machine learning solution would have to achieve. Then go through the flowchart below.&lt;/p&gt;
&lt;h3 id=&quot;machine-learning-models-can-fail-in-unexpected-ways&quot;&gt;Machine learning models can fail in unexpected ways&lt;/h3&gt;
&lt;p&gt;The clearest answer I can give is when you come with a &lt;strong&gt;mission critical task&lt;/strong&gt;. That’s essentially anything that should never go wrong and where no final human inspection takes place. In those cases: &lt;strong&gt;forget about AI&lt;/strong&gt;. Sure, there is autonomous driving, clearly a mission critical application. But AI systems failing in unexpected ways have drastically reset expectations in that area (see &lt;a href=&quot;https://www.nytimes.com/2019/07/17/business/self-driving-autonomous-cars.html&quot;&gt;this blog post&lt;/a&gt; or &lt;a href=&quot;https://medium.com/every-day-a-datapoint/autonomous-cars-an-outdated-vision-3a44aadad839&quot;&gt;one of mine on the same topic&lt;/a&gt;). So, that’s only confirming my point: don’t use AI for it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1058&quot; height=&quot;1209&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0AUMKnSlAFbXwcv5Zb1mhg-d2e730c4.g8sLW7k0_ZrUjY6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simple flowchart to decide if machine learning could potentially be of interest. Even if the answer is yes, that of course still doesn’t mean it will really make sense for a particular problem/data combination. Hopefully the second flowchart below can then help you further. [by Florian Huber, CC BY 4.0, see &lt;a href=&quot;https://zenodo.org/record/4010272&quot;&gt;https://zenodo.org/record/4010272&lt;/a&gt; for high-res pdf]&lt;/p&gt;
&lt;h3 id=&quot;must-the-results-remain-the-same-at-all-times&quot;&gt;Must the results remain the same at all times?&lt;/h3&gt;
&lt;p&gt;Think for instance of a distance measure used for clustering. Classical measures for this (cosine, euclidean etc.) will &lt;strong&gt;always return the same values, now and in hundred years&lt;/strong&gt;. In contrast, many machine learning solutions are moving targets which involve training a model on a given dataset. Say, your model outputs a distance value for two inputs, classifies an input, or clusters a set of inputs. In all such cases the outcome can change each time the training dataset changes. Even worse, unless you take extreme care, the results will even be slightly different each time you train a model on the same data &lt;em&gt;(shocking, isn’t it!?&lt;/em&gt; &lt;a href=&quot;https://machinelearningmastery.com/different-results-each-time-in-machine-learning/&quot;&gt;read more here&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;. You can still make things more reproducible, for instance by doing a proper versioning of your trained models. But better don’t think in terms of hundred years.&lt;/p&gt;
&lt;h3 id=&quot;must-the-results-be-easy-to-explainunderstand&quot;&gt;Must the results be easy to explain/understand?&lt;/h3&gt;
&lt;p&gt;Many people interested in machine learning will have heard about the “black-box problem”, which usually refers to the fact that the model outcome cannot easily be explained due to the high model complexity. To get this right out of the way: Even the fanciest deep learning networks are not truly black boxes, because each mathematical operation done to get a certain outcome can in principle be accessed. The key problem actually is that it’s extremely hard to translate this into an understandable pattern. So, if you want an explanation as simple as “ &lt;strong&gt;A&lt;/strong&gt; is close to &lt;strong&gt;B&lt;/strong&gt; because the euclidean distance is below &lt;strong&gt;x&lt;/strong&gt; ” then deep learning is usually not the route to go (unless, maybe, you really know a lot about &lt;a href=&quot;https://en.wikipedia.org/wiki/Explainable_artificial_intelligence&quot;&gt;explainable AI&lt;/a&gt;). Some classical machine learning techniques might be worth considering here, because techniques such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Decision_tree_learning&quot;&gt;decision trees&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Linear_regression&quot;&gt;linear regression&lt;/a&gt; models (on reasonable number of features), usually do provide very human-accessible explanations.&lt;/p&gt;
&lt;h3 id=&quot;good-enough-if-results-on-average-outperform-current-measures&quot;&gt;Good enough if results (on average) outperform current measures?&lt;/h3&gt;
&lt;p&gt;Finally, if what you really want to achieve is mostly to outperform current techniques, things look different. Say you want to get better query results than before (but a human in the end would anyway inspect them), or you want to classify things with higher accuracy (failing occasionally is fine though), or you want better predictions than you currently have (as all predictions those are allowed to occasionally fail as well, just maybe less often). In such cases, machine learning is probably worth considering.&lt;/p&gt;
&lt;p&gt;It is important to notice that this point of &lt;em&gt;“outperforming current measures”&lt;/em&gt; is broader than only achieving higher accuracy. Often machine learning can also provide faster, more scalable solutions. In big data times, that can make a huge difference.&lt;/p&gt;
&lt;h2 id=&quot;part-2--will-it-make-sense-for-your-particular-problemdata&quot;&gt;Part 2 — Will it make sense for your particular problem/data?&lt;/h2&gt;
&lt;p&gt;Now we reach the difficult part.&lt;br&gt;
If you have never applied any machine learning yourself, this seems near-impossible to answer. The second best thing you can do (first best thing again is: &lt;strong&gt;talk to someone experienced with machine learning!&lt;/strong&gt;), is to search for related work where machine learning was applied. This is tedious, and you might have to dig your way through mountains of jargon and unnecessarily complex and incomprehensible papers. Going through this pain, however, will hopefully give you a more &lt;strong&gt;realistic&lt;/strong&gt; picture of what you can obtain with the type and amount of data you have. Otherwise, those incredibly shiny results that make the headlines can easily cause unrealistic expectations. As an orientation, have a look at the flowchart below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1060&quot; height=&quot;1513&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__QCfQGtoFsL6_S9Wk5v2vg-7761de7e.DCe7kJFm_1RiBxe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Quick check if you are onto something with you machine learning idea. Don’t forget, it’s a flowchart, not an expert. If you come across any question where your answer is neither Yes or No, but “I don’t know”, you unfortunately have to suffer a bit more and read another 5 related blog posts, tutorials, or papers (the latter if you like suffering). Or, maybe I repeat myself…, just talk to someone with more experience in machine learning. Hint: People that have experience with machine learning tend to drink coffee. If they don’t, they drink tea. Asking someone with machine learning experience to discuss an idea over a cup of coffee/tea will probably help to finish this flowchart. [by Florian Huber, CC BY 4.0, see &lt;a href=&quot;https://zenodo.org/record/4010272&quot;&gt;https://zenodo.org/record/4010272&lt;/a&gt; for high-res pdf]&lt;/p&gt;
&lt;p&gt;If you are serious about using machine learning for your research — maybe you are applying for funding, or deciding on future steps in you project, or looking for new collaborations? — better spend some time to gain a basic intuition on how machine learning could help with your problem. Don’t worry, you don’t have to become a machine learning expert yourself, but I imagine you also don’t want your next proposals to sound like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We have data (or hope to have it), and then we want to do magic (which we simply call deep learning).”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;a-little-magic-at-the-end&quot;&gt;A little magic at the end&lt;/h2&gt;
&lt;p&gt;OK then. No magical solutions from deep learning. Still, I am convinced that there is plenty of opportunity to enhance scientific research through machine learning.&lt;br&gt;
Yes, it can be hard to do right.&lt;br&gt;
And no, it is no silver bullet.&lt;br&gt;
But it is a whole lot of fun to do! And even if it doesn’t achieve what was hoped for, it will give you new insights about your data and your research question.&lt;br&gt;
And sometimes… well… sometimes… there are those rare moments when you press &lt;code&gt;enter&lt;/code&gt; and then start to see this &lt;em&gt;magical glittering&lt;/em&gt; that seems to come from your screen.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch&quot;&gt;Get in touch&lt;/h2&gt;
&lt;p&gt;I hope you find this quick guide helpful. If you do, please share it, clap for it, or even better: use it for your upcoming machine learning journey!&lt;br&gt;
And get in touch if you have any comments or questions.&lt;/p&gt;
&lt;p&gt;If you are based at a Dutch research institution and have a research question where you have hope that machine learning could help improve things, speed up things, or give access to bigger datasets, but feel that you need additional feedback on your ideas: feel free to get in touch with the machine learning team at the: &lt;em&gt;&lt;a href=&quot;mailto:machine-learning@esciencecenter.nl&quot;&gt;machine-learning@esciencecenter.nl&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You also find me on twitter: &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;&lt;strong&gt;me_datapoint&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 01 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;machine-learning-in-particular-deep-learning-started-to-become-extremely-hot-510-years-ago-now-this-trend-has-fully-reached-most-academic-fields-outside-computer-science-as-well-but-will-it-also-help-you-with-your-research-question&quot;&gt;Machine learning (in particular deep learning) started to become extremely hot 5–10 years ago. Now, this trend has fully reached most academic fields outside computer science as well. But will it also help you with your research question?&lt;/h2&gt;
&lt;p&gt;Clearly, machine learning is a broad and complex field. So there is no simple answer to whether it makes sense to aim for applying machine learning for your specific problem. If you have never applied machine learning tools yourself, honestly, the best you can do is grab your data and your research question and sit together with someone with plenty of hands-on experience in machine learning, preferably on related topics (or join &lt;a href=&quot;https://blog.esciencecenter.nl/workshop-machine-learning-for-research-2020-39c4fc8218e8&quot;&gt;events such as this one&lt;/a&gt;). But if you don’t have the luxury to know such a person, try this short guide (and better not what you see in the cartoon below).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1231&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QAhUoMJk3ocCBlzK1TKvzQ-e23d3602.CpXhBJ1x_ZvIXEb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Machine learning (deep learning in particular) is often expected to do near-magical things with data and/or techniques that are hardly suitable for such wonders.[cartoon by Florian Huber, CC BY 4.0 ]&lt;/p&gt;
&lt;h2 id=&quot;part-1--is-it-worth-considering&quot;&gt;Part 1 — Is it worth considering?&lt;/h2&gt;
&lt;p&gt;To start, try getting a clear idea of what a machine learning solution would have to achieve. Then go through the flowchart below.&lt;/p&gt;
&lt;h3 id=&quot;machine-learning-models-can-fail-in-unexpected-ways&quot;&gt;Machine learning models can fail in unexpected ways&lt;/h3&gt;
&lt;p&gt;The clearest answer I can give is when you come with a &lt;strong&gt;mission critical task&lt;/strong&gt;. That’s essentially anything that should never go wrong and where no final human inspection takes place. In those cases: &lt;strong&gt;forget about AI&lt;/strong&gt;. Sure, there is autonomous driving, clearly a mission critical application. But AI systems failing in unexpected ways have drastically reset expectations in that area (see &lt;a href=&quot;https://www.nytimes.com/2019/07/17/business/self-driving-autonomous-cars.html&quot;&gt;this blog post&lt;/a&gt; or &lt;a href=&quot;https://medium.com/every-day-a-datapoint/autonomous-cars-an-outdated-vision-3a44aadad839&quot;&gt;one of mine on the same topic&lt;/a&gt;). So, that’s only confirming my point: don’t use AI for it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1058&quot; height=&quot;1209&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0AUMKnSlAFbXwcv5Zb1mhg-d2e730c4.g8sLW7k0_ZrUjY6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Simple flowchart to decide if machine learning could potentially be of interest. Even if the answer is yes, that of course still doesn’t mean it will really make sense for a particular problem/data combination. Hopefully the second flowchart below can then help you further. [by Florian Huber, CC BY 4.0, see &lt;a href=&quot;https://zenodo.org/record/4010272&quot;&gt;https://zenodo.org/record/4010272&lt;/a&gt; for high-res pdf]&lt;/p&gt;
&lt;h3 id=&quot;must-the-results-remain-the-same-at-all-times&quot;&gt;Must the results remain the same at all times?&lt;/h3&gt;
&lt;p&gt;Think for instance of a distance measure used for clustering. Classical measures for this (cosine, euclidean etc.) will &lt;strong&gt;always return the same values, now and in hundred years&lt;/strong&gt;. In contrast, many machine learning solutions are moving targets which involve training a model on a given dataset. Say, your model outputs a distance value for two inputs, classifies an input, or clusters a set of inputs. In all such cases the outcome can change each time the training dataset changes. Even worse, unless you take extreme care, the results will even be slightly different each time you train a model on the same data &lt;em&gt;(shocking, isn’t it!?&lt;/em&gt; &lt;a href=&quot;https://machinelearningmastery.com/different-results-each-time-in-machine-learning/&quot;&gt;read more here&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;. You can still make things more reproducible, for instance by doing a proper versioning of your trained models. But better don’t think in terms of hundred years.&lt;/p&gt;
&lt;h3 id=&quot;must-the-results-be-easy-to-explainunderstand&quot;&gt;Must the results be easy to explain/understand?&lt;/h3&gt;
&lt;p&gt;Many people interested in machine learning will have heard about the “black-box problem”, which usually refers to the fact that the model outcome cannot easily be explained due to the high model complexity. To get this right out of the way: Even the fanciest deep learning networks are not truly black boxes, because each mathematical operation done to get a certain outcome can in principle be accessed. The key problem actually is that it’s extremely hard to translate this into an understandable pattern. So, if you want an explanation as simple as “ &lt;strong&gt;A&lt;/strong&gt; is close to &lt;strong&gt;B&lt;/strong&gt; because the euclidean distance is below &lt;strong&gt;x&lt;/strong&gt; ” then deep learning is usually not the route to go (unless, maybe, you really know a lot about &lt;a href=&quot;https://en.wikipedia.org/wiki/Explainable_artificial_intelligence&quot;&gt;explainable AI&lt;/a&gt;). Some classical machine learning techniques might be worth considering here, because techniques such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Decision_tree_learning&quot;&gt;decision trees&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Linear_regression&quot;&gt;linear regression&lt;/a&gt; models (on reasonable number of features), usually do provide very human-accessible explanations.&lt;/p&gt;
&lt;h3 id=&quot;good-enough-if-results-on-average-outperform-current-measures&quot;&gt;Good enough if results (on average) outperform current measures?&lt;/h3&gt;
&lt;p&gt;Finally, if what you really want to achieve is mostly to outperform current techniques, things look different. Say you want to get better query results than before (but a human in the end would anyway inspect them), or you want to classify things with higher accuracy (failing occasionally is fine though), or you want better predictions than you currently have (as all predictions those are allowed to occasionally fail as well, just maybe less often). In such cases, machine learning is probably worth considering.&lt;/p&gt;
&lt;p&gt;It is important to notice that this point of &lt;em&gt;“outperforming current measures”&lt;/em&gt; is broader than only achieving higher accuracy. Often machine learning can also provide faster, more scalable solutions. In big data times, that can make a huge difference.&lt;/p&gt;
&lt;h2 id=&quot;part-2--will-it-make-sense-for-your-particular-problemdata&quot;&gt;Part 2 — Will it make sense for your particular problem/data?&lt;/h2&gt;
&lt;p&gt;Now we reach the difficult part.&lt;br&gt;
If you have never applied any machine learning yourself, this seems near-impossible to answer. The second best thing you can do (first best thing again is: &lt;strong&gt;talk to someone experienced with machine learning!&lt;/strong&gt;), is to search for related work where machine learning was applied. This is tedious, and you might have to dig your way through mountains of jargon and unnecessarily complex and incomprehensible papers. Going through this pain, however, will hopefully give you a more &lt;strong&gt;realistic&lt;/strong&gt; picture of what you can obtain with the type and amount of data you have. Otherwise, those incredibly shiny results that make the headlines can easily cause unrealistic expectations. As an orientation, have a look at the flowchart below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1060&quot; height=&quot;1513&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__QCfQGtoFsL6_S9Wk5v2vg-7761de7e.DCe7kJFm_1RiBxe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Quick check if you are onto something with you machine learning idea. Don’t forget, it’s a flowchart, not an expert. If you come across any question where your answer is neither Yes or No, but “I don’t know”, you unfortunately have to suffer a bit more and read another 5 related blog posts, tutorials, or papers (the latter if you like suffering). Or, maybe I repeat myself…, just talk to someone with more experience in machine learning. Hint: People that have experience with machine learning tend to drink coffee. If they don’t, they drink tea. Asking someone with machine learning experience to discuss an idea over a cup of coffee/tea will probably help to finish this flowchart. [by Florian Huber, CC BY 4.0, see &lt;a href=&quot;https://zenodo.org/record/4010272&quot;&gt;https://zenodo.org/record/4010272&lt;/a&gt; for high-res pdf]&lt;/p&gt;
&lt;p&gt;If you are serious about using machine learning for your research — maybe you are applying for funding, or deciding on future steps in you project, or looking for new collaborations? — better spend some time to gain a basic intuition on how machine learning could help with your problem. Don’t worry, you don’t have to become a machine learning expert yourself, but I imagine you also don’t want your next proposals to sound like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We have data (or hope to have it), and then we want to do magic (which we simply call deep learning).”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;a-little-magic-at-the-end&quot;&gt;A little magic at the end&lt;/h2&gt;
&lt;p&gt;OK then. No magical solutions from deep learning. Still, I am convinced that there is plenty of opportunity to enhance scientific research through machine learning.&lt;br&gt;
Yes, it can be hard to do right.&lt;br&gt;
And no, it is no silver bullet.&lt;br&gt;
But it is a whole lot of fun to do! And even if it doesn’t achieve what was hoped for, it will give you new insights about your data and your research question.&lt;br&gt;
And sometimes… well… sometimes… there are those rare moments when you press &lt;code&gt;enter&lt;/code&gt; and then start to see this &lt;em&gt;magical glittering&lt;/em&gt; that seems to come from your screen.&lt;/p&gt;
&lt;h2 id=&quot;get-in-touch&quot;&gt;Get in touch&lt;/h2&gt;
&lt;p&gt;I hope you find this quick guide helpful. If you do, please share it, clap for it, or even better: use it for your upcoming machine learning journey!&lt;br&gt;
And get in touch if you have any comments or questions.&lt;/p&gt;
&lt;p&gt;If you are based at a Dutch research institution and have a research question where you have hope that machine learning could help improve things, speed up things, or give access to bigger datasets, but feel that you need additional feedback on your ideas: feel free to get in touch with the machine learning team at the: &lt;em&gt;&lt;a href=&quot;mailto:machine-learning@esciencecenter.nl&quot;&gt;machine-learning@esciencecenter.nl&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You also find me on twitter: &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;&lt;strong&gt;me_datapoint&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_QAhUoMJk3ocCBlzK1TKvzQ-e23d3602.CpXhBJ1x.jpeg" medium="image"/><author>Florian Huber</author></item><item><title>Parallel R in a nutshell</title><link>https://blog2.esciencecenter.nl/posts/2020-08-17---parallel-r-in-a-nutshell</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-08-17---parallel-r-in-a-nutshell</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_6Zv5YFtBvwcwadl3-10a4b625.HpSNPUiA_Z1CWNvw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Marvin Meyer on Unsplash&lt;/p&gt;
&lt;p&gt;Loops are, by definition, repetitive tasks. Although it is not part of the definition, loops also tend to be boring. Luckily for us, computers are good at performing repetitive tasks, and they never complain about boredom.&lt;/p&gt;
&lt;p&gt;When the tasks are complex, or if the number of repetitions is high, loops may take a lot of time to run even on a computer. There are several strategies to increase the execution speed of loops. In this short tutorial, we will talk about one of them: parallelization.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;R is required, and RStudio is recommended. Additionally, some libraries may be required. If you are missing any, you can install it running &lt;code&gt;install.package(&apos;&amp;#x3C;library-name&gt;&apos;)&lt;/code&gt;, where &lt;code&gt;&amp;#x3C;library-name&gt;&lt;/code&gt; stands for the name of the library (for instance, &lt;code&gt;install.package(&apos;parallel&apos;)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If you prefer to execute it line-by-line, you may be interested in visiting the &lt;a href=&quot;https://github.com/PabRod/blog-parallelR&quot;&gt;vignette version&lt;/a&gt; of this tutorial.&lt;/p&gt;
&lt;h2 id=&quot;why-parallelizing&quot;&gt;Why parallelizing?&lt;/h2&gt;
&lt;p&gt;Modern laptops typically have 4 or 8 cores. Each of them can be loosely thought of as an independent mini-computer, capable of doing tasks independently of the other ones. The number of cores in your computer can be retrieved from &lt;code&gt;R&lt;/code&gt; with the command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numCores &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parallel&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detectCores&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Requires&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; library(parallel)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(numCores)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; In&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; my &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, this prints &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When a program runs serially (as they usually do by default), only one core is recruited for performing the program’s task. Recruiting more than one core for a given task is known as parallelization. The desired result of parallelizing a task is a reduction in its execution time. An analogy could be to build a wall by laying bricks alone, one by one (serial) as opposed to building it with the help of three friends (parallel with 4 “cores”).&lt;/p&gt;
&lt;p&gt;In the figure below, we see the CPU usage over time of my computer performing the same task serially (highlighted in green) and in parallel (in red). Both processes performed the very same task and produced the same result, but the parallel one, recruiting more cores, ran roughly three times faster.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;475&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3qaXCEcKBHIVpQkMcmtvvg-493b492c.BQH382dC_29RGOs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It may be surprising to notice that using 8 cores instead of one didn’t multiply the speed by 8. This is normal. Parallelization rarely behaves as linearly as we would like. A reason for this is that the code, and often also the data, has to be copied to each of the cores. The output of each core also has to be put together, and this also consumes time. Following the analogy of the 4 brick-layers, it is clear that building a wall with friends requires a bit of planning and coordination before starting laying the bricks (at least if we want the wall to be one wall, and not four disconnected pieces). Intuition also tells us that, while perhaps asking for the help of 4 friends may be a good idea, calling 256 friends could be an organizational nightmare. For a more formal approach to these ideas, check &lt;a href=&quot;https://en.wikipedia.org/wiki/Amdahl%27s_law&quot;&gt;Amdahl’s law&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;More importantly, some repetitive tasks are not parallelizable at all. For instance, what if instead of a brick wall we want to make a brick stack? There is no point in laying the 3rd brick if the 1st and 2nd are not there already!&lt;/p&gt;
&lt;p&gt;But don’t worry about these details now. The example I’ve prepared for you is going to work fine.&lt;/p&gt;
&lt;h2 id=&quot;we-need-a-task-to-perform&quot;&gt;We need a task to perform&lt;/h2&gt;
&lt;p&gt;In this short introduction, I want to show different approaches, some of them serial and some of them parallel, to approach a parallelizable problem. A good example task for showing the advantages of parallelization would be one that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Is simple.&lt;/li&gt;
&lt;li&gt;Takes an appreciable amount of CPU time to be completed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The problem of &lt;a href=&quot;https://en.wikipedia.org/wiki/Primality_test&quot;&gt;deciding if a large integer is prime or not&lt;/a&gt; fulfills both characteristics.&lt;/p&gt;
&lt;p&gt;It will be a good idea to split our task into a &lt;strong&gt;function&lt;/strong&gt; (describing WHAT to do) and an &lt;strong&gt;input&lt;/strong&gt; (describing to WHOM).&lt;/p&gt;
&lt;p&gt;In our case, the &lt;strong&gt;function&lt;/strong&gt; performs a test on primality (if you think this is a silly function, you are right, but please see Notes at the end of this tutorial).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fun &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(x) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  numbers&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;isPrime(x) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Requires&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the package numbers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the &lt;strong&gt;input&lt;/strong&gt; is just a vector containing 1000 large integers (that I created programmatically just to not have to type then one-by-one).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Generate some large integers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Number&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; integers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;min &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Lower&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bound&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;max &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10000000000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Upper&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; boundinputs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sample(min&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;max, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; random large integers (between &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1e5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1e10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These two objects, &lt;code&gt;fun&lt;/code&gt; and &lt;code&gt;inputs&lt;/code&gt;, define the &lt;em&gt;homework&lt;/em&gt; we want to assign to our computer (in this case, to decide which integers from the list of inputs are prime). We also want our computer to store the results. We will do this in six different ways, two of them parallel. Later, we’ll compare their performance.&lt;/p&gt;
&lt;h2 id=&quot;possibility-0-run-serially&quot;&gt;Possibility 0: run serially&lt;/h2&gt;
&lt;p&gt;In this section, we’ll see three different ways of solving our problem by running serially. That is, without using parallelization. The user is likely to be familiar with at least some of them.&lt;/p&gt;
&lt;h2 id=&quot;01-run-serially-with-a-loop&quot;&gt;0.1 Run serially with a loop&lt;/h2&gt;
&lt;p&gt;This is the most straightforward approach, although not very efficient. The basic structure is given in the snippet below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results vector&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;for (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { # Loop one by one along the input elements&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  results[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs[i])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;02-run-serially-with-foreach&quot;&gt;0.2 Run serially with foreach&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;foreach&lt;/code&gt; package saves us the explicit typing of the index (compare with the &lt;code&gt;for&lt;/code&gt; loop in the previous example). The output of &lt;code&gt;foreach&lt;/code&gt; is, by default, a list. We used the parameter &lt;code&gt;.combine = &quot;c&quot;&lt;/code&gt; (concatenate) to return the output as a vector.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Load the required libraries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(foreach)foreach (val &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inputs, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;combine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;c&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%do%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    fun(val) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Loop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; one&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;by&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;one using foreach&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;03-run-serially-with-lapply&quot;&gt;0.3 Run serially with lapply&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;lapply&lt;/code&gt; is usually preferred over explicit &lt;code&gt;for&lt;/code&gt; or &lt;code&gt;foreach&lt;/code&gt; loops.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lapply(inputs, fun) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Use&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lapply instead &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for loop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;do-it-in-parallel&quot;&gt;Do it in parallel!&lt;/h2&gt;
&lt;p&gt;And now, we’ll finally use parallel programming to solve our problem.&lt;/p&gt;
&lt;h2 id=&quot;possibility-1-run-in-parallel-with-mclapply-linux-only&quot;&gt;Possibility 1: run in parallel with mclapply (Linux only)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;mclapply&lt;/code&gt; is part of the &lt;code&gt;parallel&lt;/code&gt; library. Rule of thumb: use it instead of &lt;code&gt;lapply&lt;/code&gt;. If the code is parallelizable, it will do the magic:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Load the required libraries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(parallel)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parallel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mclapply(inputs, fun, mc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cores &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numCores)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Note that the number of cores is required by mclapply&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, this approach only works on Linux. If you are working on a Windows machine, it will perform as a serial &lt;code&gt;lapply&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;possibility-2-run-in-parallel-with-doparallel--foreach&quot;&gt;Possibility 2: run in parallel with doParallel + foreach&lt;/h2&gt;
&lt;p&gt;Rule of thumb: &lt;code&gt;doParallel&lt;/code&gt; transforms a &lt;code&gt;foreach&lt;/code&gt; loop into a parallel process. Provided, of course, the underlying process is parallelizable.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Load the required libraries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(iterators)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(doParallel)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;registerDoParallel(numCores)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foreach(val &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inputs, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;combine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;c&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;dopar&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    fun(val)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;possibility-3-take-advantage-of-vector-functions&quot;&gt;Possibility 3: take advantage of vector functions&lt;/h2&gt;
&lt;p&gt;Most (but not all) of &lt;code&gt;R&lt;/code&gt; functions can work with vectorized inputs. This means that the function accepts a vector of inputs and returns an equally sized vector of outputs. This allows &lt;em&gt;hiding&lt;/em&gt; the whole &lt;em&gt;loop&lt;/em&gt; in a single, easy-to-read line.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More importantly, although running serially, vector functions often run faster than parallel schemes. Why not use them always then? The quick answer is: we are not always lucky enough to have a function that accepts a vector input.&lt;/p&gt;
&lt;h2 id=&quot;compare-results&quot;&gt;Compare results&lt;/h2&gt;
&lt;p&gt;In the figure below we plot the execution times of each of the six methods we tried. We also provide a summary table for each of them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;664&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BeEX_sXEa65n1z1P_0BIvA-d78cecd9.BE94DZz4_Z1epJVk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We notice that the parallel methods performed significantly better than the serial ones. We also notice that the vector method performed even better (but keep in mind not all functions are vectorizable).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pro tip: what about using vectorization AND parallelization?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;trying-to-parallelize-non-parallelizable-code&quot;&gt;Trying to parallelize non-parallelizable code&lt;/h2&gt;
&lt;p&gt;In this subsection we’ll use the expression below as an example:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;293&quot; height=&quot;40&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ltsKnFbjM5srKhkk7HFn_Q-ce448f4c.QHmW10B0_Z1AcP4P.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It is just a recipe to build a list of numbers by adding 1 to the previous number in the list. It is easy to see that, when initialized with &lt;em&gt;x&lt;/em&gt; 0=0, this iterator yields {0,1,2,3,4,…}. Note that in order to obtain the value a given x in position n, we need to know the value of the previous x (that in position n-1; remember the analogy of building a stack of bricks). This operation is thus intrinsically serial.&lt;/p&gt;
&lt;p&gt;In this case, our function and inputs look like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fun &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(x) {x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; as (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using a serial loop everything works fine:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foreach(i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%do%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inputs[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs[i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result is the expected&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what if we insist on parallelizing? After all, our serial loop is very similar to the &lt;code&gt;foreach&lt;/code&gt; + &lt;code&gt;doParallel&lt;/code&gt; one, so it is tempting to at least try. And what happens then? As expected, it simply doesn’t work properly. And more worryingly, doesn’t throw an error either!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; again&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 0foreach(i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;dopar&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inputs[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs[i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; this &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is a disastrous &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that was it. This is just a quick starting guide to a complicated topic. If you want to know more, I suggest you go directly to the &lt;a href=&quot;https://github.com/HenrikBengtsson/future&quot;&gt;future&lt;/a&gt; library.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The astute reader may have noticed that our function &lt;code&gt;fun&lt;/code&gt; is a mere renaming of the function &lt;code&gt;isPrime&lt;/code&gt; contained in the package &lt;code&gt;numbers&lt;/code&gt;. The reason for that is merely pedagogical: we want the readers to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Notice that the structure input -&gt; function -&gt; results is indeed VERY general.&lt;/li&gt;
&lt;li&gt;Be able to try their own pieces of slow code inside the body of &lt;code&gt;fun&lt;/code&gt; (this can be done comfortably using our &lt;a href=&quot;https://github.com/PabRod/blog-parallelR&quot;&gt;vignette&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;are-you-more-into-python&quot;&gt;Are you more into Python?&lt;/h2&gt;
&lt;p&gt;We can also help with that! Check out this other tutorial: &lt;a href=&quot;https://blog.esciencecenter.nl/parallel-programming-in-python-7fd62c90217d&quot;&gt;Parallel program in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I want to say thanks to &lt;a href=&quot;https://www.esciencecenter.nl/team/lourens-veen-msc/&quot;&gt;Lourens Veen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-peter-kalverla-2/&quot;&gt;Peter Kalverla&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;Patrick Bos&lt;/a&gt;. Their useful comments definitely improved the clarity of the final text.&lt;/p&gt;</description><pubDate>Mon, 17 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_6Zv5YFtBvwcwadl3-10a4b625.HpSNPUiA_Z1CWNvw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Marvin Meyer on Unsplash&lt;/p&gt;
&lt;p&gt;Loops are, by definition, repetitive tasks. Although it is not part of the definition, loops also tend to be boring. Luckily for us, computers are good at performing repetitive tasks, and they never complain about boredom.&lt;/p&gt;
&lt;p&gt;When the tasks are complex, or if the number of repetitions is high, loops may take a lot of time to run even on a computer. There are several strategies to increase the execution speed of loops. In this short tutorial, we will talk about one of them: parallelization.&lt;/p&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;R is required, and RStudio is recommended. Additionally, some libraries may be required. If you are missing any, you can install it running &lt;code&gt;install.package(&apos;&amp;#x3C;library-name&gt;&apos;)&lt;/code&gt;, where &lt;code&gt;&amp;#x3C;library-name&gt;&lt;/code&gt; stands for the name of the library (for instance, &lt;code&gt;install.package(&apos;parallel&apos;)&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;If you prefer to execute it line-by-line, you may be interested in visiting the &lt;a href=&quot;https://github.com/PabRod/blog-parallelR&quot;&gt;vignette version&lt;/a&gt; of this tutorial.&lt;/p&gt;
&lt;h2 id=&quot;why-parallelizing&quot;&gt;Why parallelizing?&lt;/h2&gt;
&lt;p&gt;Modern laptops typically have 4 or 8 cores. Each of them can be loosely thought of as an independent mini-computer, capable of doing tasks independently of the other ones. The number of cores in your computer can be retrieved from &lt;code&gt;R&lt;/code&gt; with the command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;numCores &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parallel&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;detectCores&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Requires&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; library(parallel)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(numCores)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; In&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; my &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, this prints &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When a program runs serially (as they usually do by default), only one core is recruited for performing the program’s task. Recruiting more than one core for a given task is known as parallelization. The desired result of parallelizing a task is a reduction in its execution time. An analogy could be to build a wall by laying bricks alone, one by one (serial) as opposed to building it with the help of three friends (parallel with 4 “cores”).&lt;/p&gt;
&lt;p&gt;In the figure below, we see the CPU usage over time of my computer performing the same task serially (highlighted in green) and in parallel (in red). Both processes performed the very same task and produced the same result, but the parallel one, recruiting more cores, ran roughly three times faster.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;475&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3qaXCEcKBHIVpQkMcmtvvg-493b492c.BQH382dC_29RGOs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It may be surprising to notice that using 8 cores instead of one didn’t multiply the speed by 8. This is normal. Parallelization rarely behaves as linearly as we would like. A reason for this is that the code, and often also the data, has to be copied to each of the cores. The output of each core also has to be put together, and this also consumes time. Following the analogy of the 4 brick-layers, it is clear that building a wall with friends requires a bit of planning and coordination before starting laying the bricks (at least if we want the wall to be one wall, and not four disconnected pieces). Intuition also tells us that, while perhaps asking for the help of 4 friends may be a good idea, calling 256 friends could be an organizational nightmare. For a more formal approach to these ideas, check &lt;a href=&quot;https://en.wikipedia.org/wiki/Amdahl%27s_law&quot;&gt;Amdahl’s law&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;More importantly, some repetitive tasks are not parallelizable at all. For instance, what if instead of a brick wall we want to make a brick stack? There is no point in laying the 3rd brick if the 1st and 2nd are not there already!&lt;/p&gt;
&lt;p&gt;But don’t worry about these details now. The example I’ve prepared for you is going to work fine.&lt;/p&gt;
&lt;h2 id=&quot;we-need-a-task-to-perform&quot;&gt;We need a task to perform&lt;/h2&gt;
&lt;p&gt;In this short introduction, I want to show different approaches, some of them serial and some of them parallel, to approach a parallelizable problem. A good example task for showing the advantages of parallelization would be one that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Is simple.&lt;/li&gt;
&lt;li&gt;Takes an appreciable amount of CPU time to be completed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The problem of &lt;a href=&quot;https://en.wikipedia.org/wiki/Primality_test&quot;&gt;deciding if a large integer is prime or not&lt;/a&gt; fulfills both characteristics.&lt;/p&gt;
&lt;p&gt;It will be a good idea to split our task into a &lt;strong&gt;function&lt;/strong&gt; (describing WHAT to do) and an &lt;strong&gt;input&lt;/strong&gt; (describing to WHOM).&lt;/p&gt;
&lt;p&gt;In our case, the &lt;strong&gt;function&lt;/strong&gt; performs a test on primality (if you think this is a silly function, you are right, but please see Notes at the end of this tutorial).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fun &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(x) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  numbers&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;isPrime(x) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Requires&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the package numbers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the &lt;strong&gt;input&lt;/strong&gt; is just a vector containing 1000 large integers (that I created programmatically just to not have to type then one-by-one).&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Generate some large integers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Number&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; integers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;min &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Lower&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; bound&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;max &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 10000000000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; #&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Upper&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; boundinputs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sample(min&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;max, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; random large integers (between &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1e5&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1e10&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These two objects, &lt;code&gt;fun&lt;/code&gt; and &lt;code&gt;inputs&lt;/code&gt;, define the &lt;em&gt;homework&lt;/em&gt; we want to assign to our computer (in this case, to decide which integers from the list of inputs are prime). We also want our computer to store the results. We will do this in six different ways, two of them parallel. Later, we’ll compare their performance.&lt;/p&gt;
&lt;h2 id=&quot;possibility-0-run-serially&quot;&gt;Possibility 0: run serially&lt;/h2&gt;
&lt;p&gt;In this section, we’ll see three different ways of solving our problem by running serially. That is, without using parallelization. The user is likely to be familiar with at least some of them.&lt;/p&gt;
&lt;h2 id=&quot;01-run-serially-with-a-loop&quot;&gt;0.1 Run serially with a loop&lt;/h2&gt;
&lt;p&gt;This is the most straightforward approach, although not very efficient. The basic structure is given in the snippet below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results vector&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;for (i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { # Loop one by one along the input elements&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  results[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs[i])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;02-run-serially-with-foreach&quot;&gt;0.2 Run serially with foreach&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;foreach&lt;/code&gt; package saves us the explicit typing of the index (compare with the &lt;code&gt;for&lt;/code&gt; loop in the previous example). The output of &lt;code&gt;foreach&lt;/code&gt; is, by default, a list. We used the parameter &lt;code&gt;.combine = &quot;c&quot;&lt;/code&gt; (concatenate) to return the output as a vector.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Load the required libraries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(foreach)foreach (val &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inputs, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;combine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;c&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%do%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; { &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    fun(val) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Loop&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; one&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;by&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;one using foreach&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;03-run-serially-with-lapply&quot;&gt;0.3 Run serially with lapply&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;lapply&lt;/code&gt; is usually preferred over explicit &lt;code&gt;for&lt;/code&gt; or &lt;code&gt;foreach&lt;/code&gt; loops.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lapply(inputs, fun) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Use&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; lapply instead &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for loop&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;do-it-in-parallel&quot;&gt;Do it in parallel!&lt;/h2&gt;
&lt;p&gt;And now, we’ll finally use parallel programming to solve our problem.&lt;/p&gt;
&lt;h2 id=&quot;possibility-1-run-in-parallel-with-mclapply-linux-only&quot;&gt;Possibility 1: run in parallel with mclapply (Linux only)&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;mclapply&lt;/code&gt; is part of the &lt;code&gt;parallel&lt;/code&gt; library. Rule of thumb: use it instead of &lt;code&gt;lapply&lt;/code&gt;. If the code is parallelizable, it will do the magic:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Load the required libraries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(parallel)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Run&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; parallel&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; mclapply(inputs, fun, mc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cores &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; numCores)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Note that the number of cores is required by mclapply&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, this approach only works on Linux. If you are working on a Windows machine, it will perform as a serial &lt;code&gt;lapply&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;possibility-2-run-in-parallel-with-doparallel--foreach&quot;&gt;Possibility 2: run in parallel with doParallel + foreach&lt;/h2&gt;
&lt;p&gt;Rule of thumb: &lt;code&gt;doParallel&lt;/code&gt; transforms a &lt;code&gt;foreach&lt;/code&gt; loop into a parallel process. Provided, of course, the underlying process is parallelizable.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;# Load the required libraries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(iterators)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;library(doParallel)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;registerDoParallel(numCores)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foreach(val &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inputs, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;combine &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;c&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;dopar&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    fun(val)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; results&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;possibility-3-take-advantage-of-vector-functions&quot;&gt;Possibility 3: take advantage of vector functions&lt;/h2&gt;
&lt;p&gt;Most (but not all) of &lt;code&gt;R&lt;/code&gt; functions can work with vectorized inputs. This means that the function accepts a vector of inputs and returns an equally sized vector of outputs. This allows &lt;em&gt;hiding&lt;/em&gt; the whole &lt;em&gt;loop&lt;/em&gt; in a single, easy-to-read line.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;results &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More importantly, although running serially, vector functions often run faster than parallel schemes. Why not use them always then? The quick answer is: we are not always lucky enough to have a function that accepts a vector input.&lt;/p&gt;
&lt;h2 id=&quot;compare-results&quot;&gt;Compare results&lt;/h2&gt;
&lt;p&gt;In the figure below we plot the execution times of each of the six methods we tried. We also provide a summary table for each of them.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;664&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BeEX_sXEa65n1z1P_0BIvA-d78cecd9.BE94DZz4_Z1epJVk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We notice that the parallel methods performed significantly better than the serial ones. We also notice that the vector method performed even better (but keep in mind not all functions are vectorizable).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pro tip: what about using vectorization AND parallelization?&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;trying-to-parallelize-non-parallelizable-code&quot;&gt;Trying to parallelize non-parallelizable code&lt;/h2&gt;
&lt;p&gt;In this subsection we’ll use the expression below as an example:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;293&quot; height=&quot;40&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ltsKnFbjM5srKhkk7HFn_Q-ce448f4c.QHmW10B0_Z1AcP4P.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It is just a recipe to build a list of numbers by adding 1 to the previous number in the list. It is easy to see that, when initialized with &lt;em&gt;x&lt;/em&gt; 0=0, this iterator yields {0,1,2,3,4,…}. Note that in order to obtain the value a given x in position n, we need to know the value of the previous x (that in position n-1; remember the analogy of building a stack of bricks). This operation is thus intrinsically serial.&lt;/p&gt;
&lt;p&gt;In this case, our function and inputs look like:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fun &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function(x) {x &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; as (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using a serial loop everything works fine:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;foreach(i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%do%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inputs[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs[i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result is the expected&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 3&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what if we insist on parallelizing? After all, our serial loop is very similar to the &lt;code&gt;foreach&lt;/code&gt; + &lt;code&gt;doParallel&lt;/code&gt; one, so it is tempting to at least try. And what happens then? As expected, it simply doesn’t work properly. And more worryingly, doesn’t throw an error either!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; rep(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;NA&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Initialize&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; again&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; 0foreach(i &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;dopar&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  inputs[i] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fun(inputs[i&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; this &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is a disastrous &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; NA&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that was it. This is just a quick starting guide to a complicated topic. If you want to know more, I suggest you go directly to the &lt;a href=&quot;https://github.com/HenrikBengtsson/future&quot;&gt;future&lt;/a&gt; library.&lt;/p&gt;
&lt;h2 id=&quot;notes&quot;&gt;Notes&lt;/h2&gt;
&lt;p&gt;The astute reader may have noticed that our function &lt;code&gt;fun&lt;/code&gt; is a mere renaming of the function &lt;code&gt;isPrime&lt;/code&gt; contained in the package &lt;code&gt;numbers&lt;/code&gt;. The reason for that is merely pedagogical: we want the readers to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Notice that the structure input -&gt; function -&gt; results is indeed VERY general.&lt;/li&gt;
&lt;li&gt;Be able to try their own pieces of slow code inside the body of &lt;code&gt;fun&lt;/code&gt; (this can be done comfortably using our &lt;a href=&quot;https://github.com/PabRod/blog-parallelR&quot;&gt;vignette&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;are-you-more-into-python&quot;&gt;Are you more into Python?&lt;/h2&gt;
&lt;p&gt;We can also help with that! Check out this other tutorial: &lt;a href=&quot;https://blog.esciencecenter.nl/parallel-programming-in-python-7fd62c90217d&quot;&gt;Parallel program in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I want to say thanks to &lt;a href=&quot;https://www.esciencecenter.nl/team/lourens-veen-msc/&quot;&gt;Lourens Veen&lt;/a&gt;, &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-peter-kalverla-2/&quot;&gt;Peter Kalverla&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/team/dr-patrick-bos/&quot;&gt;Patrick Bos&lt;/a&gt;. Their useful comments definitely improved the clarity of the final text.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_3qaXCEcKBHIVpQkMcmtvvg-493b492c.BQH382dC.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Get up to speed with software sustainability — the WOSSS19 report and a look to the future</title><link>https://blog2.esciencecenter.nl/posts/2020-07-23---get-up-to-speed-with-software-sustainability-the-wosss19-rep</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-07-23---get-up-to-speed-with-software-sustainability-the-wosss19-rep</guid><description>&lt;p&gt;The audience discussed topics raised by the introductions, and as part of this they wrote material for the report in a process adapted from the &lt;a href=&quot;https://www.software.ac.uk/speed-blogging-and-tips-writing-speed-blog-post&quot;&gt;speed blogging&lt;/a&gt; approach. Those who spoke or contributed to the discussions are therefore all authors on the report. There were a number of review cycles after the workshop guided by the report editors (Shoaib, Carlos, Cees and Patrick).&lt;/p&gt;
&lt;p&gt;There were six key areas of specific recommendation in the workshop report. These are in terms of credit, cultural heritage, FAIR software, funding, policy and training. Some of the findings are detailed below (for the complete set, see section 4 of &lt;a href=&quot;https://zenodo.org/record/3922155&quot;&gt;the report&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The efforts around FAIRification of software, i.e. the FAIR principles being applied to software, have implications far beyond just researchers as they impact funders and journals. There should therefore be joint efforts to move this work forward.&lt;/p&gt;
&lt;p&gt;At a policy level, software sustainability efforts and co-ordination across Europe need to be a priority and properly funded if we are to reuse practice and level up regions that are not active in this space.&lt;/p&gt;
&lt;p&gt;Credit for software and the associated citation mechanisms are far from being a solved problem, even though significant effort has already been spent in this area. Getting this right remains a priority for the appropriate type and weight of credit to be attributed to software and the right stakeholders need to be involved.&lt;/p&gt;
&lt;p&gt;The cultural heritage sector is unique in its purpose to preserve culture, thus technology choices should be made which align to its goals. It is noted that pressures on commercial software providers can be at odds with these goals.&lt;/p&gt;
&lt;p&gt;Training remains central to sustainability efforts and it should address all levels of practice. Best practices for curricula development and growing capacity (e.g. increasing the number of instructors) should be learnt from initiatives such as &lt;a href=&quot;https://carpentries.org/&quot;&gt;The Carpentries&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The report is available at &lt;a href=&quot;https://zenodo.org/record/3922155&quot;&gt;Zenodo&lt;/a&gt; (if you are short on time, read section 4, ‘Executive summary and key recommendations’). Take part in the conversation on &lt;a href=&quot;https://twitter.com/SoftwareSaved/status/1280870136807817217&quot;&gt;Twitter&lt;/a&gt;. Comments are welcome, please contact &lt;a href=&quot;mailto:shoaib.sufi@manchester.ac.uk&quot;&gt;Shoaib Sufi&lt;/a&gt; from the WOSSS19 editors group.&lt;/p&gt;
&lt;p&gt;The Workshop on Sustainable Software Sustainability 2021 (WOSSS21) is being planned for quarter three of 2021 as an in-person event at the University of Manchester, UK. The overarching themes and communities of the WOSSS initiative and the WOSSS21 workshop are research software, legacy systems and the cultural heritage sector. If you would like to hear when more details on WOSSS21 become available please &lt;a href=&quot;https://bit.ly/wosss21-expression-of-interest&quot;&gt;complete this form&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Want to discuss this post with us? *&lt;a href=&quot;mailto:info%40software.ac.uk&quot;&gt;*Send us an email *&lt;/a&gt;&lt;em&gt;or contact us on &lt;em&gt;&lt;a href=&quot;https://www.twitter.com/SoftwareSaved&quot;&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; @SoftwareSaved.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 23 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The audience discussed topics raised by the introductions, and as part of this they wrote material for the report in a process adapted from the &lt;a href=&quot;https://www.software.ac.uk/speed-blogging-and-tips-writing-speed-blog-post&quot;&gt;speed blogging&lt;/a&gt; approach. Those who spoke or contributed to the discussions are therefore all authors on the report. There were a number of review cycles after the workshop guided by the report editors (Shoaib, Carlos, Cees and Patrick).&lt;/p&gt;
&lt;p&gt;There were six key areas of specific recommendation in the workshop report. These are in terms of credit, cultural heritage, FAIR software, funding, policy and training. Some of the findings are detailed below (for the complete set, see section 4 of &lt;a href=&quot;https://zenodo.org/record/3922155&quot;&gt;the report&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The efforts around FAIRification of software, i.e. the FAIR principles being applied to software, have implications far beyond just researchers as they impact funders and journals. There should therefore be joint efforts to move this work forward.&lt;/p&gt;
&lt;p&gt;At a policy level, software sustainability efforts and co-ordination across Europe need to be a priority and properly funded if we are to reuse practice and level up regions that are not active in this space.&lt;/p&gt;
&lt;p&gt;Credit for software and the associated citation mechanisms are far from being a solved problem, even though significant effort has already been spent in this area. Getting this right remains a priority for the appropriate type and weight of credit to be attributed to software and the right stakeholders need to be involved.&lt;/p&gt;
&lt;p&gt;The cultural heritage sector is unique in its purpose to preserve culture, thus technology choices should be made which align to its goals. It is noted that pressures on commercial software providers can be at odds with these goals.&lt;/p&gt;
&lt;p&gt;Training remains central to sustainability efforts and it should address all levels of practice. Best practices for curricula development and growing capacity (e.g. increasing the number of instructors) should be learnt from initiatives such as &lt;a href=&quot;https://carpentries.org/&quot;&gt;The Carpentries&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The report is available at &lt;a href=&quot;https://zenodo.org/record/3922155&quot;&gt;Zenodo&lt;/a&gt; (if you are short on time, read section 4, ‘Executive summary and key recommendations’). Take part in the conversation on &lt;a href=&quot;https://twitter.com/SoftwareSaved/status/1280870136807817217&quot;&gt;Twitter&lt;/a&gt;. Comments are welcome, please contact &lt;a href=&quot;mailto:shoaib.sufi@manchester.ac.uk&quot;&gt;Shoaib Sufi&lt;/a&gt; from the WOSSS19 editors group.&lt;/p&gt;
&lt;p&gt;The Workshop on Sustainable Software Sustainability 2021 (WOSSS21) is being planned for quarter three of 2021 as an in-person event at the University of Manchester, UK. The overarching themes and communities of the WOSSS initiative and the WOSSS21 workshop are research software, legacy systems and the cultural heritage sector. If you would like to hear when more details on WOSSS21 become available please &lt;a href=&quot;https://bit.ly/wosss21-expression-of-interest&quot;&gt;complete this form&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Want to discuss this post with us? *&lt;a href=&quot;mailto:info%40software.ac.uk&quot;&gt;*Send us an email *&lt;/a&gt;&lt;em&gt;or contact us on &lt;em&gt;&lt;a href=&quot;https://www.twitter.com/SoftwareSaved&quot;&gt;&lt;em&gt;Twitter&lt;/em&gt;&lt;/a&gt;&lt;/em&gt; @SoftwareSaved.&lt;/em&gt;&lt;/p&gt;</content:encoded><author>Netherlands eScience Center</author></item><item><title>Machine learning: when it is easy &amp;amp; when it is difficult</title><link>https://blog2.esciencecenter.nl/posts/2020-06-18---machine-learning-when-it-is-easy-amp-when-it-is-difficult</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-06-18---machine-learning-when-it-is-easy-amp-when-it-is-difficult</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Hey, should I draw a wild curve that splits all points exactly?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;369&quot; height=&quot;336&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-a569527f.Df3mtEmN_Z64VS9.webp&quot; srcset=&quot;&quot;&gt;
But how am I sure that the curve will split properly all new points that I haven’t seen, that it will not over-fit* on the training data? I tried lots of methods (SVM, neural networks, random forests…) and still I don’t get good results on my test points, even though I kept some of the training data as a “control” dataset during training.&lt;/p&gt;
&lt;p&gt;Wait. Why would I draw curves? Every time I have a new point for which I don’t know whether it is good or bad, I can just look into the neighborhood and label my point as the neighbors (“k-nearest neighbors method”).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;349&quot; height=&quot;318&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-aacd51ae.CotToNZe_17SmGS.webp&quot; srcset=&quot;&quot;&gt;
But how many neighbors should I look at? One, two, three? They all have different labels. And what is a neighbor by the way? Yes, in 2D it is easy but my points are not in 2D actually.&lt;/p&gt;
&lt;p&gt;Wait, how am I sure that I chose the right features to represent my data? Maybe my data looks so messy because the features are not helping into classifying my objects in good and bad. Ah, what a mess, I should start all over with new features! Or maybe I should craft completely new features?&lt;/p&gt;
&lt;p&gt;A-ha. Features. Why are we still talking about features when everybody knows that &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;deep neural networks&lt;/a&gt; don’t need features? They take as input directly your data and learn everything by themselves. If you have enough properly labeled data, you barely need to do anything. Maybe you need to watch for over-fitting and under-fitting by using a part of your ground truth data as a control set, and tweak the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning)&quot;&gt;hyper-parameters&lt;/a&gt; of the network, that is, the parameters that are not automatically learned by the network, until you get desired results. But that’s about it, it is all straightforward. Even the parameter tweaking is being &lt;a href=&quot;https://en.wikipedia.org/wiki/Automated_machine_learning&quot;&gt;automated&lt;/a&gt; nowadays. So, ML is easy again!&lt;/p&gt;
&lt;p&gt;It used to be so, when all you were doing was classifying images. On the &lt;a href=&quot;http://www.image-net.org/&quot;&gt;ImageNet&lt;/a&gt; dataset. On the input you put a picture of a robot or a man. On the output you tell the network what the picture is. In-between the network tries to adapt its “weights” by seeing many examples of robots or men and using calculus methods. Ultimately it finds which weights are best to go from a picture to a label with as few mistakes as possible.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;215&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-2910710e.4WToM5O5_1lfom1.webp&quot; srcset=&quot;&quot;&gt;
That would be level 1.0. We opened a new chapter: deep learning.&lt;/p&gt;
&lt;p&gt;Level 1.1 is when your input is not a picture or text, or anything else for which off-the-shelve neural networks exist. It is some kind of a special object of type X and there are no neural network architectures that can handle it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;365&quot; height=&quot;119&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-e3c843b0.BeuQIcQ5_1o3J5k.webp&quot; srcset=&quot;&quot;&gt;
What do you do? Do you try to convert your object into a picture, or a sequence, or? But then what is the best way to convert it so that the neural network can do its job? And what kind of neural network? And how do you best design this conversion, or features, for your neural network? Oh no, features again! Maybe I can try to design a new type of neural network to address my original objects of type X. You wish. That’s level 5.&lt;/p&gt;
&lt;p&gt;Level 1.2 is when you are not trying to classify, but instead to map your input object to an arbitrary representation of it that suits your problem. From object X at the input to object X’ at the output. Lots of practical problems are of this type.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;110&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-2e04ff2a.BCr8riTs_qes4g.webp&quot; srcset=&quot;&quot;&gt;
Then you need to figure out what the network should learn. It is easy when you classify, the network needs to learn the label *good *or &lt;em&gt;bad&lt;/em&gt;. In the general case, learning to map from X to X’, you want the output to be as close to X’ as possible. Nice, what’s the problem? The problem is what you mean by “close”. We are back to the “neighbours” problem (see level 0.2). Remember, what works in a 2D space, does not work in an arbitrary space (in math, or ML, this is called “&lt;a href=&quot;https://en.wikipedia.org/wiki/Curse_of_dimensionality&quot;&gt;the curse of dimensionality&lt;/a&gt;”).&lt;/p&gt;
&lt;p&gt;One can go to even higher levels, where the class of problems is different than classification or mapping from representation X to X’. E.g. when you try to &lt;a href=&quot;https://towardsdatascience.com/deep-generative-models-25ab2821afd3#:~:text=A%20Generative%20Model%20is%20a,data%20points%20with%20some%20variations.&quot;&gt;generate&lt;/a&gt; new data that looks realistic (what do you mean by realistic, then?), i.e. deep generative models, or when you try to come up with a best automated strategy to achieve a goal, i.e. deep reinforcement learning.&lt;/p&gt;
&lt;p&gt;There are many applications of neural networks and machine learning, and here we only scratched the surface. And we did not even touch unsupervised learning. See, here the learning was always done using some ground truth (supervised).&lt;/p&gt;
&lt;p&gt;And, for sure, there is no upper limit on the number of levels!&lt;/p&gt;</description><pubDate>Thu, 18 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Hey, should I draw a wild curve that splits all points exactly?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;369&quot; height=&quot;336&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-a569527f.Df3mtEmN_Z64VS9.webp&quot; srcset=&quot;&quot;&gt;
But how am I sure that the curve will split properly all new points that I haven’t seen, that it will not over-fit* on the training data? I tried lots of methods (SVM, neural networks, random forests…) and still I don’t get good results on my test points, even though I kept some of the training data as a “control” dataset during training.&lt;/p&gt;
&lt;p&gt;Wait. Why would I draw curves? Every time I have a new point for which I don’t know whether it is good or bad, I can just look into the neighborhood and label my point as the neighbors (“k-nearest neighbors method”).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;349&quot; height=&quot;318&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-aacd51ae.CotToNZe_17SmGS.webp&quot; srcset=&quot;&quot;&gt;
But how many neighbors should I look at? One, two, three? They all have different labels. And what is a neighbor by the way? Yes, in 2D it is easy but my points are not in 2D actually.&lt;/p&gt;
&lt;p&gt;Wait, how am I sure that I chose the right features to represent my data? Maybe my data looks so messy because the features are not helping into classifying my objects in good and bad. Ah, what a mess, I should start all over with new features! Or maybe I should craft completely new features?&lt;/p&gt;
&lt;p&gt;A-ha. Features. Why are we still talking about features when everybody knows that &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;deep neural networks&lt;/a&gt; don’t need features? They take as input directly your data and learn everything by themselves. If you have enough properly labeled data, you barely need to do anything. Maybe you need to watch for over-fitting and under-fitting by using a part of your ground truth data as a control set, and tweak the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning)&quot;&gt;hyper-parameters&lt;/a&gt; of the network, that is, the parameters that are not automatically learned by the network, until you get desired results. But that’s about it, it is all straightforward. Even the parameter tweaking is being &lt;a href=&quot;https://en.wikipedia.org/wiki/Automated_machine_learning&quot;&gt;automated&lt;/a&gt; nowadays. So, ML is easy again!&lt;/p&gt;
&lt;p&gt;It used to be so, when all you were doing was classifying images. On the &lt;a href=&quot;http://www.image-net.org/&quot;&gt;ImageNet&lt;/a&gt; dataset. On the input you put a picture of a robot or a man. On the output you tell the network what the picture is. In-between the network tries to adapt its “weights” by seeing many examples of robots or men and using calculus methods. Ultimately it finds which weights are best to go from a picture to a label with as few mistakes as possible.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;215&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-2910710e.4WToM5O5_1lfom1.webp&quot; srcset=&quot;&quot;&gt;
That would be level 1.0. We opened a new chapter: deep learning.&lt;/p&gt;
&lt;p&gt;Level 1.1 is when your input is not a picture or text, or anything else for which off-the-shelve neural networks exist. It is some kind of a special object of type X and there are no neural network architectures that can handle it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;365&quot; height=&quot;119&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-e3c843b0.BeuQIcQ5_1o3J5k.webp&quot; srcset=&quot;&quot;&gt;
What do you do? Do you try to convert your object into a picture, or a sequence, or? But then what is the best way to convert it so that the neural network can do its job? And what kind of neural network? And how do you best design this conversion, or features, for your neural network? Oh no, features again! Maybe I can try to design a new type of neural network to address my original objects of type X. You wish. That’s level 5.&lt;/p&gt;
&lt;p&gt;Level 1.2 is when you are not trying to classify, but instead to map your input object to an arbitrary representation of it that suits your problem. From object X at the input to object X’ at the output. Lots of practical problems are of this type.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Machine learning: when it is easy &amp;amp;#x26; when it is difficult&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;110&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-2e04ff2a.BCr8riTs_qes4g.webp&quot; srcset=&quot;&quot;&gt;
Then you need to figure out what the network should learn. It is easy when you classify, the network needs to learn the label *good *or &lt;em&gt;bad&lt;/em&gt;. In the general case, learning to map from X to X’, you want the output to be as close to X’ as possible. Nice, what’s the problem? The problem is what you mean by “close”. We are back to the “neighbours” problem (see level 0.2). Remember, what works in a 2D space, does not work in an arbitrary space (in math, or ML, this is called “&lt;a href=&quot;https://en.wikipedia.org/wiki/Curse_of_dimensionality&quot;&gt;the curse of dimensionality&lt;/a&gt;”).&lt;/p&gt;
&lt;p&gt;One can go to even higher levels, where the class of problems is different than classification or mapping from representation X to X’. E.g. when you try to &lt;a href=&quot;https://towardsdatascience.com/deep-generative-models-25ab2821afd3#:~:text=A%20Generative%20Model%20is%20a,data%20points%20with%20some%20variations.&quot;&gt;generate&lt;/a&gt; new data that looks realistic (what do you mean by realistic, then?), i.e. deep generative models, or when you try to come up with a best automated strategy to achieve a goal, i.e. deep reinforcement learning.&lt;/p&gt;
&lt;p&gt;There are many applications of neural networks and machine learning, and here we only scratched the surface. And we did not even touch unsupervised learning. See, here the learning was always done using some ground truth (supervised).&lt;/p&gt;
&lt;p&gt;And, for sure, there is no upper limit on the number of levels!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/machine-learning-when-it-is-easy-amp-whe-aacd51ae.CotToNZe.png" medium="image"/><author>Sonja Georgievska</author></item><item><title>Machine learning when it is easy &amp; when it is difficult</title><link>https://blog2.esciencecenter.nl/posts/2020-06-18---machine-learning-when-it-is-easy-when-it-is-difficult</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-06-18---machine-learning-when-it-is-easy-when-it-is-difficult</guid><description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;A crash course in machine learning; only high-school level of math is required before reading.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;988&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_gkZdPqJd5cZmoPeP-42c6d9ad.B-I-wYIH_gyaHj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Element5 Digital on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Machine_learning&quot;&gt;Machine learning&lt;/a&gt; (ML) is about having the computer learn how to convert input into output (or to make predictions), based on sample data, known as training data. In this article, I’ll introduce you to the basics of ML, and show you that, however, there’s more to it than having the machine &lt;em&gt;learning it all&lt;/em&gt; by itself.&lt;/p&gt;
&lt;p&gt;Let us start with the basic ML problem: classification. Imagine you have a lot of objects of the same type (data) and you want your computer to learn how to classify each object into good or bad. Usually you already have a lot of objects for which you know whether they are good or bad (“ground truth”) and you want to be able to predict for every new object that you come upon whether it is good or bad.&lt;/p&gt;
&lt;p&gt;So far so good. For simplicity, it is convenient to imagine that you can represent each of your objects with two numbers (features, or variables), x and y. In real life the objects are much more complex than that (can you represent the content of an image with two numbers?), but for the purpose of explaining this is enough. This way every object is a point (x,y) in a 2D plane.&lt;/p&gt;
&lt;p&gt;In the following plots, assume that your good points are the check-marks and your bad points are the crosses.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;362&quot; height=&quot;288&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2UduKkf8td0c97TDb011BQ-24c9dbf3.Bn0uo-hQ_Zc7Ksv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The problem of classification then becomes one of drawing a line (or curve) in the graph such that all good points are on one side of the curve and all bad points are on the other side. How difficult can it be? Here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;305&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iTOMTOe1ePrbBsR1s5I3xg-bce9b1d7.DUG1-uhk_lAMzu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Congratulations! You have reached machine learning, level 0.0.&lt;/p&gt;
&lt;p&gt;Let’s go to level 0.1. You want to try your fresh ML model in practice on new points. How well will it predict on new points? Suddenly, the new points are on the wrong side of the line!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;313&quot; height=&quot;287&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lpiKpseZ0J6Y3Z2ghBq4jg-41b795c1.D9I7CTvR_ZBwdSw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What happened? You trained the model on too few data points. Or someone cherry-picked the points on which you train. Or you did not use a generic enough data-set for training. Anyway, after seeing the new points you wish you had used a circle instead of a line.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;317&quot; height=&quot;280&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bb-sfqrHrRQOhLS7RDVgyw-3dbc70a3.C1Vut0bc_ZvrsJb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Or you don’t wish anything, because, remember, your data in reality is not a point in a 2-dimensional plane and you could not see that. If data objects were points in a 2-dimensional plane, there would have never been need for machine learning. In reality you need much more features to represent your data, but we cannot plot 10-dimensional plots.&lt;/p&gt;
&lt;p&gt;Level 0.2 is when your good and bad points look something like this (but remember, you would not know that, because your data is not really in 2D).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;358&quot; height=&quot;315&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rIwRK7l0w4iRQEu8Hxz7sw-033c6ae7.PmZCBfZN_ZShHzW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Should I draw a line? Should I draw a circle? But then I have too many errors. (underfitting).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;284&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8nQdld5t2XinIJOfvl3TYQ-47e83c92.DMeYDFKv_p4d8G.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Are those points errors indeed or were they wrongly labeled in the first place by e.g. the lab staff? How am I supposed to know? How are the staff supposed to know, if they have to rely on lab technology for labeling?&lt;/p&gt;
&lt;p&gt;Hey, should I draw a wild curve that splits all points exactly?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;369&quot; height=&quot;336&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gSEEUQPFbMeGJNHytZBbCg-d1f8fb14.CyQQ58by_Z27DurI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But how am I sure that the curve will split properly all new points that I haven’t seen, that it will not &lt;em&gt;over-fit&lt;/em&gt; on the training data? I tried lots of methods (SVM, neural networks, random forests…) and still I don’t get good results on my test points, even though I kept some of the training data as a “control” dataset during training.&lt;/p&gt;
&lt;p&gt;Wait. Why would I draw curves? Every time I have a new point for which I don’t know whether it is good or bad, I can just look into the neighborhood and label my point as the neighbors (“k-nearest neighbors method”).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;349&quot; height=&quot;318&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Q9eWWK4bH5y4imz682tQgg-d1bb9c85.6RdJvSOU_rfQ9E.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But how many neighbors should I look at? One, two, three? They all have different labels. And what is a neighbor by the way? Yes, in 2D it is easy but my points are not in 2D actually.&lt;/p&gt;
&lt;p&gt;Wait, how am I sure that I chose the right features to represent my data? Maybe my data looks so messy because the features are not helping into classifying my objects in good and bad. Ah, what a mess, I should start all over with new features! Or maybe I should craft completely new features?&lt;/p&gt;
&lt;p&gt;A-ha. Features. Why are we still talking about features when everybody knows that &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;deep neural networks&lt;/a&gt; don’t need features? They take as input directly your data and learn everything by themselves. If you have enough properly labeled data, you barely need to do anything. Maybe you need to watch for over-fitting and under-fitting by using a part of your ground truth data as a control set, and tweak the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning)&quot;&gt;hyper-parameters&lt;/a&gt; of the network, that is, the parameters that are not automatically learned by the network, until you get desired results. But that’s about it, it is all straightforward. Even the parameter tweaking is being &lt;a href=&quot;https://en.wikipedia.org/wiki/Automated_machine_learning&quot;&gt;automated&lt;/a&gt; nowadays. So, ML is easy again!&lt;/p&gt;
&lt;p&gt;It used to be so, when all you were doing was classifying images. On the &lt;a href=&quot;http://www.image-net.org/&quot;&gt;ImageNet&lt;/a&gt; dataset. On the input you put a picture of a robot or a man. On the output you tell the network what the picture is. In-between the network tries to adapt its “weights” by seeing many examples of robots or men and using calculus methods. Ultimately it finds which weights are best to go from a picture to a label with as few mistakes as possible.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;246&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_fo3bHw6SDRfaGHBO-d057219a.CWjg7kX9_ZPow3U.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That would be level 1.0. We opened a new chapter: deep learning.&lt;/p&gt;
&lt;p&gt;Level 1.1 is when your input is not a picture or text, or anything else for which off-the-shelve neural networks exist. It is some kind of a special object of type X and there are no neural network architectures that can handle it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;365&quot; height=&quot;119&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vGInRnL95lhk9W2kKutX5g-2ced40d6.ChT6Tei1_ZWl0K2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What do you do? Do you try to convert your object into a picture, or a sequence, or? But then what is the best way to convert it so that the neural network can do its job? And what kind of neural network? And how do you best design this conversion, or features, for your neural network? Oh no, features again! Maybe I can try to design a new type of neural network to address my original objects of type X. You wish. That’s level 5.&lt;/p&gt;
&lt;p&gt;Level 1.2 is when you are not trying to classify, but instead to map your input object to an arbitrary representation of it that suits your problem. From object X at the input to object X’ at the output. Lots of practical problems are of this type.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;110&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RkUVolMiiYiVg0x4EI25_Q-63f07cef.DDYXL6aN_18GV2L.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Then you need to figure out what the network should learn. It is easy when you classify, the network needs to learn the label &lt;em&gt;good&lt;/em&gt; or &lt;em&gt;bad&lt;/em&gt;. In the general case, learning to map from X to X’, you want the output to be as close to X’ as possible. Nice, what’s the problem? The problem is what you mean by “close”. We are back to the “neighbours” problem (see level 0.2). Remember, what works in a 2D space, does not work in an arbitrary space (in math, or ML, this is called “ &lt;a href=&quot;https://en.wikipedia.org/wiki/Curse_of_dimensionality&quot;&gt;the curse of dimensionality&lt;/a&gt; ”).&lt;/p&gt;
&lt;p&gt;One can go to even higher levels, where the class of problems is different than classification or mapping from representation X to X’. E.g. when you try to &lt;a href=&quot;https://towardsdatascience.com/deep-generative-models-25ab2821afd3#:~:text=A%20Generative%20Model%20is%20a,data%20points%20with%20some%20variations.&quot;&gt;generate&lt;/a&gt; new data that looks realistic (what do you mean by realistic, then?), i.e. deep generative models, or when you try to come up with a best automated strategy to achieve a goal, i.e. deep reinforcement learning.&lt;/p&gt;
&lt;p&gt;There are many applications of neural networks and machine learning, and here we only scratched the surface. And we did not even touch unsupervised learning. See, here the learning was always done using some ground truth (supervised).&lt;/p&gt;
&lt;p&gt;And, for sure, there is no upper limit on the number of levels!&lt;/p&gt;</description><pubDate>Thu, 18 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;&lt;strong&gt;A crash course in machine learning; only high-school level of math is required before reading.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;988&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_gkZdPqJd5cZmoPeP-42c6d9ad.B-I-wYIH_gyaHj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Element5 Digital on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Machine_learning&quot;&gt;Machine learning&lt;/a&gt; (ML) is about having the computer learn how to convert input into output (or to make predictions), based on sample data, known as training data. In this article, I’ll introduce you to the basics of ML, and show you that, however, there’s more to it than having the machine &lt;em&gt;learning it all&lt;/em&gt; by itself.&lt;/p&gt;
&lt;p&gt;Let us start with the basic ML problem: classification. Imagine you have a lot of objects of the same type (data) and you want your computer to learn how to classify each object into good or bad. Usually you already have a lot of objects for which you know whether they are good or bad (“ground truth”) and you want to be able to predict for every new object that you come upon whether it is good or bad.&lt;/p&gt;
&lt;p&gt;So far so good. For simplicity, it is convenient to imagine that you can represent each of your objects with two numbers (features, or variables), x and y. In real life the objects are much more complex than that (can you represent the content of an image with two numbers?), but for the purpose of explaining this is enough. This way every object is a point (x,y) in a 2D plane.&lt;/p&gt;
&lt;p&gt;In the following plots, assume that your good points are the check-marks and your bad points are the crosses.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;362&quot; height=&quot;288&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2UduKkf8td0c97TDb011BQ-24c9dbf3.Bn0uo-hQ_Zc7Ksv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The problem of classification then becomes one of drawing a line (or curve) in the graph such that all good points are on one side of the curve and all bad points are on the other side. How difficult can it be? Here.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;305&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iTOMTOe1ePrbBsR1s5I3xg-bce9b1d7.DUG1-uhk_lAMzu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Congratulations! You have reached machine learning, level 0.0.&lt;/p&gt;
&lt;p&gt;Let’s go to level 0.1. You want to try your fresh ML model in practice on new points. How well will it predict on new points? Suddenly, the new points are on the wrong side of the line!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;313&quot; height=&quot;287&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lpiKpseZ0J6Y3Z2ghBq4jg-41b795c1.D9I7CTvR_ZBwdSw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What happened? You trained the model on too few data points. Or someone cherry-picked the points on which you train. Or you did not use a generic enough data-set for training. Anyway, after seeing the new points you wish you had used a circle instead of a line.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;317&quot; height=&quot;280&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bb-sfqrHrRQOhLS7RDVgyw-3dbc70a3.C1Vut0bc_ZvrsJb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Or you don’t wish anything, because, remember, your data in reality is not a point in a 2-dimensional plane and you could not see that. If data objects were points in a 2-dimensional plane, there would have never been need for machine learning. In reality you need much more features to represent your data, but we cannot plot 10-dimensional plots.&lt;/p&gt;
&lt;p&gt;Level 0.2 is when your good and bad points look something like this (but remember, you would not know that, because your data is not really in 2D).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;358&quot; height=&quot;315&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rIwRK7l0w4iRQEu8Hxz7sw-033c6ae7.PmZCBfZN_ZShHzW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Should I draw a line? Should I draw a circle? But then I have too many errors. (underfitting).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;284&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8nQdld5t2XinIJOfvl3TYQ-47e83c92.DMeYDFKv_p4d8G.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Are those points errors indeed or were they wrongly labeled in the first place by e.g. the lab staff? How am I supposed to know? How are the staff supposed to know, if they have to rely on lab technology for labeling?&lt;/p&gt;
&lt;p&gt;Hey, should I draw a wild curve that splits all points exactly?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;369&quot; height=&quot;336&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gSEEUQPFbMeGJNHytZBbCg-d1f8fb14.CyQQ58by_Z27DurI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But how am I sure that the curve will split properly all new points that I haven’t seen, that it will not &lt;em&gt;over-fit&lt;/em&gt; on the training data? I tried lots of methods (SVM, neural networks, random forests…) and still I don’t get good results on my test points, even though I kept some of the training data as a “control” dataset during training.&lt;/p&gt;
&lt;p&gt;Wait. Why would I draw curves? Every time I have a new point for which I don’t know whether it is good or bad, I can just look into the neighborhood and label my point as the neighbors (“k-nearest neighbors method”).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;349&quot; height=&quot;318&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Q9eWWK4bH5y4imz682tQgg-d1bb9c85.6RdJvSOU_rfQ9E.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But how many neighbors should I look at? One, two, three? They all have different labels. And what is a neighbor by the way? Yes, in 2D it is easy but my points are not in 2D actually.&lt;/p&gt;
&lt;p&gt;Wait, how am I sure that I chose the right features to represent my data? Maybe my data looks so messy because the features are not helping into classifying my objects in good and bad. Ah, what a mess, I should start all over with new features! Or maybe I should craft completely new features?&lt;/p&gt;
&lt;p&gt;A-ha. Features. Why are we still talking about features when everybody knows that &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;deep neural networks&lt;/a&gt; don’t need features? They take as input directly your data and learn everything by themselves. If you have enough properly labeled data, you barely need to do anything. Maybe you need to watch for over-fitting and under-fitting by using a part of your ground truth data as a control set, and tweak the &lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_(machine_learning)&quot;&gt;hyper-parameters&lt;/a&gt; of the network, that is, the parameters that are not automatically learned by the network, until you get desired results. But that’s about it, it is all straightforward. Even the parameter tweaking is being &lt;a href=&quot;https://en.wikipedia.org/wiki/Automated_machine_learning&quot;&gt;automated&lt;/a&gt; nowadays. So, ML is easy again!&lt;/p&gt;
&lt;p&gt;It used to be so, when all you were doing was classifying images. On the &lt;a href=&quot;http://www.image-net.org/&quot;&gt;ImageNet&lt;/a&gt; dataset. On the input you put a picture of a robot or a man. On the output you tell the network what the picture is. In-between the network tries to adapt its “weights” by seeing many examples of robots or men and using calculus methods. Ultimately it finds which weights are best to go from a picture to a label with as few mistakes as possible.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;246&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_fo3bHw6SDRfaGHBO-d057219a.CWjg7kX9_ZPow3U.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That would be level 1.0. We opened a new chapter: deep learning.&lt;/p&gt;
&lt;p&gt;Level 1.1 is when your input is not a picture or text, or anything else for which off-the-shelve neural networks exist. It is some kind of a special object of type X and there are no neural network architectures that can handle it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;365&quot; height=&quot;119&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vGInRnL95lhk9W2kKutX5g-2ced40d6.ChT6Tei1_ZWl0K2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What do you do? Do you try to convert your object into a picture, or a sequence, or? But then what is the best way to convert it so that the neural network can do its job? And what kind of neural network? And how do you best design this conversion, or features, for your neural network? Oh no, features again! Maybe I can try to design a new type of neural network to address my original objects of type X. You wish. That’s level 5.&lt;/p&gt;
&lt;p&gt;Level 1.2 is when you are not trying to classify, but instead to map your input object to an arbitrary representation of it that suits your problem. From object X at the input to object X’ at the output. Lots of practical problems are of this type.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;359&quot; height=&quot;110&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RkUVolMiiYiVg0x4EI25_Q-63f07cef.DDYXL6aN_18GV2L.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Then you need to figure out what the network should learn. It is easy when you classify, the network needs to learn the label &lt;em&gt;good&lt;/em&gt; or &lt;em&gt;bad&lt;/em&gt;. In the general case, learning to map from X to X’, you want the output to be as close to X’ as possible. Nice, what’s the problem? The problem is what you mean by “close”. We are back to the “neighbours” problem (see level 0.2). Remember, what works in a 2D space, does not work in an arbitrary space (in math, or ML, this is called “ &lt;a href=&quot;https://en.wikipedia.org/wiki/Curse_of_dimensionality&quot;&gt;the curse of dimensionality&lt;/a&gt; ”).&lt;/p&gt;
&lt;p&gt;One can go to even higher levels, where the class of problems is different than classification or mapping from representation X to X’. E.g. when you try to &lt;a href=&quot;https://towardsdatascience.com/deep-generative-models-25ab2821afd3#:~:text=A%20Generative%20Model%20is%20a,data%20points%20with%20some%20variations.&quot;&gt;generate&lt;/a&gt; new data that looks realistic (what do you mean by realistic, then?), i.e. deep generative models, or when you try to come up with a best automated strategy to achieve a goal, i.e. deep reinforcement learning.&lt;/p&gt;
&lt;p&gt;There are many applications of neural networks and machine learning, and here we only scratched the surface. And we did not even touch unsupervised learning. See, here the learning was always done using some ground truth (supervised).&lt;/p&gt;
&lt;p&gt;And, for sure, there is no upper limit on the number of levels!&lt;/p&gt;</content:encoded><media:content url="data:image/png;base64,UklGRuoMAABXRUJQVlA4WAoAAAAIAAAAaQEAHwEAVlA4IAoMAACQSwCdASpqASABPnU4l0mkoyIhInQpmJAOiWdu4XVL8vFxfE/lp7J9ofvGy0FT7Af3/3EfPz0AeYB+svSI8wH7R/s77XP7Ae6X9pPYA/V/rH/QX/aj00v2q+ED9uf2h+Av9qv/NrQPi/+x9rn+X6Hn19+k/s5yRIjvx/7DfuP7B6Cd6/AC9lf6HeCQAfV7vwdRfBZ/Yf+R6x98z5l7Av8v/tfnv513pr2D/5j/dP+j65Xre/cD2Kv21FHazfYZu7PrlKl3zipB5JQqXfCR90utPXQZ3V7eSUKl3zipB5JQPOYRfT+yBKGy3L0lXHML7Zlu1S/ZB0bvrSpoHuuEiSwBQXunfpTuIsDjrsA65nOWeJ09MsqpfqvjFBnFQwFCOy4CQbQ/54n5k38cOImIlsRKFS74b7EtJah+Wy4HvRf2qE0JdH2XXcBgclLFfyeixKSxJd84dU9G04rmfezJepdK9NvmJg78Ik8W0abifzZBh7I39jJy0fIkY5fcuP8DQOT2cRYSewN+T6ABb0JIVZVS+cWYMH0SWmKCpJiqOJDNRO9sX9nAroq0r/L4sKQms8rqkcGVpB5JJ3uA+iPfOsg3pPpDfx7MplXBdPbs6A5lJQKpykpZGSXfOHVPSMg5bJUZou2EIahFTg+i47LKktK14FPV+TFi4S75xUg8aTVZx2WVUv2QeSUKIP9SkBv7IPJKFS74cHEkoVLvnFSDyShRB/qUgN/ZB5JQqWzYTOWv0I3iksL40ICWljzecEtLHm84JaQXsGCWjWHfnhALeAAh5fKEmHDfzJYcN/MlhwnSjqMFGQYAAP7wsKHWbLCJ/LQJklSyslfMrI2suDDLP7FLN7pLZ8D5WC6K/xnPDeidK39UeBf2gCMYEy93VkvRlpsT77dND+B5MwHI+7XcPb6BTsb1DIpy/aXN/+xL6xJ6qGin308uJnmsJUdzP7MHRmd01s9e0ZnWAW7RFl/7KsD+Rq4qclFqj/zGf/Iq414kt7wXPTksqR6JpDmHyr4EP+v3k3JY4PE/cWzAV6DGma4Xl4zvXR8Y5P6xIZnCfFTYqvtuevKjplpRCSgy8phlzwD119dAWNmWIULFbzqriaQKtklcuiProI2XCoXZHFBCPPqM+4p+/4i36zU4KZXQ3kQHjppcX9GcsAjIU3LZHtioJQLMQ8vC2+zU45IJYqtcbM+x5KKAOpnRaJkFeEgRDP/EmcW98QcMsBJs35PAk5XzqrEVGHqFYQmzaX1L7QyDmhcAHpWhsWFfdjld9R8tOy2a5+796xN6uBcxUkHRUQKdsk31my3mt+MWLACWXb/ozb4J9L9CnUDEgpT/I7MjccOJ7JRoJg6aB/3rPnGXtY3U61FhJTrb990OUI2pr8ok/xlRRLxryUvHmhhtrIIPQ3kLAd+mnv4JJ3n5NFubiOeIFmn1qhDVkYSbdIA2xPIB3wjyfuIuR6kxezIGj+ZEOnF4b9rytvlfzXp/I+nAKbUNSFdy1ABBCmfzbOmMs+6FsO8ixKyqsyCD5kGtRePGCIhjcVGaWP2sGqS/92V24PIRq50bbjhzDNb8+Vc5HvLu/i/CvnUfWrNMqCbSM90u06ckteK3x/msA7WjhZioq7ppYYEcdKeacPTdmLsP38/vo3s+/30GnZ5gefMuHVh3EwfDJ7iZ7e5/nBO6FNuqpC3DKj/tPKTNb6Zucgmmas2LBJ2NUGLCul7XZ4HuVh2CVMSdnOIMDkvGpEVOpZa+8erjGUhA/Q5dpXVfrh//Ufi7TrO/dVYn1vZtA9b0Ef997nG4XFJHs8jqox+fQwtTJOUuQn6N0AJRiq+kDAl2akvQU/T+rE5KbF1cbPloUE4I3axuO8s6peBxVx44I4PEh9S3W7mwhgzASURzKwdwrpFEogjEMjZLT7mq2SiH5vbh91dbRyOI0849EUgSBdSqDd59BUzcrHxjPQ0Daot6UI3CYX4kr8ABt++4QLpKGFUCabPV5zG0zae9E/CPnNWmKAffXXsgnszgbC2ZVoxC8iVlu9ruO9zKrJRT+LLRuEVqb1VudfqEH0Xp5FuJ5X1hzHHPGIlwZLkI7krUBwPcxDCS5xvvN9XEbHm4VPE8wyAJ5yKYzLb7LwjlRTzeg6t/J5Xw7jhKU2C9XpcCB8XKxD9zcJJbJiFbvPt6KX6EQEg9lriT5wQ59jpnEvw0GjYymIYWIn8IELOrzITWSHAZVvM7OpKSQCJpMEhB/ejfZQ8PdXDnyvrgCbPFxvhLBlNnugokDQn0YGYM9smDpNgUh0qk61osolT9E2JyucnZpN8oPHDmv2Y6/EzOZdXyySnOE5zW02kaN9zXVyPEUaM+YHg/ehbVzVTk+fst/t6CKlKnfSUBu1X+7eNdCjZOjn9CYcb2VPaU5damxILlhGN9eNsrw7RWbMdbU1RTQO3l+b8ZDm6N4Zt/xmTJ/JIxHjT9/ET6MR7aO3tChxqHPe4HPxfXNTgS+ku1wB+1kIFOwhoW68sXptlTrxXFHULvbGIfsZHW8ONaxeGRb9hDWG4lyv0OaHYA6EwN9/WPZm5g/gkXCOoXd44XbMINxdqMrDjUiC2Vn30nKh/5cY7AFDBOF+/89vpU+SMaVR9gcKb8uEr2B+8k8hIrXCJrPj9y3/Jxk5AY8ztnH+ePHb9TaiaLHoTrOiGBNjza/1wZ0n0sRdzZdStw56S9VbgyuD7uva1RcXBI22bAzP9/9XrfndoKblO3v9VTv/OefWz4asPI/isZWNamsLDJLeZkQE4wMUiEhRYvA4qiY0HRMch7oRO2jxIPsH37wECeCG6FykH83r5NVIio7GJp2TlCbM0EbaMrPSQNgL4UGuNRSEr9DC8TPYUo+CQLG9KtN9yLrqLSdSUIHEDemhzJGm2rETaMbFZ1MYtH2QKlwG4DNB5mwQu28wgNF99ukzjQExjOxSP5Q8s6qGIph6Xq3jww7xzRfSGgjQ1f2mOk8EzX/AaMsKBYsGoh0RxHK2s1JpH+bookMCXd6T1ifhjXi45qPdIUr/Lpqd2jViBQ3D+G2dAeBj1QcQDm052QMZZcCjDZHj6nuNZQ2AJNO1zR/Xj6yJZ0uc5Hap+VueEASrp0DXY+QvqdTsx3NsC1misBhg3JWe9Iomd/f3unctJe+pdtfRcQQJgsLNviX7f2wi6nB/qpUQt/6e0eSkV1a8eyVVTWDqlxBtAohGSMITut+Nlav/4Ip7Aj6IjLhNfaxT0kTeNyT3CwD5K1KRyvYLkNcjc+Ku6tQO+3eapBx+t9rnA8y/OzhTvb//XXZxfnjAA2C0EIHm36DNV4R1Tx6fIqWgXMGXFAr0wkknnFfHHAKefqBpXyzGVkLMCWrKCUns0Q/L5U1wPZuD5RYhefp+lCSoc41HbNv8tq0aAr/S1iLOTeSLXxPesUb65ci2hh8NiPH9N1voEpOWHcYPSgFmdUkQVs28wYac4g13w8mL9o8pe8FOxuSXBOOkO64RMxoBf8SUcdWUDsvex230QoVHCSWEJuiRUQjAztnycHxZTzyfCw+944xstQbbN1ms26UmHqzy75ZiuSX+Acrbsm16YGXB2NHs7ceDXgq9/Px5gF2dPYAdbHwSczlsrHTTGg5Nte1GAdaRisdh6YvBzzP1hT7lft+mxXgJIgCEm4b1Do8dnrQhkrpzrV7Ua0n+8Ym1m7ZWozlqiG2QG80O+yqfF4EEG08jfTsJPXE4VitfCMj+HZdTphDdDFdX9Q/VWEX6Ny1UiIWS49EHHFR5kulr6U5N5D69xJ/k7F9FqAs7AAAAAADqd06zUt9iGptOhY1i4t/Xnb+O4S/9c6kySj1DqrxdxV/1t3t3eqXuEPc84sDl5wV1kEn16MqQ+FragKYLcEKrcuZOEwx5qGQZNgReYYpwnFcsuZZzpsgqrUwXPRs0/LZ3+DysCTOkGHKmB539rHCLsh7jzkEsYaKWKtM8s/swYzvKqX97jm05pm1+MUF4EsAoixZoUNbczvI69blctKogUq22uAjmRFvW7gXA/rDkCGblMzv3mznmRgAHt5L8RBpFJYCz8re+aoKp2XgZ2m+Mc2E70pbIghYfqUzpksDaLIb3xznoP7ZSsimFyZmWVNAAAARVhJRroAAABFeGlmAABJSSoACAAAAAYAEgEDAAEAAAABAAAAGgEFAAEAAABWAAAAGwEFAAEAAABeAAAAKAEDAAEAAAACAAAAEwIDAAEAAAABAAAAaYcEAAEAAABmAAAAAAAAAEgAAAABAAAASAAAAAEAAAAGAACQBwAEAAAAMDIxMAGRBwAEAAAAAQIDAACgBwAEAAAAMDEwMAGgAwABAAAA//8AAAKgBAABAAAAagEAAAOgBAABAAAAIAEAAAAAAAA=" medium="image"/><author>Sonja Georgievska</author></item><item><title>Evidence for the importance of research software</title><link>https://blog2.esciencecenter.nl/posts/2020-06-08---evidence-for-the-importance-of-research-software</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-06-08---evidence-for-the-importance-of-research-software</guid><description>&lt;p&gt;● &lt;a href=&quot;https://op.europa.eu/en/publication-detail/-/publication/fd0f6775-e0dd-11e9-9c4e-01aa75ed71a1&quot;&gt;Recognising the importance of software in research: Research Software Engineers (RSEs), a UK example — Study &lt;/a&gt;is a case study that discusses the current challenges faced by RSEs and policy conclusions to further help support RSEs and to contribute to the progress of open science in Europe.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://www.ukri.org/research/infrastructure/&quot;&gt;UK’s research and innovation infrastructure: opportunities to grow our capability&lt;/a&gt; highlights the importance of software by recognising software and skills as one of the six computational and e-infrastructure themes.&lt;/p&gt;
&lt;p&gt;Community **considers work on the importance of research software communities in ensuring best practice in software development.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://sinews.siam.org/Details-Page/computational-research-software-challenges-and-community-organizations-working-for-culture-change&quot;&gt;Computational Research Software: Challenges and Community Organizations Working for Culture Change &lt;/a&gt;identifies the importance of sustained community in the development of high-quality software, and introduces efforts by grassroots organisations and projects to improve software quality, productivity, and sustainability. These endeavors ensure the integrity of research results and enable more effective collaboration.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1109/MCSE.2018.2883051&quot;&gt;Community Organizations: Changing the Culture in Which Research Software Is Developed and Sustained &lt;/a&gt;provides an overview of the grass-roots organisations and projects that have evolved to address growing technical and social challenges in research software productivity, quality, reproducibility, and sustainability. This article then discusses opportunities to leverage their synergistic activities while nurturing work toward emerging software ecosystems.&lt;/p&gt;
&lt;p&gt;**Education and training **identifies work that considers issues round skills, training, career paths and reward structures.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1109/SANER.2018.8330263&quot;&gt;How do scientists develop scientific software? An external replication &lt;/a&gt;considers how scientists acquire software engineering knowledge to suggest improvements in this process.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;http://arxiv.org/abs/1507.03989&quot;&gt;Software Use in Astronomy: an Informal Survey &lt;/a&gt;finds that all participants use software in their research, and identifies the ten most popular tools. 90% of participants write at least some of their own software. while only 8% of them report that they have received substantial training in software development.&lt;/p&gt;
&lt;p&gt;● Unmet needs for analyzing biological big data: A survey of 704 NSF principal investigators highlights the importance of skills in software development for data analysis, with 90% of respondents indicating they are currently or will soon be analyzing large data sets.&lt;/p&gt;
&lt;p&gt;**Research breakthroughs **include papers on significant research accomplishments that acknowledge reliance on research software tools:&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://numfocus.org/case-studies/first-photograph-black-hole&quot;&gt;Case Study: First Photograph of a Black Hole, Enabled by NumFOCUS Tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://pegasus.isi.edu/2016/02/11/pegasus-powers-ligo-gravitational-waves-detection-analysis/&quot;&gt;Pegasus powers LIGO gravitational wave detection analysis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://phys.org/news/2018-08-software-framework-drug-discovery-ieee.html&quot;&gt;Software framework designed to accelerate drug discovery wins IEEE International Scalable Computing Challenge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;**Software **has been applied as a tag to resources that mention particular pieces of software, including when this is part of a broader focus in the resource. This category includes a sample of the tens of thousands of papers that rely on research software and that collectively build knowledge in a field, for example:&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1016/j.cell.2018.02.031&quot;&gt;Analysis of Human Sequence Data Reveals Two Pulses of Archaic Denisovan Admixture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1186/s13059-019-1763-7&quot;&gt;Challenges in funding and developing genomic software: roots and remedies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://arstechnica.com/information-technology/2019/10/chemists-discover-cross-platform-python-scripts-not-so-cross-platform/&quot;&gt;Researchers find bug in Python script may have affected hundreds of studies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● Securing the future of research computing in the biosciences.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://interestingengineering.com/these-7-cern-spinoffs-show-the-project-isnt-just-theoretical&quot;&gt;These 7 CERN Spinoffs Show The Project Isn’t Just Theoretical&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;other-useful-approaches&quot;&gt;Other useful approaches&lt;/h2&gt;
&lt;p&gt;This analysis has been useful in elucidating some of the ways in which the value of software can be demonstrated. However, there are also other approaches that could be useful. For example, methods to evaluate economic value are providing valuable statistics for research data, but comparable examples for research software are rare. The recent European Union publication,&lt;a href=&quot;https://op.europa.eu/en/publication-detail/-/publication/d375368c-1a0a-11e9-8d04-01aa75ed71a1&quot;&gt; Cost-benefit analysis for FAIR research data&lt;/a&gt;, finds that the overall cost to the European economy of not having Findable, Accessible, Interoperable and Reusable (FAIR) research data is €10.2bn per year in Europe. A 2014 Australian study by &lt;a href=&quot;https://www.ands.org.au/__data/assets/pdf_file/0019/393022/open-research-data-report.pdf&quot;&gt;Houghton and Gruen &lt;/a&gt;similarly demonstrates the economic value of data, estimating the value of Australian public research data at over $1.9 billion a year. One of the few economic valuations of research software is a 2017 analysis by &lt;a href=&quot;https://nectar.org.au/wp-content/uploads/2016/06/Estimating-the-value-and-impact-of-Nectar-Virtual-Laboratories-2017.pdf&quot;&gt;Sweeny et al. &lt;/a&gt;of the return on investment generated by three Australian virtual laboratories, which provide access to research software and data for researchers, was at least double the investment for every measure. This indicated that the services had a significant economic and user impact — by one measure the value of one virtual laboratory was over 100 times the cost of investment. It would be useful if more studies were undertaken to demonstrate the economic benefits of research software using different methodologies.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This summary of evidence of the importance of research software to research outcomes illustrates increasing recognition of this fact. This summary could also be useful to encourage the community to consider where additional work could be useful (such as expanding existing surveys in specific countries and disciplines to get a more global scope), and to inspire the recording of more of this information (which could include striking examples that convey the impact of failing to understanding the costs and responsibilities of thoughtful software management).&lt;/p&gt;
&lt;p&gt;We encourage readers to submit additional resources to the ReSA resources list, which is publicly available:&lt;/p&gt;
&lt;p&gt;● Add it directly to the ReSA&lt;a href=&quot;https://www.zotero.org/groups/2400609/resa/library&quot;&gt; Zotero group library &lt;/a&gt;(requires Zotero account).&lt;/p&gt;
&lt;p&gt;● Submit an issue in &lt;a href=&quot;https://github.com/researchsoft/Resources/issues/new/choose&quot;&gt;GitHub &lt;/a&gt;(requires GitHub account).&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;mailto:info@researchsoft.org&quot;&gt;Email &lt;/a&gt;it directly to ReSA.&lt;/p&gt;
&lt;p&gt;Authors: &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-3623-172X&quot;&gt;&lt;em&gt;Michelle Barker&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;,&lt;em&gt;&lt;a href=&quot;http://orcid.org/0000-0001-5934-7525&quot;&gt;* Daniel S. Katz*&lt;/a&gt;&lt;/em&gt;,*&lt;a href=&quot;https://orcid.org/0000-0003-3499-8262&quot;&gt;* Alejandra Gonzalez-Beltran*&lt;/a&gt;the&lt;/p&gt;</description><pubDate>Mon, 08 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;● &lt;a href=&quot;https://op.europa.eu/en/publication-detail/-/publication/fd0f6775-e0dd-11e9-9c4e-01aa75ed71a1&quot;&gt;Recognising the importance of software in research: Research Software Engineers (RSEs), a UK example — Study &lt;/a&gt;is a case study that discusses the current challenges faced by RSEs and policy conclusions to further help support RSEs and to contribute to the progress of open science in Europe.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://www.ukri.org/research/infrastructure/&quot;&gt;UK’s research and innovation infrastructure: opportunities to grow our capability&lt;/a&gt; highlights the importance of software by recognising software and skills as one of the six computational and e-infrastructure themes.&lt;/p&gt;
&lt;p&gt;Community **considers work on the importance of research software communities in ensuring best practice in software development.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://sinews.siam.org/Details-Page/computational-research-software-challenges-and-community-organizations-working-for-culture-change&quot;&gt;Computational Research Software: Challenges and Community Organizations Working for Culture Change &lt;/a&gt;identifies the importance of sustained community in the development of high-quality software, and introduces efforts by grassroots organisations and projects to improve software quality, productivity, and sustainability. These endeavors ensure the integrity of research results and enable more effective collaboration.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1109/MCSE.2018.2883051&quot;&gt;Community Organizations: Changing the Culture in Which Research Software Is Developed and Sustained &lt;/a&gt;provides an overview of the grass-roots organisations and projects that have evolved to address growing technical and social challenges in research software productivity, quality, reproducibility, and sustainability. This article then discusses opportunities to leverage their synergistic activities while nurturing work toward emerging software ecosystems.&lt;/p&gt;
&lt;p&gt;**Education and training **identifies work that considers issues round skills, training, career paths and reward structures.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1109/SANER.2018.8330263&quot;&gt;How do scientists develop scientific software? An external replication &lt;/a&gt;considers how scientists acquire software engineering knowledge to suggest improvements in this process.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;http://arxiv.org/abs/1507.03989&quot;&gt;Software Use in Astronomy: an Informal Survey &lt;/a&gt;finds that all participants use software in their research, and identifies the ten most popular tools. 90% of participants write at least some of their own software. while only 8% of them report that they have received substantial training in software development.&lt;/p&gt;
&lt;p&gt;● Unmet needs for analyzing biological big data: A survey of 704 NSF principal investigators highlights the importance of skills in software development for data analysis, with 90% of respondents indicating they are currently or will soon be analyzing large data sets.&lt;/p&gt;
&lt;p&gt;**Research breakthroughs **include papers on significant research accomplishments that acknowledge reliance on research software tools:&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://numfocus.org/case-studies/first-photograph-black-hole&quot;&gt;Case Study: First Photograph of a Black Hole, Enabled by NumFOCUS Tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://pegasus.isi.edu/2016/02/11/pegasus-powers-ligo-gravitational-waves-detection-analysis/&quot;&gt;Pegasus powers LIGO gravitational wave detection analysis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://phys.org/news/2018-08-software-framework-drug-discovery-ieee.html&quot;&gt;Software framework designed to accelerate drug discovery wins IEEE International Scalable Computing Challenge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;**Software **has been applied as a tag to resources that mention particular pieces of software, including when this is part of a broader focus in the resource. This category includes a sample of the tens of thousands of papers that rely on research software and that collectively build knowledge in a field, for example:&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1016/j.cell.2018.02.031&quot;&gt;Analysis of Human Sequence Data Reveals Two Pulses of Archaic Denisovan Admixture&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://doi.org/10.1186/s13059-019-1763-7&quot;&gt;Challenges in funding and developing genomic software: roots and remedies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://arstechnica.com/information-technology/2019/10/chemists-discover-cross-platform-python-scripts-not-so-cross-platform/&quot;&gt;Researchers find bug in Python script may have affected hundreds of studies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;● Securing the future of research computing in the biosciences.&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;https://interestingengineering.com/these-7-cern-spinoffs-show-the-project-isnt-just-theoretical&quot;&gt;These 7 CERN Spinoffs Show The Project Isn’t Just Theoretical&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;other-useful-approaches&quot;&gt;Other useful approaches&lt;/h2&gt;
&lt;p&gt;This analysis has been useful in elucidating some of the ways in which the value of software can be demonstrated. However, there are also other approaches that could be useful. For example, methods to evaluate economic value are providing valuable statistics for research data, but comparable examples for research software are rare. The recent European Union publication,&lt;a href=&quot;https://op.europa.eu/en/publication-detail/-/publication/d375368c-1a0a-11e9-8d04-01aa75ed71a1&quot;&gt; Cost-benefit analysis for FAIR research data&lt;/a&gt;, finds that the overall cost to the European economy of not having Findable, Accessible, Interoperable and Reusable (FAIR) research data is €10.2bn per year in Europe. A 2014 Australian study by &lt;a href=&quot;https://www.ands.org.au/__data/assets/pdf_file/0019/393022/open-research-data-report.pdf&quot;&gt;Houghton and Gruen &lt;/a&gt;similarly demonstrates the economic value of data, estimating the value of Australian public research data at over $1.9 billion a year. One of the few economic valuations of research software is a 2017 analysis by &lt;a href=&quot;https://nectar.org.au/wp-content/uploads/2016/06/Estimating-the-value-and-impact-of-Nectar-Virtual-Laboratories-2017.pdf&quot;&gt;Sweeny et al. &lt;/a&gt;of the return on investment generated by three Australian virtual laboratories, which provide access to research software and data for researchers, was at least double the investment for every measure. This indicated that the services had a significant economic and user impact — by one measure the value of one virtual laboratory was over 100 times the cost of investment. It would be useful if more studies were undertaken to demonstrate the economic benefits of research software using different methodologies.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This summary of evidence of the importance of research software to research outcomes illustrates increasing recognition of this fact. This summary could also be useful to encourage the community to consider where additional work could be useful (such as expanding existing surveys in specific countries and disciplines to get a more global scope), and to inspire the recording of more of this information (which could include striking examples that convey the impact of failing to understanding the costs and responsibilities of thoughtful software management).&lt;/p&gt;
&lt;p&gt;We encourage readers to submit additional resources to the ReSA resources list, which is publicly available:&lt;/p&gt;
&lt;p&gt;● Add it directly to the ReSA&lt;a href=&quot;https://www.zotero.org/groups/2400609/resa/library&quot;&gt; Zotero group library &lt;/a&gt;(requires Zotero account).&lt;/p&gt;
&lt;p&gt;● Submit an issue in &lt;a href=&quot;https://github.com/researchsoft/Resources/issues/new/choose&quot;&gt;GitHub &lt;/a&gt;(requires GitHub account).&lt;/p&gt;
&lt;p&gt;● &lt;a href=&quot;mailto:info@researchsoft.org&quot;&gt;Email &lt;/a&gt;it directly to ReSA.&lt;/p&gt;
&lt;p&gt;Authors: &lt;em&gt;&lt;a href=&quot;https://orcid.org/0000-0002-3623-172X&quot;&gt;&lt;em&gt;Michelle Barker&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;,&lt;em&gt;&lt;a href=&quot;http://orcid.org/0000-0001-5934-7525&quot;&gt;* Daniel S. Katz*&lt;/a&gt;&lt;/em&gt;,*&lt;a href=&quot;https://orcid.org/0000-0003-3499-8262&quot;&gt;* Alejandra Gonzalez-Beltran*&lt;/a&gt;the&lt;/p&gt;</content:encoded><author>Netherlands eScience Center</author></item><item><title>Forcing science with brute force deep learning</title><link>https://blog2.esciencecenter.nl/posts/2020-04-25---forcing-science-with-brute-force-deep-learning</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-04-25---forcing-science-with-brute-force-deep-learning</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;When we are children, we lack patience. When we grow up, “we lack time”.&lt;/p&gt;
&lt;p&gt;Not all is bad, of course. Once trained, the deep neural networks are very fast when used for prediction. However, that assumes that the model is actually* used in practice rather than for the incremental improvement of state-of-art, i.e. academic scores. Not to mention that, in the latter case, the published model usually leaves &lt;em&gt;a lot&lt;/em&gt; to be desired in terms of generated scientific knowledge.&lt;/p&gt;
&lt;p&gt;Apart from deep learning, Google is also famous for — well, their first product ever — the &lt;em&gt;Google&lt;/em&gt; search engine. The latter must be incredibly fast as it has to work in real-time. Therefore, the time efficiency of the algorithms used here is of supreme importance, and the engineers developing it must swim without effort through the big O notation. Or, use Bubble-sort instead of Quick-sort and you are beaten by the competition.&lt;/p&gt;
&lt;p&gt;Scarce resources, like time, in this case, stimulate creative and efficient usage of the same.&lt;/p&gt;
&lt;p&gt;Thus, when using deep learning in science, perhaps we should instead search for inspiration in this corner of the Google Universe.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Johan Hidding, Florian Huber, Tom Bakker and Pablo Rodriguez-Sanchez for the useful suggestions.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Sat, 25 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;When we are children, we lack patience. When we grow up, “we lack time”.&lt;/p&gt;
&lt;p&gt;Not all is bad, of course. Once trained, the deep neural networks are very fast when used for prediction. However, that assumes that the model is actually* used in practice rather than for the incremental improvement of state-of-art, i.e. academic scores. Not to mention that, in the latter case, the published model usually leaves &lt;em&gt;a lot&lt;/em&gt; to be desired in terms of generated scientific knowledge.&lt;/p&gt;
&lt;p&gt;Apart from deep learning, Google is also famous for — well, their first product ever — the &lt;em&gt;Google&lt;/em&gt; search engine. The latter must be incredibly fast as it has to work in real-time. Therefore, the time efficiency of the algorithms used here is of supreme importance, and the engineers developing it must swim without effort through the big O notation. Or, use Bubble-sort instead of Quick-sort and you are beaten by the competition.&lt;/p&gt;
&lt;p&gt;Scarce resources, like time, in this case, stimulate creative and efficient usage of the same.&lt;/p&gt;
&lt;p&gt;Thus, when using deep learning in science, perhaps we should instead search for inspiration in this corner of the Google Universe.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Johan Hidding, Florian Huber, Tom Bakker and Pablo Rodriguez-Sanchez for the useful suggestions.&lt;/em&gt;&lt;/p&gt;</content:encoded><author>Sonja Georgievska</author></item><item><title>Why AI will not replace experts</title><link>https://blog2.esciencecenter.nl/posts/2020-04-25---why-ai-will-not-replace-experts</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-04-25---why-ai-will-not-replace-experts</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Let’s take a few steps back. It is 1990 and a team of medical researchers equipped with a statistician is performing a &lt;a href=&quot;https://www.thelancet.com/journals/lancet/article/PII0140-6736(90)91656-U/fulltext&quot;&gt;randomized control study&lt;/a&gt; to find out if phenomenon X causes disease Y. They first take the utmost care that the data, I mean the patients, from which they want to derive conclusions, are representative of the population; that the experimental and the control group are properly established; that there are no correlations in the data-set, sorry, cohort, that might contaminate the results of the study; etc, etc… You get the point (I am not a professional statistician, so please ask one for more details). Only after* the experiment is prepared with the utmost rigor, are they allowed to actually make the experiment and apply AI, I mean, statistical methods, to gain predictions. (Did I say predictions? I meant conclusions.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why AI will not replace experts&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-ai-will-not-replace-experts-ac29c84f.CRn9md0i_1gBnnV.webp&quot; srcset=&quot;&quot;&gt;
“We don’t know why, but a state-of-art algorithm told us you can take these”. Photo by &lt;a href=&quot;https://unsplash.com/@hikendal?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Kendal&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;It is now 2020. Imagine that a team of medical researchers collects a huge amount of profiles of “patients” from a popular social media website, and says “Bingo! We have so much data! Let us apply one of the fancy new statistical, now called AI, methods, and get results without all the effort we used to put into it”. They get the results, make a pill based on them, send it for mass production, the pills start killing instead of curing… It is difficult to imagine, isn’t it? Then why on Earth do we want the prediction methods of the 21st century to be able to turn garbage data into gold? Is it because we gave them such a sophisticated name, &lt;em&gt;Artificial Intelligence&lt;/em&gt;, and so we expect them to replace humans altogether?&lt;/p&gt;
&lt;p&gt;How about this: instead of saying that AI turns data into prediction, say that it merely consumes the data to be able to perform its daily activities. (So, don’t worry, we are still humanizing AI ’cause it’s so irresistible). So, data is food for AI. When we buy food from the supermarket we know that it has gone through quality control during production to make sure we don’t eat poison. When we pick up spinach from the garden we wash it thoroughly to make sure it is not contaminated with bacteria. Or else we get sick and anything can happen. But from AI we expect it to be almighty and be able to skip all those quality control steps, ’cause AI is, after all, supernatural and such creatures cannot get sick, can they?&lt;/p&gt;
&lt;p&gt;So, here is the good news. AI is &lt;em&gt;not&lt;/em&gt; going to replace the jobs of radiologists, medical experts, accountants, please finish the list. It is just going to transform the kind of jobs that they are doing and speed up progress. &lt;em&gt;Nobody&lt;/em&gt; is going to make AI almighty. &lt;em&gt;Experts&lt;/em&gt; will be needed to make sure AI is being fed with the right data. Only *then *will society be able to trust AI. Because it will not be about AI in the end. It will be about &lt;em&gt;the&lt;/em&gt; &lt;em&gt;people&lt;/em&gt;, again.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Patrick Bos, Florian Huber, Carlos Martinez Ortiz, Tom Bakker, and Johan Ridder for the useful remarks.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Sat, 25 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;Let’s take a few steps back. It is 1990 and a team of medical researchers equipped with a statistician is performing a &lt;a href=&quot;https://www.thelancet.com/journals/lancet/article/PII0140-6736(90)91656-U/fulltext&quot;&gt;randomized control study&lt;/a&gt; to find out if phenomenon X causes disease Y. They first take the utmost care that the data, I mean the patients, from which they want to derive conclusions, are representative of the population; that the experimental and the control group are properly established; that there are no correlations in the data-set, sorry, cohort, that might contaminate the results of the study; etc, etc… You get the point (I am not a professional statistician, so please ask one for more details). Only after* the experiment is prepared with the utmost rigor, are they allowed to actually make the experiment and apply AI, I mean, statistical methods, to gain predictions. (Did I say predictions? I meant conclusions.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Why AI will not replace experts&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/why-ai-will-not-replace-experts-ac29c84f.CRn9md0i_1gBnnV.webp&quot; srcset=&quot;&quot;&gt;
“We don’t know why, but a state-of-art algorithm told us you can take these”. Photo by &lt;a href=&quot;https://unsplash.com/@hikendal?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Kendal&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=medium&amp;#x26;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;It is now 2020. Imagine that a team of medical researchers collects a huge amount of profiles of “patients” from a popular social media website, and says “Bingo! We have so much data! Let us apply one of the fancy new statistical, now called AI, methods, and get results without all the effort we used to put into it”. They get the results, make a pill based on them, send it for mass production, the pills start killing instead of curing… It is difficult to imagine, isn’t it? Then why on Earth do we want the prediction methods of the 21st century to be able to turn garbage data into gold? Is it because we gave them such a sophisticated name, &lt;em&gt;Artificial Intelligence&lt;/em&gt;, and so we expect them to replace humans altogether?&lt;/p&gt;
&lt;p&gt;How about this: instead of saying that AI turns data into prediction, say that it merely consumes the data to be able to perform its daily activities. (So, don’t worry, we are still humanizing AI ’cause it’s so irresistible). So, data is food for AI. When we buy food from the supermarket we know that it has gone through quality control during production to make sure we don’t eat poison. When we pick up spinach from the garden we wash it thoroughly to make sure it is not contaminated with bacteria. Or else we get sick and anything can happen. But from AI we expect it to be almighty and be able to skip all those quality control steps, ’cause AI is, after all, supernatural and such creatures cannot get sick, can they?&lt;/p&gt;
&lt;p&gt;So, here is the good news. AI is &lt;em&gt;not&lt;/em&gt; going to replace the jobs of radiologists, medical experts, accountants, please finish the list. It is just going to transform the kind of jobs that they are doing and speed up progress. &lt;em&gt;Nobody&lt;/em&gt; is going to make AI almighty. &lt;em&gt;Experts&lt;/em&gt; will be needed to make sure AI is being fed with the right data. Only *then *will society be able to trust AI. Because it will not be about AI in the end. It will be about &lt;em&gt;the&lt;/em&gt; &lt;em&gt;people&lt;/em&gt;, again.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Patrick Bos, Florian Huber, Carlos Martinez Ortiz, Tom Bakker, and Johan Ridder for the useful remarks.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/why-ai-will-not-replace-experts-ac29c84f.CRn9md0i.jpg" medium="image"/><author>Sonja Georgievska</author></item><item><title>Can we teach AI’s speech by simulating young children’s ability to learn spoken language?</title><link>https://blog2.esciencecenter.nl/posts/2020-04-02---can-we-teach-ais-speech-by-simulating-young-childrens-abilit</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-04-02---can-we-teach-ais-speech-by-simulating-young-childrens-abilit</guid><description>&lt;p&gt;&lt;strong&gt;8
Today, we can´t imagine life without voice controlled intelligent systems such as Siri, Google Assistant, car navigation systems and other applications. Such systems use a speech understanding component to interact with humans. Their ability to understand human language is therefore a crucial capability.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The most widely used technique to enable an application to understand and react to spoken language is to first transcribe speech into text using a speech recognition module, and then to process the text with a separate text understanding module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;An alternative approach&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The project ‘Understanding visually grounded spoken language via multi-tasking’ is a result of the Accelerating Scientific Discovery 2018 call for proposals. Led by Dr Grzegorz Chrupała, associate professor at Tilburg University and supported by the Netherlands eScience Center, the project proposes an alternative approach inspired by how humans understand speech. “I am primarily interested in how we can simulate young children’s ability to learn spoken language simply by being exposed to speech in various situations”, says Chrupała. “We call this scenario visually grounded, because the source of supervision comes from correlations between two (or even more) modalities: speech and vision.”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Kim-Anh Holthaus&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;445&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-e9857822.UkVRCUka_BuTPf.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Dr Grzegorz Chrupała&lt;/em&gt;Speech will be processed directly by an end-to-end neural network model without first being transcribed into text, avoiding the need for large amounts of transcribed speech required to train a traditional speech recognition system. The system will instead learn simultaneously from more easily obtained types of data. For example, it will learn to match images to their spoken descriptions, answer questions about images, or match utterances spoken in different languages.&lt;/p&gt;
&lt;p&gt;“For this project we want to look at what additional signals we can exploit, or what additional tasks can help the computational model to learn something about the meaning of spoken language”, Chrupała explains. “Does it help to have access to a written language sample, and how much? Can an attempt to translate between different languages contribute? What specific biases can we put into the model to make language acquisition more efficient in our visually grounded learning scenario?”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;392&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-8df78313.Tl4NHqSZ_15JFnf.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Left to right: Dr Patrick Bos, Dr Bertrand Higy, Dr Grzegorz Chrupala, Dr Afra Alishahi and Dr Jisk Attema&lt;/em&gt;Dr Patrick Bos, eScience Research Engineer at the Netherlands eScience Center, clarifies three main goals of the project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The impact of adding other types of data on speech recognition model performance. For instance, does it help to tell the model which sounds correspond to separate letters? Or does it help to tell it about sentence grammar?&lt;/li&gt;
&lt;li&gt;When exploring the technical details of the machine learning model, we need to ask ourselves whether we can make the model work just as well (or better) by using a so-called “transformer” model instead of the recurrent neural network we currently use. Also, do we need more or less data to train it? Does it take more or less time (hence higher or lower power consumption by the computers)?&lt;/li&gt;
&lt;li&gt;To make the speech recognition models useful for a wide range of problems in many different languages, with different amounts of data, different demands on performance in certain tasks, etcetera, we need to make them as efficient as possible. One of the ways to make it faster to train a model and make more efficient use of available hardware is to enable parallel calculation on multiple GPUs at once. The aim is to implement this for the project’s model.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The project promises to be less reliant on strong supervision and expensive resources and thus applicable in a wider range of circumstances than traditional systems, especially when large amounts of transcribed speech are not available, for example when dealing with low-resource languages or specialized domains.&lt;/p&gt;
&lt;p&gt;Although the project recently started, the team is aware expertise and focus are essential. Chrupała: “Jisk and Patrick have expertise in high- performance computing. The models we use in our project are deep neural networks with hundreds of thousands or millions of trainable parameters, which are learned from hours of spoken language and thousands of images. The only realistic way to fit these models is by using Graphical Processing Units (GPU). Patrick is working on adapting our software to make training more efficient and scalable to multiple GPU hardware, using state of the art neural architectural designs.’’&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;1248&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-217423ae.Ct9xNnMm_1UxJTj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1917&quot; height=&quot;1337&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-1f1a38e0.BL_xl1-R_Z9e8Do.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2261&quot; height=&quot;1228&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-181aa193.BntICi4D_ZopI5q.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1682&quot; height=&quot;1344&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-8708486a.7jPRpV4-_1sTE9P.webp&quot; srcset=&quot;&quot;&gt;
“One thing I have noticed so far is that this field (deep learning for voice recognition) is moving quite fast, a lot faster than fields I’ve worked in.” says Bos.&lt;/p&gt;
&lt;p&gt;Dr Bertrand Higy, postdoc at Tilburg University and part of the project team, notes the benefits of collaborating with different partners and how research is done during the project. “What gives this project such great potential is the fact that we can focus all our efforts on our research question and bring together researchers with different backgrounds and expertise.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-5ba44267.BmJHeyYE_nF0oo.webp&quot; srcset=&quot;&quot;&gt;
&lt;strong&gt;Making an impact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The project aims to help us understand the connection between human language learning and teaching language to a computer. As such, it promises to make learning more data efficient by using less training examples.&lt;/p&gt;
&lt;p&gt;“Most researchers in our field work either on textual data or on transcribing speech into text”, says Chrupała. “By working on the more general problem of modeling the learning of spoken language in a multimodal setting, we hope to move one step closer to the amazing language learning skills that young children possess. Although we mostly focus on basic research, we believe our work could help improve practical applications such as conversational agents of image retrieval via spoken commands. The recent deep learning revolution relies heavily on expensive labeled data. By exploring how language understanding can be acquired in a less supervised manner, I hope we can contribute to a more accessible technology. I imagine that some progress toward this goal will have been made in the next three years.”&lt;/p&gt;
&lt;p&gt;Read more about project &lt;a href=&quot;https://www.esciencecenter.nl/projects/understanding-visually-grounded-spoken-language-via-multi-tasking/&quot;&gt;Understanding visually grounded spoken language via multi-tasking&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 02 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;8
Today, we can´t imagine life without voice controlled intelligent systems such as Siri, Google Assistant, car navigation systems and other applications. Such systems use a speech understanding component to interact with humans. Their ability to understand human language is therefore a crucial capability.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The most widely used technique to enable an application to understand and react to spoken language is to first transcribe speech into text using a speech recognition module, and then to process the text with a separate text understanding module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;An alternative approach&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The project ‘Understanding visually grounded spoken language via multi-tasking’ is a result of the Accelerating Scientific Discovery 2018 call for proposals. Led by Dr Grzegorz Chrupała, associate professor at Tilburg University and supported by the Netherlands eScience Center, the project proposes an alternative approach inspired by how humans understand speech. “I am primarily interested in how we can simulate young children’s ability to learn spoken language simply by being exposed to speech in various situations”, says Chrupała. “We call this scenario visually grounded, because the source of supervision comes from correlations between two (or even more) modalities: speech and vision.”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Kim-Anh Holthaus&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;445&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-e9857822.UkVRCUka_BuTPf.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Dr Grzegorz Chrupała&lt;/em&gt;Speech will be processed directly by an end-to-end neural network model without first being transcribed into text, avoiding the need for large amounts of transcribed speech required to train a traditional speech recognition system. The system will instead learn simultaneously from more easily obtained types of data. For example, it will learn to match images to their spoken descriptions, answer questions about images, or match utterances spoken in different languages.&lt;/p&gt;
&lt;p&gt;“For this project we want to look at what additional signals we can exploit, or what additional tasks can help the computational model to learn something about the meaning of spoken language”, Chrupała explains. “Does it help to have access to a written language sample, and how much? Can an attempt to translate between different languages contribute? What specific biases can we put into the model to make language acquisition more efficient in our visually grounded learning scenario?”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;392&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-8df78313.Tl4NHqSZ_15JFnf.webp&quot; srcset=&quot;&quot;&gt;
&lt;em&gt;Left to right: Dr Patrick Bos, Dr Bertrand Higy, Dr Grzegorz Chrupala, Dr Afra Alishahi and Dr Jisk Attema&lt;/em&gt;Dr Patrick Bos, eScience Research Engineer at the Netherlands eScience Center, clarifies three main goals of the project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The impact of adding other types of data on speech recognition model performance. For instance, does it help to tell the model which sounds correspond to separate letters? Or does it help to tell it about sentence grammar?&lt;/li&gt;
&lt;li&gt;When exploring the technical details of the machine learning model, we need to ask ourselves whether we can make the model work just as well (or better) by using a so-called “transformer” model instead of the recurrent neural network we currently use. Also, do we need more or less data to train it? Does it take more or less time (hence higher or lower power consumption by the computers)?&lt;/li&gt;
&lt;li&gt;To make the speech recognition models useful for a wide range of problems in many different languages, with different amounts of data, different demands on performance in certain tasks, etcetera, we need to make them as efficient as possible. One of the ways to make it faster to train a model and make more efficient use of available hardware is to enable parallel calculation on multiple GPUs at once. The aim is to implement this for the project’s model.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The project promises to be less reliant on strong supervision and expensive resources and thus applicable in a wider range of circumstances than traditional systems, especially when large amounts of transcribed speech are not available, for example when dealing with low-resource languages or specialized domains.&lt;/p&gt;
&lt;p&gt;Although the project recently started, the team is aware expertise and focus are essential. Chrupała: “Jisk and Patrick have expertise in high- performance computing. The models we use in our project are deep neural networks with hundreds of thousands or millions of trainable parameters, which are learned from hours of spoken language and thousands of images. The only realistic way to fit these models is by using Graphical Processing Units (GPU). Patrick is working on adapting our software to make training more efficient and scalable to multiple GPU hardware, using state of the art neural architectural designs.’’&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;1248&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-217423ae.Ct9xNnMm_1UxJTj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1917&quot; height=&quot;1337&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-1f1a38e0.BL_xl1-R_Z9e8Do.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2261&quot; height=&quot;1228&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-181aa193.BntICi4D_ZopI5q.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1682&quot; height=&quot;1344&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-8708486a.7jPRpV4-_1sTE9P.webp&quot; srcset=&quot;&quot;&gt;
“One thing I have noticed so far is that this field (deep learning for voice recognition) is moving quite fast, a lot faster than fields I’ve worked in.” says Bos.&lt;/p&gt;
&lt;p&gt;Dr Bertrand Higy, postdoc at Tilburg University and part of the project team, notes the benefits of collaborating with different partners and how research is done during the project. “What gives this project such great potential is the fact that we can focus all our efforts on our research question and bring together researchers with different backgrounds and expertise.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Can we teach AI’s speech by simulating young children’s ability to learn spoken language?&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;394&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-5ba44267.BmJHeyYE_nF0oo.webp&quot; srcset=&quot;&quot;&gt;
&lt;strong&gt;Making an impact&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The project aims to help us understand the connection between human language learning and teaching language to a computer. As such, it promises to make learning more data efficient by using less training examples.&lt;/p&gt;
&lt;p&gt;“Most researchers in our field work either on textual data or on transcribing speech into text”, says Chrupała. “By working on the more general problem of modeling the learning of spoken language in a multimodal setting, we hope to move one step closer to the amazing language learning skills that young children possess. Although we mostly focus on basic research, we believe our work could help improve practical applications such as conversational agents of image retrieval via spoken commands. The recent deep learning revolution relies heavily on expensive labeled data. By exploring how language understanding can be acquired in a less supervised manner, I hope we can contribute to a more accessible technology. I imagine that some progress toward this goal will have been made in the next three years.”&lt;/p&gt;
&lt;p&gt;Read more about project &lt;a href=&quot;https://www.esciencecenter.nl/projects/understanding-visually-grounded-spoken-language-via-multi-tasking/&quot;&gt;Understanding visually grounded spoken language via multi-tasking&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/can-we-teach-ais-speech-by-simulating-yo-e9857822.UkVRCUka.jpeg" medium="image"/><author>Netherlands eScience Center</author></item><item><title>6 months of eScience: 6 lessons worth sharing</title><link>https://blog2.esciencecenter.nl/posts/2020-03-25---6-months-of-escience-6-lessons-worth-sharing</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-03-25---6-months-of-escience-6-lessons-worth-sharing</guid><description>&lt;h2 id=&quot;on-the-road-towards-fair-and-reproducible-science&quot;&gt;On the road towards FAIR and reproducible science.&lt;/h2&gt;
&lt;p&gt;Ever find yourself hesitating to send that important email, cursor hovering over the send button? For me, it’s grown into a curious habit. I particularly recall the time that I had to submit a code sample for my job application at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt;. Sharing my code felt like publishing my diary. (If you feel the same, be sure to read the part about linters).&lt;/p&gt;
&lt;p&gt;My strategy for the job interview was simple: I was frankly going to admit that my code wasn’t great. I would explain why I thought this was a problem, not just for me, but for science as a whole. And then beg to be hired so I could contribute to the solution. &lt;em&gt;It was super effective.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So what is this problem that turned a scientist into a research software engineer? It has everything to do with the digital competence required to work with large and complex models and data sets, in a manner consistent with the principles of FAIR and open science (as illustrated below). As a PhD student, I never quite felt properly equipped to effectively wield the tools and technologies that are available to this effect.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;750&quot; height=&quot;530&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_bqZuEZ4aKevZpJVu-b09ef874.LTKy3FVl_1XL5MB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image was created by Scriberia for The Turing Way community and is used under a CC-BY licence.&lt;/p&gt;
&lt;p&gt;That’s why I applied at the eScience Center. Because being surrounded by experts is the easiest way to become an expert yourself. And because I wanted this expertise to become widespread in the academic world. Today, six months into my eScience adventure, I want to share some of the lessons I’ve learned with my scientific peers.&lt;/p&gt;
&lt;p&gt;I’ll start with something I found quite surprising: treating research code as ‘software’. I’ll explain how that can help to think about re-use and reproducibility. Sharing code is an essential, and therefore I continue with a number of lessons I learned about sharing software. The last two lessons are about reuse of existing software and a community of Research Software Engineers that I discovered.&lt;/p&gt;
&lt;h3 id=&quot;research-code-vs-scientific-software&quot;&gt;Research code vs scientific software&lt;/h3&gt;
&lt;p&gt;Most of my everyday research activities centered around data analysis, which typically consists of a long exploratory phase and then converges towards something publishable. I never thought of the selected fragments of code, tailored to my publications, as (research) software. I still think this is a bit far-fetched, but I &lt;em&gt;do&lt;/em&gt; see now that this &lt;em&gt;scientific software perspective&lt;/em&gt; completely changes the way I think of my code in retrospect.&lt;/p&gt;
&lt;p&gt;What mostly set ‘my code’ apart from ‘software’ was that it was tailored to my use case, whereas software would be more generally applicable. It felt as a humble perspective at the time, but come to think of it, perhaps the term &lt;em&gt;downplay&lt;/em&gt; better captures my reluctance to think of my code as something bigger than my own scribbles. It is an attitude that hampers re-use and, consequently, progress.&lt;/p&gt;
&lt;p&gt;I think everyone can agree that sharing research code, even if it’s just for reproducibility, can be considered good practice. So why aren’t we doing it? I think there are three* main obstacles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We’re insecure about our research code&lt;/li&gt;
&lt;li&gt;We’re willing to share, but don’t know how&lt;/li&gt;
&lt;li&gt;A lack of time, priority or incentive&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The good news is that all these issues can easily be addressed if we stop thinking of (‘just my’) code and start thinking more in terms of research software. Software developers (&lt;a href=&quot;https://www.techwell.com/techwell-insights/2013/12/why-best-programmers-are-lazy-and-act-dumb&quot;&gt;lazy as they are&lt;/a&gt;) have come up with all kinds of tools and tricks and practices and whatnot to facilitate and automate issues like quality control and collaboration.&lt;/p&gt;
&lt;p&gt;*I’m assuming you’re &lt;em&gt;willing&lt;/em&gt; to share the code here. If you want to keep it to yourself, there are options, but we should have a good discussion about that…&lt;/p&gt;
&lt;h3 id=&quot;improve-your-code-using-linters&quot;&gt;Improve your code using linters&lt;/h3&gt;
&lt;p&gt;For example, I wish I had known about ‘linters’ before I submitted my code sample for the job application.&lt;/p&gt;
&lt;p&gt;Linters are little tools that will check whether your code is up to standard. There are many linters for various programming languages that focus on different sets of standards. Many decent code editors offer plugins that provide suggestions as you go. The image below shows an example for Python and &lt;a href=&quot;https://atom.io/&quot;&gt;Atom&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;522&quot; height=&quot;302&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_ec0KLCI8_avDgIRw-f4562f4d.CtsQ6mQP_ZXWugu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example view from &lt;a href=&quot;https://atom.io/packages/linter-python-pep257&quot;&gt;https://atom.io/packages/linter-python-pep257&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here, &lt;a href=&quot;https://www.python.org/dev/peps/pep-0257/&quot;&gt;pep257&lt;/a&gt; refers to style guidelines for Python documentation. Flake8 combines several common Python quality checks, including &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;pep8&lt;/a&gt; adherence. For those who like to work with Jupyter notebooks: there are several plugins to check or even &lt;a href=&quot;https://jupyterlab-code-formatter.readthedocs.io/en/latest/index.html&quot;&gt;auto-format&lt;/a&gt; your code. These tools are great to help you improve your code formatting and learn about quality standards.&lt;/p&gt;
&lt;h3 id=&quot;use-project-templates-to-organize-your-work&quot;&gt;Use project templates to organize your work&lt;/h3&gt;
&lt;p&gt;Research projects usually consist of more than code, and you don’t want your beautiful code to be undermined by a messy project structure. But organizing your work can be a challenge. I for one have wished for guidance more than once.&lt;/p&gt;
&lt;p&gt;Luckily, more people are facing this problem, and some have come up with solutions. One of those solutions is &lt;a href=&quot;https://cookiecutter.readthedocs.io/en/1.7.0/index.html&quot;&gt;Cookiecutter&lt;/a&gt;, ‘a tool for creating projects from templates’. There are templates for many kinds of projects, so you can choose one that suits your needs, for example &lt;a href=&quot;https://cookiecutter.readthedocs.io/en/1.7.0/README.html#reproducible-science&quot;&gt;Reproducible Science&lt;/a&gt;. For the more experienced Python programmers, the eScience Center developed a &lt;a href=&quot;https://github.com/NLeSC/python-template&quot;&gt;template for Python packages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The tool automatically sets up a directory structure for your project. It also creates things like a license and a README file. These will be useful when you’re ready to share your project. An important advantage of using a standardized project structure is that it will make it easier for others to navigate your project.&lt;/p&gt;
&lt;h3 id=&quot;sharing-is-easy-version-control-is-great&quot;&gt;Sharing is easy, version control is great&lt;/h3&gt;
&lt;p&gt;Once there’s no more need to be shy about our projects, let’s talk about &lt;em&gt;how&lt;/em&gt; to share it. Software repositories like GitHub (or GitLab, or the like) are the way to go here. During my PhD I was familiar with the basics of version control and GitHub, but I found it quite cumbersome as I was just working on it alone. Therefore, I never made it to all the nice features.&lt;/p&gt;
&lt;p&gt;For example, GitHub offers a great workflow for code review. You can configure it such that you’re code must always be checked by at least one other person. You can also set it up to perform all kinds of checks and tests. You can add various &lt;a href=&quot;https://www.freecodecamp.org/news/how-to-use-badges-to-stop-feeling-like-a-noob-d4e6600d37d2/&quot;&gt;automated quality badges&lt;/a&gt;. A lot is happening around notebooks as well (&lt;a href=&quot;https://github.com/reviewNB/treon&quot;&gt;example&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;439&quot; height=&quot;250&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_eRGe6Sr1ihmPTH92-aecc852c.pZYejZPL_Z10BF1I.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://xkcd.com/1296/&quot;&gt;https://xkcd.com/1296/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By writing nice commit messages, it becomes easy to show all the hard work you’ve been doing to e.g. your supervisor. Tangible output is nice! And why not use tags or releases for making a stable version for the reviewers of your publication? And then another release when the paper is accepted.&lt;/p&gt;
&lt;p&gt;The problem here is that, although this all sounds very nice, it requires collaboration and therefore commitment from a larger entity than yourself. It’s probably best organized at the level of a chair group/research unit. And that brings me to the last obstacle I listed above: ‘it all sounds very nice, but we simply don’t have the time…’&lt;/p&gt;
&lt;h3 id=&quot;proper-recognition-for-research-code-through-software-citations&quot;&gt;Proper recognition for research code through software citations&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://the-turing-way.netlify.com/credit/credit.html&quot;&gt;Software is citeable&lt;/a&gt;. It is not (yet) commonplace, but think about how this can change the everyday life of an academic. Imagine my PhD supervisor valued my code just as much as he valued my research papers. Time spent on code would suddenly have a purpose. All those hours of endless debugging would have a clear, visible, &lt;em&gt;citeable&lt;/em&gt; output product. Impact factor over 9000.&lt;/p&gt;
&lt;p&gt;My group (at the time) could have owned and maintained a public code base, and encouraged and assisted every employee to contribute. With a little generalization effort, some pieces of code might be suitable for reuse and could eventually become their own little tools in their own little repositories. Other repos could host (sets of) notebooks illustrating the analysis underlying corresponding journal publications.&lt;/p&gt;
&lt;p&gt;Of course, if you release something that you hope will have an impact, you want to have some sort of quality assurance. Therefore, my group would start encouraging us to test and provide feedback on each other’s code. Collaboration and exchange within the research group would drastically increase.&lt;/p&gt;
&lt;p&gt;How is that possible when each PhD student works on ‘his own’ project? First of all, because it pays. To stop reinventing the wheel will actually save a lot time. But more importantly: perhaps that status quo is also up for revision.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The proposition of one of my peers that ‘ &lt;em&gt;Becoming an independent scientist is often mistaken for working alone&lt;/em&gt; ’ could finally become a thing of the past.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Okay, I seem to be going astray here. But I &lt;em&gt;do&lt;/em&gt; think this is the direction in which we’re headed. After &lt;a href=&quot;https://www.openaccess.nl/en/what-is-open-access&quot;&gt;open access publications&lt;/a&gt; and &lt;a href=&quot;https://www.force11.org/group/fairgroup/fairprinciples&quot;&gt;FAIR data&lt;/a&gt;, software is the &lt;a href=&quot;https://content.iospress.com/articles/data-science/ds190026&quot;&gt;next big thing&lt;/a&gt; in open science. The eScience Center is &lt;a href=&quot;https://www.esciencecenter.nl/news/netherlands-escience-center-and-dans-launch-new-fair-software-website-2/&quot;&gt;actively involved&lt;/a&gt; in making this transformation possible.&lt;/p&gt;
&lt;h3 id=&quot;boarding-an-existing-project&quot;&gt;Boarding an existing project&lt;/h3&gt;
&lt;p&gt;The last lesson I want to share is probably the most important one. At this point, I hope you’re all enthusiastic to start sharing your code. But before you go, please consider the image below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;283&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xfyQzwHuHr3xQSjD-498ccc5c.D1hsCotm_2esRr2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://xkcd.com/927/&quot;&gt;https://xkcd.com/927/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The notion that you’d better use an existing standard, even if it doesn’t exactly fit your use case, probably applies even more to software than to usb-cables. Not only can you benefit from what’s already there, but more importantly, you’ll get involved with an existing community.&lt;/p&gt;
&lt;p&gt;If you build something from scratch, the impact is null unless you convince many potential users to abandon their own workflow in favor of yours. Contributing to an existing project is much easier, and you’ll immediately create an impact for all its users.&lt;/p&gt;
&lt;p&gt;And that’s not all. Boarding an existing project means more collaboration from which you can benefit. And you’ll have less to worry about the maintenance and sustainability of your code.&lt;/p&gt;
&lt;p&gt;One of the projects I get to contribute to at the eScience Center is &lt;a href=&quot;https://esmvaltool.readthedocs.io/en/latest/introduction.html&quot;&gt;ESMValTool&lt;/a&gt;. This tool consists of two main repositories: one of them contains the actual ‘machinery’ to perform robust and efficient climate data analysis. The other repository is mostly a collection of ‘recipes’. I think this is a prime example of how a large community of climate scientists (re-)use a common code base to perform a broad variety of analyses that can easily be reproduced.&lt;/p&gt;
&lt;h3 id=&quot;a-career-path-for-research-software-engineers&quot;&gt;A career path for Research Software Engineers&lt;/h3&gt;
&lt;p&gt;When I applied at the eScience center, I knew I wanted to contribute to ‘better’ science or improved scientific practice. But I wasn’t sure exactly how. Already after six months, I’ve learned a lot of tricks and obtained many new insights.&lt;/p&gt;
&lt;p&gt;This video nicely illustrates what reproducible research could look like.&lt;/p&gt;
&lt;p&gt;Sometimes I wish I could go back to the start of my PhD, to start fresh and do everything ‘the proper way’. I now have a much clearer vision on how FAIR and open science can actually be implemented in my field, and I could put that into practice.&lt;/p&gt;
&lt;p&gt;But I’ve also learned about myself. I’ve discovered a community of like-minded people that identify as &lt;a href=&quot;https://nl-rse.org/&quot;&gt;Research Software Engineers&lt;/a&gt;. In a &lt;a href=&quot;https://zenodo.org/record/495360#.XnUY5FHQg5l&quot;&gt;very well-written report&lt;/a&gt;, the UK-RSE community explains how this community has sprouted. They also write:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A career path for Research Software Engineers would increase access to skills that are vital to modern research.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I couldn’t agree more. For all my enthusiasm about my work, I understand that not all scientists feel the same. That’s why we need each other. RSEs can look after the software so others can focus on the science. I’ll be the RSE.&lt;/p&gt;
&lt;h3 id=&quot;thanks-for-reading&quot;&gt;Thanks for reading!&lt;/h3&gt;
&lt;p&gt;I hope I’ve inspired you to pursue the path of FAIR and reproducible science. If you want to read more, there are many excellent resources out there. I highly recommend the &lt;a href=&quot;http://the-turing-way.netlify.com/&quot;&gt;Turing Way&lt;/a&gt;. And don’t hesitate to get in touch:-).&lt;/p&gt;
&lt;p&gt;You can reach me via &lt;a href=&quot;mailto:p.kalverla@esciencecenter.nl&quot;&gt;email&lt;/a&gt; or &lt;a href=&quot;https://www.linkedin.com/in/peter9192/&quot;&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Wed, 25 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;on-the-road-towards-fair-and-reproducible-science&quot;&gt;On the road towards FAIR and reproducible science.&lt;/h2&gt;
&lt;p&gt;Ever find yourself hesitating to send that important email, cursor hovering over the send button? For me, it’s grown into a curious habit. I particularly recall the time that I had to submit a code sample for my job application at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt;. Sharing my code felt like publishing my diary. (If you feel the same, be sure to read the part about linters).&lt;/p&gt;
&lt;p&gt;My strategy for the job interview was simple: I was frankly going to admit that my code wasn’t great. I would explain why I thought this was a problem, not just for me, but for science as a whole. And then beg to be hired so I could contribute to the solution. &lt;em&gt;It was super effective.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So what is this problem that turned a scientist into a research software engineer? It has everything to do with the digital competence required to work with large and complex models and data sets, in a manner consistent with the principles of FAIR and open science (as illustrated below). As a PhD student, I never quite felt properly equipped to effectively wield the tools and technologies that are available to this effect.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;750&quot; height=&quot;530&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_bqZuEZ4aKevZpJVu-b09ef874.LTKy3FVl_1XL5MB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This image was created by Scriberia for The Turing Way community and is used under a CC-BY licence.&lt;/p&gt;
&lt;p&gt;That’s why I applied at the eScience Center. Because being surrounded by experts is the easiest way to become an expert yourself. And because I wanted this expertise to become widespread in the academic world. Today, six months into my eScience adventure, I want to share some of the lessons I’ve learned with my scientific peers.&lt;/p&gt;
&lt;p&gt;I’ll start with something I found quite surprising: treating research code as ‘software’. I’ll explain how that can help to think about re-use and reproducibility. Sharing code is an essential, and therefore I continue with a number of lessons I learned about sharing software. The last two lessons are about reuse of existing software and a community of Research Software Engineers that I discovered.&lt;/p&gt;
&lt;h3 id=&quot;research-code-vs-scientific-software&quot;&gt;Research code vs scientific software&lt;/h3&gt;
&lt;p&gt;Most of my everyday research activities centered around data analysis, which typically consists of a long exploratory phase and then converges towards something publishable. I never thought of the selected fragments of code, tailored to my publications, as (research) software. I still think this is a bit far-fetched, but I &lt;em&gt;do&lt;/em&gt; see now that this &lt;em&gt;scientific software perspective&lt;/em&gt; completely changes the way I think of my code in retrospect.&lt;/p&gt;
&lt;p&gt;What mostly set ‘my code’ apart from ‘software’ was that it was tailored to my use case, whereas software would be more generally applicable. It felt as a humble perspective at the time, but come to think of it, perhaps the term &lt;em&gt;downplay&lt;/em&gt; better captures my reluctance to think of my code as something bigger than my own scribbles. It is an attitude that hampers re-use and, consequently, progress.&lt;/p&gt;
&lt;p&gt;I think everyone can agree that sharing research code, even if it’s just for reproducibility, can be considered good practice. So why aren’t we doing it? I think there are three* main obstacles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We’re insecure about our research code&lt;/li&gt;
&lt;li&gt;We’re willing to share, but don’t know how&lt;/li&gt;
&lt;li&gt;A lack of time, priority or incentive&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The good news is that all these issues can easily be addressed if we stop thinking of (‘just my’) code and start thinking more in terms of research software. Software developers (&lt;a href=&quot;https://www.techwell.com/techwell-insights/2013/12/why-best-programmers-are-lazy-and-act-dumb&quot;&gt;lazy as they are&lt;/a&gt;) have come up with all kinds of tools and tricks and practices and whatnot to facilitate and automate issues like quality control and collaboration.&lt;/p&gt;
&lt;p&gt;*I’m assuming you’re &lt;em&gt;willing&lt;/em&gt; to share the code here. If you want to keep it to yourself, there are options, but we should have a good discussion about that…&lt;/p&gt;
&lt;h3 id=&quot;improve-your-code-using-linters&quot;&gt;Improve your code using linters&lt;/h3&gt;
&lt;p&gt;For example, I wish I had known about ‘linters’ before I submitted my code sample for the job application.&lt;/p&gt;
&lt;p&gt;Linters are little tools that will check whether your code is up to standard. There are many linters for various programming languages that focus on different sets of standards. Many decent code editors offer plugins that provide suggestions as you go. The image below shows an example for Python and &lt;a href=&quot;https://atom.io/&quot;&gt;Atom&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;522&quot; height=&quot;302&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_ec0KLCI8_avDgIRw-f4562f4d.CtsQ6mQP_ZXWugu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example view from &lt;a href=&quot;https://atom.io/packages/linter-python-pep257&quot;&gt;https://atom.io/packages/linter-python-pep257&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here, &lt;a href=&quot;https://www.python.org/dev/peps/pep-0257/&quot;&gt;pep257&lt;/a&gt; refers to style guidelines for Python documentation. Flake8 combines several common Python quality checks, including &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;pep8&lt;/a&gt; adherence. For those who like to work with Jupyter notebooks: there are several plugins to check or even &lt;a href=&quot;https://jupyterlab-code-formatter.readthedocs.io/en/latest/index.html&quot;&gt;auto-format&lt;/a&gt; your code. These tools are great to help you improve your code formatting and learn about quality standards.&lt;/p&gt;
&lt;h3 id=&quot;use-project-templates-to-organize-your-work&quot;&gt;Use project templates to organize your work&lt;/h3&gt;
&lt;p&gt;Research projects usually consist of more than code, and you don’t want your beautiful code to be undermined by a messy project structure. But organizing your work can be a challenge. I for one have wished for guidance more than once.&lt;/p&gt;
&lt;p&gt;Luckily, more people are facing this problem, and some have come up with solutions. One of those solutions is &lt;a href=&quot;https://cookiecutter.readthedocs.io/en/1.7.0/index.html&quot;&gt;Cookiecutter&lt;/a&gt;, ‘a tool for creating projects from templates’. There are templates for many kinds of projects, so you can choose one that suits your needs, for example &lt;a href=&quot;https://cookiecutter.readthedocs.io/en/1.7.0/README.html#reproducible-science&quot;&gt;Reproducible Science&lt;/a&gt;. For the more experienced Python programmers, the eScience Center developed a &lt;a href=&quot;https://github.com/NLeSC/python-template&quot;&gt;template for Python packages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The tool automatically sets up a directory structure for your project. It also creates things like a license and a README file. These will be useful when you’re ready to share your project. An important advantage of using a standardized project structure is that it will make it easier for others to navigate your project.&lt;/p&gt;
&lt;h3 id=&quot;sharing-is-easy-version-control-is-great&quot;&gt;Sharing is easy, version control is great&lt;/h3&gt;
&lt;p&gt;Once there’s no more need to be shy about our projects, let’s talk about &lt;em&gt;how&lt;/em&gt; to share it. Software repositories like GitHub (or GitLab, or the like) are the way to go here. During my PhD I was familiar with the basics of version control and GitHub, but I found it quite cumbersome as I was just working on it alone. Therefore, I never made it to all the nice features.&lt;/p&gt;
&lt;p&gt;For example, GitHub offers a great workflow for code review. You can configure it such that you’re code must always be checked by at least one other person. You can also set it up to perform all kinds of checks and tests. You can add various &lt;a href=&quot;https://www.freecodecamp.org/news/how-to-use-badges-to-stop-feeling-like-a-noob-d4e6600d37d2/&quot;&gt;automated quality badges&lt;/a&gt;. A lot is happening around notebooks as well (&lt;a href=&quot;https://github.com/reviewNB/treon&quot;&gt;example&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;439&quot; height=&quot;250&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_eRGe6Sr1ihmPTH92-aecc852c.pZYejZPL_Z10BF1I.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://xkcd.com/1296/&quot;&gt;https://xkcd.com/1296/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By writing nice commit messages, it becomes easy to show all the hard work you’ve been doing to e.g. your supervisor. Tangible output is nice! And why not use tags or releases for making a stable version for the reviewers of your publication? And then another release when the paper is accepted.&lt;/p&gt;
&lt;p&gt;The problem here is that, although this all sounds very nice, it requires collaboration and therefore commitment from a larger entity than yourself. It’s probably best organized at the level of a chair group/research unit. And that brings me to the last obstacle I listed above: ‘it all sounds very nice, but we simply don’t have the time…’&lt;/p&gt;
&lt;h3 id=&quot;proper-recognition-for-research-code-through-software-citations&quot;&gt;Proper recognition for research code through software citations&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://the-turing-way.netlify.com/credit/credit.html&quot;&gt;Software is citeable&lt;/a&gt;. It is not (yet) commonplace, but think about how this can change the everyday life of an academic. Imagine my PhD supervisor valued my code just as much as he valued my research papers. Time spent on code would suddenly have a purpose. All those hours of endless debugging would have a clear, visible, &lt;em&gt;citeable&lt;/em&gt; output product. Impact factor over 9000.&lt;/p&gt;
&lt;p&gt;My group (at the time) could have owned and maintained a public code base, and encouraged and assisted every employee to contribute. With a little generalization effort, some pieces of code might be suitable for reuse and could eventually become their own little tools in their own little repositories. Other repos could host (sets of) notebooks illustrating the analysis underlying corresponding journal publications.&lt;/p&gt;
&lt;p&gt;Of course, if you release something that you hope will have an impact, you want to have some sort of quality assurance. Therefore, my group would start encouraging us to test and provide feedback on each other’s code. Collaboration and exchange within the research group would drastically increase.&lt;/p&gt;
&lt;p&gt;How is that possible when each PhD student works on ‘his own’ project? First of all, because it pays. To stop reinventing the wheel will actually save a lot time. But more importantly: perhaps that status quo is also up for revision.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The proposition of one of my peers that ‘ &lt;em&gt;Becoming an independent scientist is often mistaken for working alone&lt;/em&gt; ’ could finally become a thing of the past.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Okay, I seem to be going astray here. But I &lt;em&gt;do&lt;/em&gt; think this is the direction in which we’re headed. After &lt;a href=&quot;https://www.openaccess.nl/en/what-is-open-access&quot;&gt;open access publications&lt;/a&gt; and &lt;a href=&quot;https://www.force11.org/group/fairgroup/fairprinciples&quot;&gt;FAIR data&lt;/a&gt;, software is the &lt;a href=&quot;https://content.iospress.com/articles/data-science/ds190026&quot;&gt;next big thing&lt;/a&gt; in open science. The eScience Center is &lt;a href=&quot;https://www.esciencecenter.nl/news/netherlands-escience-center-and-dans-launch-new-fair-software-website-2/&quot;&gt;actively involved&lt;/a&gt; in making this transformation possible.&lt;/p&gt;
&lt;h3 id=&quot;boarding-an-existing-project&quot;&gt;Boarding an existing project&lt;/h3&gt;
&lt;p&gt;The last lesson I want to share is probably the most important one. At this point, I hope you’re all enthusiastic to start sharing your code. But before you go, please consider the image below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;283&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xfyQzwHuHr3xQSjD-498ccc5c.D1hsCotm_2esRr2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://xkcd.com/927/&quot;&gt;https://xkcd.com/927/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The notion that you’d better use an existing standard, even if it doesn’t exactly fit your use case, probably applies even more to software than to usb-cables. Not only can you benefit from what’s already there, but more importantly, you’ll get involved with an existing community.&lt;/p&gt;
&lt;p&gt;If you build something from scratch, the impact is null unless you convince many potential users to abandon their own workflow in favor of yours. Contributing to an existing project is much easier, and you’ll immediately create an impact for all its users.&lt;/p&gt;
&lt;p&gt;And that’s not all. Boarding an existing project means more collaboration from which you can benefit. And you’ll have less to worry about the maintenance and sustainability of your code.&lt;/p&gt;
&lt;p&gt;One of the projects I get to contribute to at the eScience Center is &lt;a href=&quot;https://esmvaltool.readthedocs.io/en/latest/introduction.html&quot;&gt;ESMValTool&lt;/a&gt;. This tool consists of two main repositories: one of them contains the actual ‘machinery’ to perform robust and efficient climate data analysis. The other repository is mostly a collection of ‘recipes’. I think this is a prime example of how a large community of climate scientists (re-)use a common code base to perform a broad variety of analyses that can easily be reproduced.&lt;/p&gt;
&lt;h3 id=&quot;a-career-path-for-research-software-engineers&quot;&gt;A career path for Research Software Engineers&lt;/h3&gt;
&lt;p&gt;When I applied at the eScience center, I knew I wanted to contribute to ‘better’ science or improved scientific practice. But I wasn’t sure exactly how. Already after six months, I’ve learned a lot of tricks and obtained many new insights.&lt;/p&gt;
&lt;p&gt;This video nicely illustrates what reproducible research could look like.&lt;/p&gt;
&lt;p&gt;Sometimes I wish I could go back to the start of my PhD, to start fresh and do everything ‘the proper way’. I now have a much clearer vision on how FAIR and open science can actually be implemented in my field, and I could put that into practice.&lt;/p&gt;
&lt;p&gt;But I’ve also learned about myself. I’ve discovered a community of like-minded people that identify as &lt;a href=&quot;https://nl-rse.org/&quot;&gt;Research Software Engineers&lt;/a&gt;. In a &lt;a href=&quot;https://zenodo.org/record/495360#.XnUY5FHQg5l&quot;&gt;very well-written report&lt;/a&gt;, the UK-RSE community explains how this community has sprouted. They also write:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A career path for Research Software Engineers would increase access to skills that are vital to modern research.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I couldn’t agree more. For all my enthusiasm about my work, I understand that not all scientists feel the same. That’s why we need each other. RSEs can look after the software so others can focus on the science. I’ll be the RSE.&lt;/p&gt;
&lt;h3 id=&quot;thanks-for-reading&quot;&gt;Thanks for reading!&lt;/h3&gt;
&lt;p&gt;I hope I’ve inspired you to pursue the path of FAIR and reproducible science. If you want to read more, there are many excellent resources out there. I highly recommend the &lt;a href=&quot;http://the-turing-way.netlify.com/&quot;&gt;Turing Way&lt;/a&gt;. And don’t hesitate to get in touch:-).&lt;/p&gt;
&lt;p&gt;You can reach me via &lt;a href=&quot;mailto:p.kalverla@esciencecenter.nl&quot;&gt;email&lt;/a&gt; or &lt;a href=&quot;https://www.linkedin.com/in/peter9192/&quot;&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_bqZuEZ4aKevZpJVu-b09ef874.LTKy3FVl.jpg" medium="image"/><author>Peter Kalverla</author></item><item><title>A mathematician in quarantine</title><link>https://blog2.esciencecenter.nl/posts/2020-03-18---a-mathematician-in-quarantine</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-03-18---a-mathematician-in-quarantine</guid><description>&lt;h2 id=&quot;flattening-the-curve-and-why-you-should-stay-at-home&quot;&gt;Flattening the curve, and why you should stay at home&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_WKJgUFCArHheoUke-bf0ce2cc.ClaEskbU_aBzDz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by History in HD on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I write this entry at the beginning of the COVID19 crisis in Europe. I am not a medical expert and, thus, the reader will not find any health advice in the current text. What I am instead is a mathematician. If you ever felt intrigued about how forecasts are being made about the progression of a contagious disease, this text may satisfy your curiosity.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Perhaps you’ve heard that the number of infections are rising “exponentially”. While in common language “exponentially” seems to mean “rapidly and much faster than yesterday”, it has a more precise meaning in mathematics. Indeed, there is a whole subfield of applied mathematics devoted to the propagation of diseases: mathematical epidemiology. Here we’ll take a look at one of its most basic models.&lt;/p&gt;
&lt;h2 id=&quot;the-kermack-mckendrick--sir-model&quot;&gt;The Kermack-McKendrick / SIR model&lt;/h2&gt;
&lt;p&gt;The most famous model describing the propagation of a contagious disease is that of Kermack and McKendrick, introduced in 1927. It is nicknamed as the SIR model, because of the names of the three state variables it keeps track of, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S: the population of susceptible individuals&lt;/li&gt;
&lt;li&gt;I: the population of infected individuals&lt;/li&gt;
&lt;li&gt;R: the population of recovered individuals&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The model looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;324&quot; height=&quot;284&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Aw1pBPik3w-O0MuO9vLxaw-35ad8edf.CMkwtjIX_ZgWsSv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Equations for the SIR model&lt;/p&gt;
&lt;p&gt;But don’t let differential equations scare you! It is possible to understand the details of this model using the mental picture of three water tanks arranged as in the figure below. In this figure, all the population is in the “susceptible tank”. Nobody is infected, so nobody can get infected and everything is all right.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;938&quot; height=&quot;1379&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VvJYAqn_vqV-Nm3rL83Ggg-9db72f23.U_3Jxeng_2hb1Eu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This figure represents a normal situation. All population is susceptible, and remains so, as there is no flow in the taps&lt;/p&gt;
&lt;p&gt;But, what happens if a disease enters the system? That is, what happens if the population of infected is not zero? Well… then, the taps open!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;992&quot; height=&quot;1379&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_R8dH541hVrHHdL_Dr6utCA-5e95a3fd.C--2Z0tS_1vsiFq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If someone is infected, the taps open, allowing for movement between tanks and, thus, dynamical changes in the different populations&lt;/p&gt;
&lt;p&gt;The equations we showed above are just a statement about how strong the flow of each tap is. Particularly, the upper tap empties the “susceptible tank” and fills the “infected” one. The upper tap thus represents contagion, and the magnitude of its flow, &lt;strong&gt;r·S·I&lt;/strong&gt;, grows both with the number of susceptible and infected people (think about it, it makes sense). The constant &lt;strong&gt;r&lt;/strong&gt; regulates the overall speed of contagion. The lower tap empties the infected tank, and thus represents recovery. The magnitude of its flow is &lt;strong&gt;a·I&lt;/strong&gt;, so the parameter &lt;strong&gt;a&lt;/strong&gt; represents the relative recovery rate.&lt;/p&gt;
&lt;p&gt;Check again the differential equations given above with this picture of inflows and outflows in mind. Note that inflows are positive and outflows are negative. The equations will just come to life.&lt;/p&gt;
&lt;h2 id=&quot;how-do-the-solutions-look&quot;&gt;How do the solutions look?&lt;/h2&gt;
&lt;p&gt;The specific solutions of the SIR model depend on the initial state and the values of the parameters &lt;strong&gt;r&lt;/strong&gt; and &lt;strong&gt;a&lt;/strong&gt;. An interactive Shiny applet can be found &lt;a href=&quot;https://pabrod.shinyapps.io/SIRmodel/&quot;&gt;here&lt;/a&gt; (source &lt;a href=&quot;https://github.com/PabRod/SIR&quot;&gt;here&lt;/a&gt;). A possible solution is sketched below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;529&quot; height=&quot;414&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4VUyoONvXrqQtwMW6zDNVQ-e3d111b9.DCxr5-jH_Z1W68ax.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Generated with &lt;a href=&quot;https://pabrod.shinyapps.io/SIRmodel/&quot;&gt;https://pabrod.shinyapps.io/SIRmodel/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-this-good-for&quot;&gt;What is this good for?&lt;/h2&gt;
&lt;p&gt;The SIR model is an extremely simple model of a very complex phenomenon. Nevertheless, it suffices to teach us a couple of lessons. By playing with the contagion (&lt;strong&gt;r&lt;/strong&gt;) and recovery (&lt;strong&gt;a&lt;/strong&gt;) parameters in the applet linked above, you’ll notice that the evolution curves change.&lt;/p&gt;
&lt;p&gt;Lowering &lt;strong&gt;r&lt;/strong&gt; (lower contagion rate) and/or increasing &lt;strong&gt;a&lt;/strong&gt; (higher recovery rate) sound like good news, and they are. Their main effect is to &lt;strong&gt;flatten the contagion curve&lt;/strong&gt;, spreading the number of cases in time and avoiding a potential collapse of the health system.&lt;/p&gt;
&lt;p&gt;How can we achieve this? Well, increasing &lt;strong&gt;a&lt;/strong&gt; (the relative recovery rate) is currently not in our hands, as right now there is no cure for the COVID19. A vaccine will dramatically reduce the susceptible population, but this is also still not developed. But lowering the contagion rate &lt;strong&gt;r&lt;/strong&gt; can be achieved, for instance, by minimizing social contact and staying at home as much as possible.&lt;/p&gt;
&lt;p&gt;Your friends said it, the authorities said it, and now the mathematics say it: just stay at home.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kermack, W. O. and McKendrick, A. G. “A Contribution to the Mathematical Theory of Epidemics.” &lt;em&gt;Proc. Roy. Soc. Lond. A&lt;/em&gt; &lt;strong&gt;115&lt;/strong&gt;, 700–721, 1927.&lt;/li&gt;
&lt;li&gt;Murray, James D. &lt;em&gt;Mathematical Biology I. An Introduction&lt;/em&gt;. 3 Vol. 17. New York: Springer, 2002.&lt;/li&gt;
&lt;li&gt;Agent-based simulation at &lt;a href=&quot;https://www.washingtonpost.com/graphics/2020/world/corona-simulator/&quot;&gt;The Washington Post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This and more elaborate models can be found in &lt;a href=&quot;https://en.wikipedia.org/wiki/Compartmental_models_in_epidemiology&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An accessible article about modelling of the &lt;em&gt;COVID19&lt;/em&gt; in &lt;a href=&quot;https://arstechnica.com/science/2020/03/new-model-examines-impact-of-different-methods-of-coronavirus-control/&quot;&gt;Ars Technica&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;attribution&quot;&gt;Attribution&lt;/h2&gt;
&lt;p&gt;The tap icon used in the figures was made by &lt;a href=&quot;https://www.flaticon.com/authors/iconixar&quot;&gt;Iconixar&lt;/a&gt; from &lt;a href=&quot;http://www.flaticon.com/&quot;&gt;www.flaticon.com&lt;/a&gt;&lt;/p&gt;</description><pubDate>Wed, 18 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;flattening-the-curve-and-why-you-should-stay-at-home&quot;&gt;Flattening the curve, and why you should stay at home&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_WKJgUFCArHheoUke-bf0ce2cc.ClaEskbU_aBzDz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by History in HD on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I write this entry at the beginning of the COVID19 crisis in Europe. I am not a medical expert and, thus, the reader will not find any health advice in the current text. What I am instead is a mathematician. If you ever felt intrigued about how forecasts are being made about the progression of a contagious disease, this text may satisfy your curiosity.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Perhaps you’ve heard that the number of infections are rising “exponentially”. While in common language “exponentially” seems to mean “rapidly and much faster than yesterday”, it has a more precise meaning in mathematics. Indeed, there is a whole subfield of applied mathematics devoted to the propagation of diseases: mathematical epidemiology. Here we’ll take a look at one of its most basic models.&lt;/p&gt;
&lt;h2 id=&quot;the-kermack-mckendrick--sir-model&quot;&gt;The Kermack-McKendrick / SIR model&lt;/h2&gt;
&lt;p&gt;The most famous model describing the propagation of a contagious disease is that of Kermack and McKendrick, introduced in 1927. It is nicknamed as the SIR model, because of the names of the three state variables it keeps track of, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S: the population of susceptible individuals&lt;/li&gt;
&lt;li&gt;I: the population of infected individuals&lt;/li&gt;
&lt;li&gt;R: the population of recovered individuals&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The model looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;324&quot; height=&quot;284&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Aw1pBPik3w-O0MuO9vLxaw-35ad8edf.CMkwtjIX_ZgWsSv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Equations for the SIR model&lt;/p&gt;
&lt;p&gt;But don’t let differential equations scare you! It is possible to understand the details of this model using the mental picture of three water tanks arranged as in the figure below. In this figure, all the population is in the “susceptible tank”. Nobody is infected, so nobody can get infected and everything is all right.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;938&quot; height=&quot;1379&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VvJYAqn_vqV-Nm3rL83Ggg-9db72f23.U_3Jxeng_2hb1Eu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This figure represents a normal situation. All population is susceptible, and remains so, as there is no flow in the taps&lt;/p&gt;
&lt;p&gt;But, what happens if a disease enters the system? That is, what happens if the population of infected is not zero? Well… then, the taps open!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;992&quot; height=&quot;1379&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_R8dH541hVrHHdL_Dr6utCA-5e95a3fd.C--2Z0tS_1vsiFq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If someone is infected, the taps open, allowing for movement between tanks and, thus, dynamical changes in the different populations&lt;/p&gt;
&lt;p&gt;The equations we showed above are just a statement about how strong the flow of each tap is. Particularly, the upper tap empties the “susceptible tank” and fills the “infected” one. The upper tap thus represents contagion, and the magnitude of its flow, &lt;strong&gt;r·S·I&lt;/strong&gt;, grows both with the number of susceptible and infected people (think about it, it makes sense). The constant &lt;strong&gt;r&lt;/strong&gt; regulates the overall speed of contagion. The lower tap empties the infected tank, and thus represents recovery. The magnitude of its flow is &lt;strong&gt;a·I&lt;/strong&gt;, so the parameter &lt;strong&gt;a&lt;/strong&gt; represents the relative recovery rate.&lt;/p&gt;
&lt;p&gt;Check again the differential equations given above with this picture of inflows and outflows in mind. Note that inflows are positive and outflows are negative. The equations will just come to life.&lt;/p&gt;
&lt;h2 id=&quot;how-do-the-solutions-look&quot;&gt;How do the solutions look?&lt;/h2&gt;
&lt;p&gt;The specific solutions of the SIR model depend on the initial state and the values of the parameters &lt;strong&gt;r&lt;/strong&gt; and &lt;strong&gt;a&lt;/strong&gt;. An interactive Shiny applet can be found &lt;a href=&quot;https://pabrod.shinyapps.io/SIRmodel/&quot;&gt;here&lt;/a&gt; (source &lt;a href=&quot;https://github.com/PabRod/SIR&quot;&gt;here&lt;/a&gt;). A possible solution is sketched below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;529&quot; height=&quot;414&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4VUyoONvXrqQtwMW6zDNVQ-e3d111b9.DCxr5-jH_Z1W68ax.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Generated with &lt;a href=&quot;https://pabrod.shinyapps.io/SIRmodel/&quot;&gt;https://pabrod.shinyapps.io/SIRmodel/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-this-good-for&quot;&gt;What is this good for?&lt;/h2&gt;
&lt;p&gt;The SIR model is an extremely simple model of a very complex phenomenon. Nevertheless, it suffices to teach us a couple of lessons. By playing with the contagion (&lt;strong&gt;r&lt;/strong&gt;) and recovery (&lt;strong&gt;a&lt;/strong&gt;) parameters in the applet linked above, you’ll notice that the evolution curves change.&lt;/p&gt;
&lt;p&gt;Lowering &lt;strong&gt;r&lt;/strong&gt; (lower contagion rate) and/or increasing &lt;strong&gt;a&lt;/strong&gt; (higher recovery rate) sound like good news, and they are. Their main effect is to &lt;strong&gt;flatten the contagion curve&lt;/strong&gt;, spreading the number of cases in time and avoiding a potential collapse of the health system.&lt;/p&gt;
&lt;p&gt;How can we achieve this? Well, increasing &lt;strong&gt;a&lt;/strong&gt; (the relative recovery rate) is currently not in our hands, as right now there is no cure for the COVID19. A vaccine will dramatically reduce the susceptible population, but this is also still not developed. But lowering the contagion rate &lt;strong&gt;r&lt;/strong&gt; can be achieved, for instance, by minimizing social contact and staying at home as much as possible.&lt;/p&gt;
&lt;p&gt;Your friends said it, the authorities said it, and now the mathematics say it: just stay at home.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kermack, W. O. and McKendrick, A. G. “A Contribution to the Mathematical Theory of Epidemics.” &lt;em&gt;Proc. Roy. Soc. Lond. A&lt;/em&gt; &lt;strong&gt;115&lt;/strong&gt;, 700–721, 1927.&lt;/li&gt;
&lt;li&gt;Murray, James D. &lt;em&gt;Mathematical Biology I. An Introduction&lt;/em&gt;. 3 Vol. 17. New York: Springer, 2002.&lt;/li&gt;
&lt;li&gt;Agent-based simulation at &lt;a href=&quot;https://www.washingtonpost.com/graphics/2020/world/corona-simulator/&quot;&gt;The Washington Post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This and more elaborate models can be found in &lt;a href=&quot;https://en.wikipedia.org/wiki/Compartmental_models_in_epidemiology&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An accessible article about modelling of the &lt;em&gt;COVID19&lt;/em&gt; in &lt;a href=&quot;https://arstechnica.com/science/2020/03/new-model-examines-impact-of-different-methods-of-coronavirus-control/&quot;&gt;Ars Technica&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;attribution&quot;&gt;Attribution&lt;/h2&gt;
&lt;p&gt;The tap icon used in the figures was made by &lt;a href=&quot;https://www.flaticon.com/authors/iconixar&quot;&gt;Iconixar&lt;/a&gt; from &lt;a href=&quot;http://www.flaticon.com/&quot;&gt;www.flaticon.com&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Aw1pBPik3w-O0MuO9vLxaw-35ad8edf.CMkwtjIX.png" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Remote revolution at the eScience Center</title><link>https://blog2.esciencecenter.nl/posts/2020-03-18---remote-revolution-at-the-escience-center</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-03-18---remote-revolution-at-the-escience-center</guid><description>&lt;h2 id=&quot;tools-and-practices-for-collaborating-from-home&quot;&gt;Tools and practices for collaborating from home&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3601&quot; height=&quot;5401&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZUCKx3r5NhRcr-sFwMhTBQ-75fd2b47.DkreyW7G_ZQ3k3u.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One of the core values of the Netherlands eScience Center is collaboration. We work with teams and even whole communities of scientists. Communication is key.&lt;/p&gt;
&lt;p&gt;The COVID-19 pandemic has forced us into social isolation. But we simply cannot do our jobs in complete isolation. Luckily, we don’t have to, as many people that have suddenly been sent to work from home are finding out.&lt;/p&gt;
&lt;p&gt;In this post, I’ll briefly list some of the tools and practices we’ve adopted the past few days to keep collaboration going.&lt;/p&gt;
&lt;p&gt;Disclaimer: we pay Microsoft for the Office 365 stack, so we’re a bit biased towards / locked-in by those tools, but I’m sure alternatives work fine as well. The important thing is to realize that you can do a lot remotely.&lt;/p&gt;
&lt;h2 id=&quot;work-from-home&quot;&gt;Work from home&lt;/h2&gt;
&lt;p&gt;Of course, many people do not have the luxury of being able to work from home. But we do, and so our organization has gone into full home mode.&lt;/p&gt;
&lt;p&gt;Usually, we divide our time between being at the office and working “on location”. At the office, we exchange knowledge, work together on projects and, of course, socialize. We also work at the location of the project partners, i.e. at the universities or institutes of the domain scientists. There we… basically do the same:) Sometimes we go on conferences, but let’s forget about that for a moment (although… see below).&lt;/p&gt;
&lt;p&gt;Working on projects usually means trying to understand the problem, finding solutions using digital technologies and then implementing them. The first part means: talking to project partners. The second means: thinking, talking to colleagues and, again, talking to project partners. Implementing solutions means: programming; sometimes alone, sometimes together. All of this is often done iteratively, so you cycle through steps 1, 2 and 3 over and over again.&lt;/p&gt;
&lt;p&gt;So, completely working from home is only possible when you have communication channels with low latency and where you can interact with high bandwidth: written words alone often don’t cut it. Video is already a lot better. Of course, there are many solutions available for this and many people were already using these tools a lot, even before we started to fully work from home: Skype, &lt;a href=&quot;https://zoom.us/&quot;&gt;Zoom&lt;/a&gt; (&lt;a href=&quot;https://docs.google.com/document/d/1xdENyIV1505FDXBj7n5PaaHinGGUWc1R0ib1t7DRSCw/edit&quot;&gt;see here for a nice guide&lt;/a&gt;), &lt;a href=&quot;https://whereby.com/&quot;&gt;Whereby&lt;/a&gt;, &lt;a href=&quot;https://www.vidyo.com/&quot;&gt;Vidyo&lt;/a&gt;, &lt;a href=&quot;https://www.gotomeeting.com/nl-nl&quot;&gt;GoToMeeting&lt;/a&gt;, &lt;a href=&quot;https://teams.microsoft.com/&quot;&gt;Teams&lt;/a&gt; and even our neighbors at SURF have their own tool for the Dutch academic community called &lt;a href=&quot;https://videobelpilot.surf.nl/&quot;&gt;Videobellen&lt;/a&gt; which seems to work well and is free for those working at Dutch academic institutions.&lt;/p&gt;
&lt;p&gt;Another thing to keep in mind is of course to prevent repetitive strain injury by making sure you have a well adjusted desk setup or whatever else works for you.&lt;/p&gt;
&lt;h2 id=&quot;pair-programming&quot;&gt;Pair programming&lt;/h2&gt;
&lt;p&gt;I would say that maybe 40–60% of the job is actually programming. A lot of coding can be done alone, but often you do need input and Google and Stack Overflow don’t cut it. At such a time, getting quick feedback can make all the difference. Often this can be done over chat or a video call.&lt;/p&gt;
&lt;p&gt;But pair programming is a different game. Sitting in pairs, working on one computer can really help getting through tough problems. Usually one person types and the other is real-time reviewing everything and reflecting on all choices. This way you avoid many errors, design flaws and other sloppiness, which in the long run can make your programming hours much more efficient.&lt;/p&gt;
&lt;p&gt;So what if you can’t sit together in front of one screen? Sharing your screen could be an option, but there are better ones. Visual Studio Code has a &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack&quot;&gt;Live Share extension&lt;/a&gt; that allows you to work together on each other’s code in each other’s editor. My colleagues have tried this and were very happy with it. It turns out even &lt;a href=&quot;https://github.com/FredKSchott/CoVim&quot;&gt;Vim has a plugin for collaborative editing&lt;/a&gt;! It seems a unmaintained, though, but may still be worth a try.&lt;/p&gt;
&lt;p&gt;Of course, other tools for writing together are already more widespread, like Google Docs and Microsoft Office Online for regular documents, or Overleaf for LaTeX documents.&lt;/p&gt;
&lt;h2 id=&quot;talks--colloquia&quot;&gt;Talks &amp;#x26; colloquia&lt;/h2&gt;
&lt;p&gt;Last week I was already in self imposed isolation, but my colloquium talk was planned. Luckily, our A/V team was already looking into remote colloquia. The solution we ended up with was:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up Microsoft Stream to live stream talks from the office (which by now has become temporarily obsolete, as the office is closed… but still nice to have for later). These are then also automatically stored on Stream after the talk, so really convenient.&lt;/li&gt;
&lt;li&gt;Set up Teams to give talks remotely. Also, these can be recorded and saved to Stream automatically.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It turns out this works fine! I got some feedback after the talk, just as I usually get when I give a colloquium, so content-wise, everything is still the same as it was.&lt;/p&gt;
&lt;p&gt;One thing that did feel a bit weird was that the other side was muted, which meant I got no direct feedback at all. So I had no idea whether my brilliant jokes were properly appreciated, for instance. But more importantly: no idea whether people are still following me at all, which is a bit easier to gauge when you can look at them every now and then (not too often, of course, like most people, I much prefer staring at my slides).&lt;/p&gt;
&lt;p&gt;I think unmuting the room (if you are still connected to a “room”) may be a bit nicer, but your mileage may vary. In any case, since we are now in full home mode, everyone will be on Teams for the next colloquium. In that case, muting non-speakers is quite essential. On the other hand, it will probably be easier to interject for individuals with a question. We’ll have to see how it goes, but based on some other talks we already did this way, I expect it will go very well.&lt;/p&gt;
&lt;h2 id=&quot;standups&quot;&gt;Standups&lt;/h2&gt;
&lt;p&gt;Every Monday, we do a full-team (70-ish people) standup. Everybody gets max 30 seconds to update colleagues on whatever they think is relevant. This is a really nice central moment that really brings out the collaborative nature of the center. People ask for help on tricky issues, announce useful new tools they created or found and share their proud moments or sad ones. For me, it’s one of the best ideas we’ve had and I advise everyone to do this.&lt;/p&gt;
&lt;p&gt;This Monday, we had our first fully remote standup and it worked really nicely via Microsoft Teams! You get the bonus of easy recording and automatic uploading to MS Stream (which we already happened to use, because we always manually recorded our colloquia and other plenary talks). Usually, we did not record these meetings and sometimes important announcements are made there first (and probably later via mail, but there might be some delay). Now, everyone can easily stay up to date by checking at their earliest convenience the standup recording. Nice!&lt;/p&gt;
&lt;p&gt;One slight practicality: when you stand in one physical room, doing the round is easy; you just go round the circle. Online, using Teams, it’s not that much harder. You just go down the participants list. The meeting is a bit quieter. Usually, people in the circle tend to respond a bit more. Now, also all the other mics are muted, so, again, you have no idea whether your horrible puns have hit home. But, I must say that the other way around, i.e. on the listening side, it was totally fine and worked just as well as the regular in-person standup.&lt;/p&gt;
&lt;p&gt;Also, in our smaller project oriented teams (5–8 people) we have started using Teams. Morning stand-ups, review meetings, etc.; so far everything has worked perfectly well!&lt;/p&gt;
&lt;h2 id=&quot;psychological-well-being--coffee-time&quot;&gt;Psychological well being &amp;#x26; coffee time!&lt;/h2&gt;
&lt;p&gt;If you feel you’re getting lonely, just open up a group chat for the heck of it and have a coffee together.&lt;/p&gt;
&lt;p&gt;I’ve seen this idea floating around on Reddit as well. Some people even keep a call open all day long. It gives people the feeling that they’re still a bit at the office with their colleagues. Also, if you find it hard to work in complete isolation and silence and crave some background noise, like the kind you may also find in coffee shops, this can actually be a great solution.&lt;/p&gt;
&lt;p&gt;Some other tips to keep your sanity after days of confinement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Try to not work in the same place you sleep, eat or relax&lt;/li&gt;
&lt;li&gt;Keep a schedule, with a focus on not working overtime&lt;/li&gt;
&lt;li&gt;(This may be silly) Don’t work in your pyjamas&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;chat&quot;&gt;Chat&lt;/h2&gt;
&lt;p&gt;Chat works well for socializing and quick questions which are not mission critical, but that you are having trouble figuring out on your own and would like some help on.&lt;/p&gt;
&lt;p&gt;One important condition imho: you need to make sure to not make chat channels essential. There are many stories doing the rounds warning against “always on” culture. Don’t fall into the trap. If you really need to immediately contact someone, call them. If not, use asynchronous communication (mail, issue trackers) and get on with another task.&lt;/p&gt;
&lt;p&gt;Also, many people do not want the distraction of chat at all. So make sure you separate general coffee corner style banter from official, plenary discussions (if you have those at all… which I wouldn’t recommend, except to support the live video calls).&lt;/p&gt;
&lt;p&gt;At the Center, we’ve been using Slack for a few years now, and it has served us well. Since we’re now starting to use Teams for many other things, we’ve also set up chat there. The word is not yet out on which tool works best for us.&lt;/p&gt;
&lt;h2 id=&quot;remote-conferences-nl-rse-meetup&quot;&gt;Remote conferences: NL-RSE meetup&lt;/h2&gt;
&lt;p&gt;Technically this is not an eScience Center activity, but as part of the bigger NL-RSE movement, some of my colleagues are involved in organizing NL-RSE meetups in Utrecht for the Dutch community of research software engineers (RSEs). Some speakers are invited and lots of opportunity to mingle and network is provided.&lt;/p&gt;
&lt;p&gt;Unfortunately, &lt;a href=&quot;https://nl-rse.org/events/2020-03-13-meetup.html&quot;&gt;this time — Friday the 13th&lt;/a&gt; — my colleagues didn’t want to tempt fate and &lt;a href=&quot;https://twitter.com/matkuzak/status/1237735075669848064&quot;&gt;made the wise decision to cancel the in-person event… only to replace it with a fully remote event&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/c2754835142?source=post_page---user_mention--28db59f86766---------------------------------------&quot;&gt;Mateusz Kuzak&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;arranged for the meeting to be held via Zoom. This went very well! &lt;a href=&quot;https://tinyurl.com/2020-03-13-nl-rse&quot;&gt;Minutes can be found here&lt;/a&gt; for those interested. 20+ people attended and had very constructive and interesting sessions, both with three speakers and with a collaborative session that will result in an article on the &lt;a href=&quot;https://lab.kb.nl/about-us/blog&quot;&gt;KB Lab (Royal Dutch Library) blog&lt;/a&gt; here very soon.&lt;/p&gt;
&lt;h3 id=&quot;digital-office-hours&quot;&gt;Digital office hours&lt;/h3&gt;
&lt;p&gt;One additional detail that I really liked was that &lt;a href=&quot;https://twitter.com/matkuzak&quot;&gt;Mateusz&lt;/a&gt; held a digital office hour via Zoom one day in advance of the meetup to help everybody get properly set up.&lt;/p&gt;
&lt;p&gt;This may also be useful in other situations, like when your students want to ask you questions, but you don’t want to be interrupted at every minute of the day. With digital office hours, you can help your students and still have guilt-free deep focused hours of work in the other hours of the day.&lt;/p&gt;
&lt;h3 id=&quot;networking&quot;&gt;Networking&lt;/h3&gt;
&lt;p&gt;One downside of doing online conferences so far is that networking becomes a lot harder when you can’t mingle easily over coffee. One of my colleagues&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/ee774bf64a6b?source=post_page---user_mention--28db59f86766---------------------------------------&quot;&gt;Fakhereh (Sarah) Alidoost&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;experienced this at the &lt;a href=&quot;https://www.eucp-project.eu/&quot;&gt;EUCP&lt;/a&gt; general assembly, which she attended remotely. The rest of the conference was really high quality, though. The meeting layout, sound and video quality using Zoom were very good. Also, Zoom has a “Raise Hand” option, which is very useful.&lt;/p&gt;
&lt;h2 id=&quot;more-inspiration&quot;&gt;More inspiration&lt;/h2&gt;
&lt;p&gt;Many people and companies have already long been experimenting with remote working. For instance, GitLab published the &lt;a href=&quot;https://about.gitlab.com/blog/2015/04/08/the-remote-manifesto/&quot;&gt;Remote Manifesto&lt;/a&gt; with some great general guidelines for making remote working work.&lt;/p&gt;
&lt;p&gt;A few days ago I came across this &lt;a href=&quot;https://www.thegreatcodeadventure.com/my-long-distance-relationship-with-github/&quot;&gt;really, really insightful article about someone working (remotely) at GitHub and the non-obvious challenges she faced transitioning from co-located to remote working&lt;/a&gt;. Turns out it’s about more than just doing video calls. Asynchronous is the keyword. Using issue trackers and other online tools for communication are vital. Indeed, we have long been using these as well, but maybe we still have things to learn about using them even more effectively.&lt;/p&gt;
&lt;p&gt;Further useful resources compiled by&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/c2754835142?source=post_page---user_mention--28db59f86766---------------------------------------&quot;&gt;Mateusz Kuzak&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://hackmd.io/cFL-4VosSfq3RpvCfVpxEQ&quot;&gt;A Lesson to Demonstrate a Few Techniques for Online Meetings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1MdmrNn5g2oa2AA6EGYZhyDx-O_YOoH_HqNGsmP6LKIo/edit?usp=sharing&quot;&gt;Tips for Teaching and Learning Online by The Carpentries Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/abbycabs/status/1237001927734542341?s=21&quot;&gt;Abby’s online meeting tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://foundation.mozilla.org/en/blog/online-meeting-tips/&quot;&gt;Mozilla online meeting tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://about.gitlab.com/company/culture/all-remote/&quot;&gt;Gitlab Guide to all remote&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1EABkSzEdJk5cmMLETpSbXaeDXmFwcTz7SUXP_C3dN9k/edit?usp=drivesdk&quot;&gt;How To Run A Free Online Academic Conference: A Workbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have any further tips or resources, please let me know in the comments or on &lt;a href=&quot;https://twitter.com/eScienceCenter/status/1240253016122458113&quot;&gt;Twitter&lt;/a&gt;! Of course, many tips are out there already. There’s even &lt;a href=&quot;https://www.reddit.com/r/remotework/&quot;&gt;a subreddit dedicated to remote working&lt;/a&gt; that’s surely going to blow up the coming weeks.&lt;/p&gt;</description><pubDate>Wed, 18 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;tools-and-practices-for-collaborating-from-home&quot;&gt;Tools and practices for collaborating from home&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3601&quot; height=&quot;5401&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZUCKx3r5NhRcr-sFwMhTBQ-75fd2b47.DkreyW7G_ZQ3k3u.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One of the core values of the Netherlands eScience Center is collaboration. We work with teams and even whole communities of scientists. Communication is key.&lt;/p&gt;
&lt;p&gt;The COVID-19 pandemic has forced us into social isolation. But we simply cannot do our jobs in complete isolation. Luckily, we don’t have to, as many people that have suddenly been sent to work from home are finding out.&lt;/p&gt;
&lt;p&gt;In this post, I’ll briefly list some of the tools and practices we’ve adopted the past few days to keep collaboration going.&lt;/p&gt;
&lt;p&gt;Disclaimer: we pay Microsoft for the Office 365 stack, so we’re a bit biased towards / locked-in by those tools, but I’m sure alternatives work fine as well. The important thing is to realize that you can do a lot remotely.&lt;/p&gt;
&lt;h2 id=&quot;work-from-home&quot;&gt;Work from home&lt;/h2&gt;
&lt;p&gt;Of course, many people do not have the luxury of being able to work from home. But we do, and so our organization has gone into full home mode.&lt;/p&gt;
&lt;p&gt;Usually, we divide our time between being at the office and working “on location”. At the office, we exchange knowledge, work together on projects and, of course, socialize. We also work at the location of the project partners, i.e. at the universities or institutes of the domain scientists. There we… basically do the same:) Sometimes we go on conferences, but let’s forget about that for a moment (although… see below).&lt;/p&gt;
&lt;p&gt;Working on projects usually means trying to understand the problem, finding solutions using digital technologies and then implementing them. The first part means: talking to project partners. The second means: thinking, talking to colleagues and, again, talking to project partners. Implementing solutions means: programming; sometimes alone, sometimes together. All of this is often done iteratively, so you cycle through steps 1, 2 and 3 over and over again.&lt;/p&gt;
&lt;p&gt;So, completely working from home is only possible when you have communication channels with low latency and where you can interact with high bandwidth: written words alone often don’t cut it. Video is already a lot better. Of course, there are many solutions available for this and many people were already using these tools a lot, even before we started to fully work from home: Skype, &lt;a href=&quot;https://zoom.us/&quot;&gt;Zoom&lt;/a&gt; (&lt;a href=&quot;https://docs.google.com/document/d/1xdENyIV1505FDXBj7n5PaaHinGGUWc1R0ib1t7DRSCw/edit&quot;&gt;see here for a nice guide&lt;/a&gt;), &lt;a href=&quot;https://whereby.com/&quot;&gt;Whereby&lt;/a&gt;, &lt;a href=&quot;https://www.vidyo.com/&quot;&gt;Vidyo&lt;/a&gt;, &lt;a href=&quot;https://www.gotomeeting.com/nl-nl&quot;&gt;GoToMeeting&lt;/a&gt;, &lt;a href=&quot;https://teams.microsoft.com/&quot;&gt;Teams&lt;/a&gt; and even our neighbors at SURF have their own tool for the Dutch academic community called &lt;a href=&quot;https://videobelpilot.surf.nl/&quot;&gt;Videobellen&lt;/a&gt; which seems to work well and is free for those working at Dutch academic institutions.&lt;/p&gt;
&lt;p&gt;Another thing to keep in mind is of course to prevent repetitive strain injury by making sure you have a well adjusted desk setup or whatever else works for you.&lt;/p&gt;
&lt;h2 id=&quot;pair-programming&quot;&gt;Pair programming&lt;/h2&gt;
&lt;p&gt;I would say that maybe 40–60% of the job is actually programming. A lot of coding can be done alone, but often you do need input and Google and Stack Overflow don’t cut it. At such a time, getting quick feedback can make all the difference. Often this can be done over chat or a video call.&lt;/p&gt;
&lt;p&gt;But pair programming is a different game. Sitting in pairs, working on one computer can really help getting through tough problems. Usually one person types and the other is real-time reviewing everything and reflecting on all choices. This way you avoid many errors, design flaws and other sloppiness, which in the long run can make your programming hours much more efficient.&lt;/p&gt;
&lt;p&gt;So what if you can’t sit together in front of one screen? Sharing your screen could be an option, but there are better ones. Visual Studio Code has a &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare-pack&quot;&gt;Live Share extension&lt;/a&gt; that allows you to work together on each other’s code in each other’s editor. My colleagues have tried this and were very happy with it. It turns out even &lt;a href=&quot;https://github.com/FredKSchott/CoVim&quot;&gt;Vim has a plugin for collaborative editing&lt;/a&gt;! It seems a unmaintained, though, but may still be worth a try.&lt;/p&gt;
&lt;p&gt;Of course, other tools for writing together are already more widespread, like Google Docs and Microsoft Office Online for regular documents, or Overleaf for LaTeX documents.&lt;/p&gt;
&lt;h2 id=&quot;talks--colloquia&quot;&gt;Talks &amp;#x26; colloquia&lt;/h2&gt;
&lt;p&gt;Last week I was already in self imposed isolation, but my colloquium talk was planned. Luckily, our A/V team was already looking into remote colloquia. The solution we ended up with was:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up Microsoft Stream to live stream talks from the office (which by now has become temporarily obsolete, as the office is closed… but still nice to have for later). These are then also automatically stored on Stream after the talk, so really convenient.&lt;/li&gt;
&lt;li&gt;Set up Teams to give talks remotely. Also, these can be recorded and saved to Stream automatically.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It turns out this works fine! I got some feedback after the talk, just as I usually get when I give a colloquium, so content-wise, everything is still the same as it was.&lt;/p&gt;
&lt;p&gt;One thing that did feel a bit weird was that the other side was muted, which meant I got no direct feedback at all. So I had no idea whether my brilliant jokes were properly appreciated, for instance. But more importantly: no idea whether people are still following me at all, which is a bit easier to gauge when you can look at them every now and then (not too often, of course, like most people, I much prefer staring at my slides).&lt;/p&gt;
&lt;p&gt;I think unmuting the room (if you are still connected to a “room”) may be a bit nicer, but your mileage may vary. In any case, since we are now in full home mode, everyone will be on Teams for the next colloquium. In that case, muting non-speakers is quite essential. On the other hand, it will probably be easier to interject for individuals with a question. We’ll have to see how it goes, but based on some other talks we already did this way, I expect it will go very well.&lt;/p&gt;
&lt;h2 id=&quot;standups&quot;&gt;Standups&lt;/h2&gt;
&lt;p&gt;Every Monday, we do a full-team (70-ish people) standup. Everybody gets max 30 seconds to update colleagues on whatever they think is relevant. This is a really nice central moment that really brings out the collaborative nature of the center. People ask for help on tricky issues, announce useful new tools they created or found and share their proud moments or sad ones. For me, it’s one of the best ideas we’ve had and I advise everyone to do this.&lt;/p&gt;
&lt;p&gt;This Monday, we had our first fully remote standup and it worked really nicely via Microsoft Teams! You get the bonus of easy recording and automatic uploading to MS Stream (which we already happened to use, because we always manually recorded our colloquia and other plenary talks). Usually, we did not record these meetings and sometimes important announcements are made there first (and probably later via mail, but there might be some delay). Now, everyone can easily stay up to date by checking at their earliest convenience the standup recording. Nice!&lt;/p&gt;
&lt;p&gt;One slight practicality: when you stand in one physical room, doing the round is easy; you just go round the circle. Online, using Teams, it’s not that much harder. You just go down the participants list. The meeting is a bit quieter. Usually, people in the circle tend to respond a bit more. Now, also all the other mics are muted, so, again, you have no idea whether your horrible puns have hit home. But, I must say that the other way around, i.e. on the listening side, it was totally fine and worked just as well as the regular in-person standup.&lt;/p&gt;
&lt;p&gt;Also, in our smaller project oriented teams (5–8 people) we have started using Teams. Morning stand-ups, review meetings, etc.; so far everything has worked perfectly well!&lt;/p&gt;
&lt;h2 id=&quot;psychological-well-being--coffee-time&quot;&gt;Psychological well being &amp;#x26; coffee time!&lt;/h2&gt;
&lt;p&gt;If you feel you’re getting lonely, just open up a group chat for the heck of it and have a coffee together.&lt;/p&gt;
&lt;p&gt;I’ve seen this idea floating around on Reddit as well. Some people even keep a call open all day long. It gives people the feeling that they’re still a bit at the office with their colleagues. Also, if you find it hard to work in complete isolation and silence and crave some background noise, like the kind you may also find in coffee shops, this can actually be a great solution.&lt;/p&gt;
&lt;p&gt;Some other tips to keep your sanity after days of confinement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Try to not work in the same place you sleep, eat or relax&lt;/li&gt;
&lt;li&gt;Keep a schedule, with a focus on not working overtime&lt;/li&gt;
&lt;li&gt;(This may be silly) Don’t work in your pyjamas&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;chat&quot;&gt;Chat&lt;/h2&gt;
&lt;p&gt;Chat works well for socializing and quick questions which are not mission critical, but that you are having trouble figuring out on your own and would like some help on.&lt;/p&gt;
&lt;p&gt;One important condition imho: you need to make sure to not make chat channels essential. There are many stories doing the rounds warning against “always on” culture. Don’t fall into the trap. If you really need to immediately contact someone, call them. If not, use asynchronous communication (mail, issue trackers) and get on with another task.&lt;/p&gt;
&lt;p&gt;Also, many people do not want the distraction of chat at all. So make sure you separate general coffee corner style banter from official, plenary discussions (if you have those at all… which I wouldn’t recommend, except to support the live video calls).&lt;/p&gt;
&lt;p&gt;At the Center, we’ve been using Slack for a few years now, and it has served us well. Since we’re now starting to use Teams for many other things, we’ve also set up chat there. The word is not yet out on which tool works best for us.&lt;/p&gt;
&lt;h2 id=&quot;remote-conferences-nl-rse-meetup&quot;&gt;Remote conferences: NL-RSE meetup&lt;/h2&gt;
&lt;p&gt;Technically this is not an eScience Center activity, but as part of the bigger NL-RSE movement, some of my colleagues are involved in organizing NL-RSE meetups in Utrecht for the Dutch community of research software engineers (RSEs). Some speakers are invited and lots of opportunity to mingle and network is provided.&lt;/p&gt;
&lt;p&gt;Unfortunately, &lt;a href=&quot;https://nl-rse.org/events/2020-03-13-meetup.html&quot;&gt;this time — Friday the 13th&lt;/a&gt; — my colleagues didn’t want to tempt fate and &lt;a href=&quot;https://twitter.com/matkuzak/status/1237735075669848064&quot;&gt;made the wise decision to cancel the in-person event… only to replace it with a fully remote event&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/c2754835142?source=post_page---user_mention--28db59f86766---------------------------------------&quot;&gt;Mateusz Kuzak&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;arranged for the meeting to be held via Zoom. This went very well! &lt;a href=&quot;https://tinyurl.com/2020-03-13-nl-rse&quot;&gt;Minutes can be found here&lt;/a&gt; for those interested. 20+ people attended and had very constructive and interesting sessions, both with three speakers and with a collaborative session that will result in an article on the &lt;a href=&quot;https://lab.kb.nl/about-us/blog&quot;&gt;KB Lab (Royal Dutch Library) blog&lt;/a&gt; here very soon.&lt;/p&gt;
&lt;h3 id=&quot;digital-office-hours&quot;&gt;Digital office hours&lt;/h3&gt;
&lt;p&gt;One additional detail that I really liked was that &lt;a href=&quot;https://twitter.com/matkuzak&quot;&gt;Mateusz&lt;/a&gt; held a digital office hour via Zoom one day in advance of the meetup to help everybody get properly set up.&lt;/p&gt;
&lt;p&gt;This may also be useful in other situations, like when your students want to ask you questions, but you don’t want to be interrupted at every minute of the day. With digital office hours, you can help your students and still have guilt-free deep focused hours of work in the other hours of the day.&lt;/p&gt;
&lt;h3 id=&quot;networking&quot;&gt;Networking&lt;/h3&gt;
&lt;p&gt;One downside of doing online conferences so far is that networking becomes a lot harder when you can’t mingle easily over coffee. One of my colleagues&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/ee774bf64a6b?source=post_page---user_mention--28db59f86766---------------------------------------&quot;&gt;Fakhereh (Sarah) Alidoost&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;experienced this at the &lt;a href=&quot;https://www.eucp-project.eu/&quot;&gt;EUCP&lt;/a&gt; general assembly, which she attended remotely. The rest of the conference was really high quality, though. The meeting layout, sound and video quality using Zoom were very good. Also, Zoom has a “Raise Hand” option, which is very useful.&lt;/p&gt;
&lt;h2 id=&quot;more-inspiration&quot;&gt;More inspiration&lt;/h2&gt;
&lt;p&gt;Many people and companies have already long been experimenting with remote working. For instance, GitLab published the &lt;a href=&quot;https://about.gitlab.com/blog/2015/04/08/the-remote-manifesto/&quot;&gt;Remote Manifesto&lt;/a&gt; with some great general guidelines for making remote working work.&lt;/p&gt;
&lt;p&gt;A few days ago I came across this &lt;a href=&quot;https://www.thegreatcodeadventure.com/my-long-distance-relationship-with-github/&quot;&gt;really, really insightful article about someone working (remotely) at GitHub and the non-obvious challenges she faced transitioning from co-located to remote working&lt;/a&gt;. Turns out it’s about more than just doing video calls. Asynchronous is the keyword. Using issue trackers and other online tools for communication are vital. Indeed, we have long been using these as well, but maybe we still have things to learn about using them even more effectively.&lt;/p&gt;
&lt;p&gt;Further useful resources compiled by&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.com/u/c2754835142?source=post_page---user_mention--28db59f86766---------------------------------------&quot;&gt;Mateusz Kuzak&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://hackmd.io/cFL-4VosSfq3RpvCfVpxEQ&quot;&gt;A Lesson to Demonstrate a Few Techniques for Online Meetings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1MdmrNn5g2oa2AA6EGYZhyDx-O_YOoH_HqNGsmP6LKIo/edit?usp=sharing&quot;&gt;Tips for Teaching and Learning Online by The Carpentries Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/abbycabs/status/1237001927734542341?s=21&quot;&gt;Abby’s online meeting tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://foundation.mozilla.org/en/blog/online-meeting-tips/&quot;&gt;Mozilla online meeting tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://about.gitlab.com/company/culture/all-remote/&quot;&gt;Gitlab Guide to all remote&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1EABkSzEdJk5cmMLETpSbXaeDXmFwcTz7SUXP_C3dN9k/edit?usp=drivesdk&quot;&gt;How To Run A Free Online Academic Conference: A Workbook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have any further tips or resources, please let me know in the comments or on &lt;a href=&quot;https://twitter.com/eScienceCenter/status/1240253016122458113&quot;&gt;Twitter&lt;/a&gt;! Of course, many tips are out there already. There’s even &lt;a href=&quot;https://www.reddit.com/r/remotework/&quot;&gt;a subreddit dedicated to remote working&lt;/a&gt; that’s surely going to blow up the coming weeks.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_ZUCKx3r5NhRcr-sFwMhTBQ-75fd2b47.DkreyW7G.jpeg" medium="image"/><author>Patrick Bos</author></item><item><title>The Research Software Alliance (ReSA) and the Community Landscape</title><link>https://blog2.esciencecenter.nl/posts/2020-03-12---the-research-software-alliance-resa-and-the-community-landsc</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-03-12---the-research-software-alliance-resa-and-the-community-landsc</guid><description>&lt;p&gt;][eScience Editorial Team]·Mar 11, 2020**Subscribe*&lt;/p&gt;
&lt;p&gt;Some of the issues we’ve had in assembling this list are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How much interest in software does an organization need to have to be listed?&lt;/li&gt;
&lt;li&gt;When is an organization sufficiently research focused to be included?&lt;/li&gt;
&lt;li&gt;What momentum/scale does an organization need to have so that we consider it relevant in the global picture?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the other hand, once we started adding entries to the list, for many we found that we immediately thought of other similar organizations that should be added. For example, some organizations have a geographic aspect, and this led us to think of other similar organizations with different geographic aspects, such as all the national and regional RSE associations.&lt;/p&gt;
&lt;p&gt;What did we learn?**&lt;/p&gt;
&lt;p&gt;There were a range of interesting outcomes of the analysis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are many, many communities that support research software, emphasizing the need for a coordinating organization such as ReSA. The importance of community development is captured in articles such as &lt;a href=&quot;https://arxiv.org/abs/1811.08473&quot;&gt;Community Organizations: Changing the Culture in Which Research Software is Developed and Sustained&lt;/a&gt; by Daniel S. Katz et al., which provides an overview of key groups and discusses opportunities to leverage their synergistic activities.&lt;/li&gt;
&lt;li&gt;There is an increasing (and wide) range of community initiatives. For example, the &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1geYQLpJQtzPbhN3UZGSqPGFKNIF-hqXd7PGrwZJzasA/edit#gid=0&quot;&gt;Open Science Grassroots Community Networks&lt;/a&gt; list has evolved into the Community of Open Scholarship Grassroots Networks (COSGN), whose networks communicate and coordinate on topics of common interest. COSGN has submitted an &lt;a href=&quot;https://osf.io/preprints/metaarxiv/d7mwk&quot;&gt;NSF proposal&lt;/a&gt; to formalize governance and coordination of the networks to maximize impact and establish standard practices for sustainability.&lt;/li&gt;
&lt;li&gt;The increasing focus on open software makes it hard to separate research and non-research initiatives. As per the points above, it is very hard to define which initiatives are part of the research software community and which are not.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some organizations that were originally data-centric now include a software focus. For example, the Research Data Alliance now includes the &lt;a href=&quot;https://www.rd-alliance.org/groups/software-source-code-ig&quot;&gt;Software Source Code Interest Group&lt;/a&gt;, which provides a forum to discuss issues on management, sharing, discovery, archiving, and provenance of software source code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are the next steps?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We invite readers to continue to add or make corrections to the ReSA list of &lt;a href=&quot;https://docs.google.com/spreadsheets/d/15JHqOxR4HIKHYe821IPvbxIuXP1zMjXKGEIJwB-GPqE/edit#gid=0&quot;&gt;research software communities&lt;/a&gt;by making comments in the list, which will continue to be curated by ReSA. We are also interested to hear from community members who would like to engage with us in writing a landscape paper based on further analysis and work. This could address questions such as what are the axes that create the space, where do the currently-known organizations fit in the space, and are there gaps where no organization is currently working? We also invite readers to consider involvement in other ReSA activities, including &lt;a href=&quot;http://www.researchsoft.org/resa-taskforces-join-us/&quot;&gt;Taskforces&lt;/a&gt;.).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The ever-growing number of constituents of the research software community both reflect and demonstrate the increasing recognition of research software. The research software community is now a complex ecosystem comprised of a wide variety of organizations and initiatives, some of which are community networks themselves. Collaboration and coordination across these initiatives is important, to enable the broader community to work together to achieve bigger goals.&lt;/p&gt;
&lt;p&gt;ReSA aims to coordinate across these efforts to leverage investments, to achieve the shared long-term goal of research software valued as a fundamental and vital component of research worldwide. Join the &lt;a href=&quot;https://groups.google.com/forum/#!forum/research-software-alliance&quot;&gt;ReSA google group&lt;/a&gt; to stay up-to-date on our activities.&lt;/p&gt;
&lt;p&gt;Authors: Daniel S. Katz, Michelle Barker, Paula Andrea Martinez, Hartwig Anzt, Alejandra Gonzalez-Beltran and Tom Bakker.*&lt;/p&gt;</description><pubDate>Thu, 12 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;][eScience Editorial Team]·Mar 11, 2020**Subscribe*&lt;/p&gt;
&lt;p&gt;Some of the issues we’ve had in assembling this list are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How much interest in software does an organization need to have to be listed?&lt;/li&gt;
&lt;li&gt;When is an organization sufficiently research focused to be included?&lt;/li&gt;
&lt;li&gt;What momentum/scale does an organization need to have so that we consider it relevant in the global picture?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the other hand, once we started adding entries to the list, for many we found that we immediately thought of other similar organizations that should be added. For example, some organizations have a geographic aspect, and this led us to think of other similar organizations with different geographic aspects, such as all the national and regional RSE associations.&lt;/p&gt;
&lt;p&gt;What did we learn?**&lt;/p&gt;
&lt;p&gt;There were a range of interesting outcomes of the analysis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are many, many communities that support research software, emphasizing the need for a coordinating organization such as ReSA. The importance of community development is captured in articles such as &lt;a href=&quot;https://arxiv.org/abs/1811.08473&quot;&gt;Community Organizations: Changing the Culture in Which Research Software is Developed and Sustained&lt;/a&gt; by Daniel S. Katz et al., which provides an overview of key groups and discusses opportunities to leverage their synergistic activities.&lt;/li&gt;
&lt;li&gt;There is an increasing (and wide) range of community initiatives. For example, the &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1geYQLpJQtzPbhN3UZGSqPGFKNIF-hqXd7PGrwZJzasA/edit#gid=0&quot;&gt;Open Science Grassroots Community Networks&lt;/a&gt; list has evolved into the Community of Open Scholarship Grassroots Networks (COSGN), whose networks communicate and coordinate on topics of common interest. COSGN has submitted an &lt;a href=&quot;https://osf.io/preprints/metaarxiv/d7mwk&quot;&gt;NSF proposal&lt;/a&gt; to formalize governance and coordination of the networks to maximize impact and establish standard practices for sustainability.&lt;/li&gt;
&lt;li&gt;The increasing focus on open software makes it hard to separate research and non-research initiatives. As per the points above, it is very hard to define which initiatives are part of the research software community and which are not.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some organizations that were originally data-centric now include a software focus. For example, the Research Data Alliance now includes the &lt;a href=&quot;https://www.rd-alliance.org/groups/software-source-code-ig&quot;&gt;Software Source Code Interest Group&lt;/a&gt;, which provides a forum to discuss issues on management, sharing, discovery, archiving, and provenance of software source code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What are the next steps?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We invite readers to continue to add or make corrections to the ReSA list of &lt;a href=&quot;https://docs.google.com/spreadsheets/d/15JHqOxR4HIKHYe821IPvbxIuXP1zMjXKGEIJwB-GPqE/edit#gid=0&quot;&gt;research software communities&lt;/a&gt;by making comments in the list, which will continue to be curated by ReSA. We are also interested to hear from community members who would like to engage with us in writing a landscape paper based on further analysis and work. This could address questions such as what are the axes that create the space, where do the currently-known organizations fit in the space, and are there gaps where no organization is currently working? We also invite readers to consider involvement in other ReSA activities, including &lt;a href=&quot;http://www.researchsoft.org/resa-taskforces-join-us/&quot;&gt;Taskforces&lt;/a&gt;.).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The ever-growing number of constituents of the research software community both reflect and demonstrate the increasing recognition of research software. The research software community is now a complex ecosystem comprised of a wide variety of organizations and initiatives, some of which are community networks themselves. Collaboration and coordination across these initiatives is important, to enable the broader community to work together to achieve bigger goals.&lt;/p&gt;
&lt;p&gt;ReSA aims to coordinate across these efforts to leverage investments, to achieve the shared long-term goal of research software valued as a fundamental and vital component of research worldwide. Join the &lt;a href=&quot;https://groups.google.com/forum/#!forum/research-software-alliance&quot;&gt;ReSA google group&lt;/a&gt; to stay up-to-date on our activities.&lt;/p&gt;
&lt;p&gt;Authors: Daniel S. Katz, Michelle Barker, Paula Andrea Martinez, Hartwig Anzt, Alejandra Gonzalez-Beltran and Tom Bakker.*&lt;/p&gt;</content:encoded><author>eScience Editorial Team</author></item><item><title>Combining ZeroMQ &amp; POSIX signals</title><link>https://blog2.esciencecenter.nl/posts/2020-02-12---combining-zeromq-posix-signals</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-02-12---combining-zeromq-posix-signals</guid><description>&lt;h2 id=&quot;use-ppoll-to-handle-eintr-once-and-for-all&quot;&gt;Use ppoll to handle EINTR once and for all&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_9673x3EO1AadXhPS-8582ce0f.BV_1Ju2O_2eA7ip.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What my first experience trying to send out signals was like. Can anybody hear me? Photo by Jason Rosewell on Unsplash&lt;/p&gt;
&lt;p&gt;I have been dabbling in using and mixing these two well known interprocess communication techniques for a few months now. Dabbling may not be the right word. More like desperately trying to find my way out of a dark room without a flash light.&lt;/p&gt;
&lt;p&gt;Speaking of which, if you’re ever in &lt;a href=&quot;https://en.wikipedia.org/wiki/Nijmegen&quot;&gt;Nijmegen&lt;/a&gt;, be sure to visit the &lt;a href=&quot;https://muzieum.nl/&quot;&gt;muZIEum&lt;/a&gt; and experience what it’s like to be blind. In their basement, they recreated everyday scenes and then made it completely, absolutely dark. It’s really a magnificent experience.&lt;/p&gt;
&lt;p&gt;Anyway, once you’ve done that, you’ll know how I have been feeling lately trying to get ZeroMQ to play nice with POSIX signals… I hope that after reading this, you won’t have to feel the same way, if you don’t want to (if you do, visit Nijmegen, or stop reading now).&lt;/p&gt;
&lt;p&gt;Specifically, I present here some &lt;strong&gt;pitfalls and problems&lt;/strong&gt; of using &lt;strong&gt;ZeroMQ&lt;/strong&gt; calls &lt;code&gt;send&lt;/code&gt;, &lt;code&gt;receive&lt;/code&gt; and &lt;code&gt;poll&lt;/code&gt;, which are blocking calls (they pause the program until they get what they were waiting for), in &lt;strong&gt;combination&lt;/strong&gt; with &lt;strong&gt;POSIX&lt;/strong&gt; signals that interrupt these calls. In my case, initially, these calls were external, but eventually, I also wanted to actively trigger them myself. Both situations require different approaches.&lt;/p&gt;
&lt;p&gt;Luckily, there is a &lt;strong&gt;solution to the problems&lt;/strong&gt;, which I’ll also come to at the end of this article after a long winded description of the process of me wrapping my head around all of this. Long story short: I implemented a &lt;code&gt;ppoll&lt;/code&gt; ZeroMQ call (yes, with double p).&lt;/p&gt;
&lt;p&gt;But let’s first set the scene before diving into details.&lt;/p&gt;
&lt;h2 id=&quot;backstory&quot;&gt;Backstory&lt;/h2&gt;
&lt;p&gt;Our story takes place in the &lt;a href=&quot;https://root.cern/&quot;&gt;ROOT C++ data analysis framework&lt;/a&gt; for particle physics experiments, specifically in the RooFit package. (For the short, technical essentials of the following chronicle, skip down to the next header Technical overview.)&lt;/p&gt;
&lt;p&gt;I’m building a system to run RooFit calculations in parallel on multiple processes. To do that, I need interprocess communication. For this, I chose ZeroMQ, because of its &lt;a href=&quot;http://zguide.zeromq.org/page:all&quot;&gt;really funny manual&lt;/a&gt; (and because other people seemed to like it, particularly Roel Aaij, who helped me get started with it).&lt;/p&gt;
&lt;p&gt;At this point, you may wonder why we didn’t use an existing task execution framework like &lt;a href=&quot;https://en.wikipedia.org/wiki/Threading_Building_Blocks&quot;&gt;TBB&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Cilk&quot;&gt;Cilk&lt;/a&gt;, but we had some specific design constaints that made this impossible (integration with the current RooFit C++ code and performance requirements), so we had to whip up our own thing.&lt;/p&gt;
&lt;p&gt;Everything was coming along nicely. With lots of valuable input from the team, Inti Pelupessy and I designed and built the MultiProcess system, it was working just fine, we benchmarked it, presented it and published a bit and things seemed to be hunky-dory. Matter of packing it up and shipping it. Or so we thought.&lt;/p&gt;
&lt;p&gt;The first version had some, let’s say, &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaghetti_code&quot;&gt;sub-optimal implementation choices&lt;/a&gt; (which I take full responsibility for). Also, in our final version, we wanted to make a few user-facing design changes. So we got together, made a better design and I started coding version two.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;484&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_h49Fzwhw4IyLttce-96e6ecef.BrHBnW_b_ZnKtpU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The redesign team at CERN past summer. So young. So naive (speaking for myself at least).&lt;/p&gt;
&lt;p&gt;To make the MultiProcess framework more maintainable, I split it into several conceptual classes. Most importantly, the so-called &lt;code&gt;TaskManager&lt;/code&gt; was taken apart. The &lt;code&gt;TaskManager&lt;/code&gt; did hardly anything to manage tasks. Instead it managed a task queue, interprocess communication and forking into multiple processes, i.e. everything needed behind the scenes to get workers (processes) to calculate their parts of the total calculation and then send the results back to the master process. Workers don’t need management, they just need someone to take all the red tape away from them so they can focus on what they do best! There is no political message here!&lt;/p&gt;
&lt;p&gt;So, now we have a &lt;code&gt;JobManager&lt;/code&gt; which keeps a list of &lt;code&gt;Job&lt;/code&gt; s, and explicitly spawns objects for the other previously bunched together tasks of the &lt;code&gt;TaskManager&lt;/code&gt; (are you confused yet?): a &lt;code&gt;Queue&lt;/code&gt;, a &lt;code&gt;Messenger&lt;/code&gt; and a &lt;code&gt;ProcessManager&lt;/code&gt;. The queue also runs an event loop on the queue process (which the master process talks to) and the worker processes (which talk to the queue as well) run a &lt;code&gt;worker_loop&lt;/code&gt; which is just a free function, yay C++, free the functions from their classist masters! Still no politics, I assure you.&lt;/p&gt;
&lt;p&gt;Now, one of the nice things of having monolithic classes is that you don’t have to worry too much about, say, separating your concerns. This means for instance that the old &lt;code&gt;TaskManager&lt;/code&gt; could use its messaging parts to tell its process management parts to shut down children after the Job was done.&lt;/p&gt;
&lt;p&gt;In the new situation, the &lt;code&gt;JobManager&lt;/code&gt; instantiates its &lt;code&gt;ProcessManager&lt;/code&gt; member to spawn child processes and after that instantiates its &lt;code&gt;Messenger&lt;/code&gt; member to setup our means of communication. In C++ it would be most natural to let the destructor of these classes clean up all connections and processes. However, when we do this after our Job is done, we can no longer use the &lt;code&gt;Messenger&lt;/code&gt; to communicate between processes, because there is a recursive dependency. We would need the &lt;code&gt;Messenger&lt;/code&gt; to tell the &lt;code&gt;ProcessManager&lt;/code&gt; to terminate the processes, but the processes cannot die before they killed the &lt;code&gt;Messenger&lt;/code&gt;, because through ZeroMQ it keeps alive an I/O thread that waits for messages from the ZeroMQ sockets that we haven’t killed yet because we needed them to kill the processes!&lt;/p&gt;
&lt;p&gt;In principle, you can do it by sending a terminate signal over the messenger, which triggers the destruction of the &lt;code&gt;JobManager&lt;/code&gt;, which then destroys all its component members. This has its own issues, not the least of which is that it creates an external dependency for destruction, which seems like a bad design choice.&lt;/p&gt;
&lt;p&gt;To get out of this swamp, there are several other possibilities, like making the messenger a singleton class like the &lt;code&gt;JobManager&lt;/code&gt; or the ZeroMQ context (yeah, now the skeletons come popping out of the closet), but I just couldn’t bear making yet another one of those.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;958&quot; height=&quot;487&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wNTLScaDrD53gnLf-f331d8a7.DYdSrnaR_Z6R5ey.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Honestly, my closet isn’t big enough to hold all the skeletons…&lt;/p&gt;
&lt;p&gt;In any case, I thought it would be nice to make the classes independent (even though the &lt;code&gt;Messenger&lt;/code&gt; still needs the &lt;code&gt;ProcessManager&lt;/code&gt; instance at creation time to tell it which process it is running on, but this can easily be passed on via the constructor, a feat which destructors unfortunately cannot perform).&lt;/p&gt;
&lt;p&gt;To this end, I decided to have the &lt;code&gt;ProcessManager&lt;/code&gt; just use POSIX signals to signal all its kids to die.&lt;/p&gt;
&lt;h2 id=&quot;technical-overview&quot;&gt;Technical overview&lt;/h2&gt;
&lt;p&gt;So, long story short: I have a master process, which spawns 1 + N children:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a queue process, running a loop to wait for messages and then act on them;&lt;/li&gt;
&lt;li&gt;N worker processes, also running a messaging loop.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;ProcessManager&lt;/code&gt; takes care of forking child processes in the constructor and killing them off by sending POSIX signals from the destructor.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Messenger&lt;/code&gt; sends around job descriptions and results from the master to the queue and from queue to workers. It uses ZeroMQ sockets for this. At the end of its life, it just shuts down all sockets, closes the ZeroMQ context and that’s that.&lt;/p&gt;
&lt;p&gt;Note that these instances are cloned to all forked children, but on each child there is only one instance, owned by the singleton &lt;code&gt;JobManager&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;All good so far.&lt;/p&gt;
&lt;p&gt;Now, the issue is this: since we can no longer use our messenger to send a termination message, the loop will run indefinitely. This is why we use the &lt;code&gt;SIGTERM&lt;/code&gt; signal to stop the process. To do this, we must install a signal handler using the POSIX &lt;code&gt;signal&lt;/code&gt; call. We use the signal handler to flip some globally accessible flag variable, which we check for in the message loops and exit the loops once it’s flipped.&lt;/p&gt;
&lt;p&gt;Again, seems simple enough.&lt;/p&gt;
&lt;p&gt;Unfortunately, it caused me a week or two of headaches.&lt;/p&gt;
&lt;h2 id=&quot;first-try-tying-knots&quot;&gt;First try: tying knots&lt;/h2&gt;
&lt;p&gt;The complication arises because ZeroMQ operations &lt;code&gt;send&lt;/code&gt;, &lt;code&gt;recv&lt;/code&gt; and &lt;code&gt;poll&lt;/code&gt;, which we use to wait for messages in the loops, are blocking functions that only exit when they have some data incoming or outgoing &lt;strong&gt;or&lt;/strong&gt; when they encounter some error, like &lt;strong&gt;a POSIX signal interrupting them&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When such an interrupt happens, the operation exits with an &lt;code&gt;EINTR&lt;/code&gt; exit code, which you can (and should!) check for. The thing is that it can happen for all kinds of signals and some may be harmless. For instance, profilers also use signals to measure a program’s time spent in certain functions. For those you may want the &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt; to just retry. Also, on other errors, you may want to just raise an exception and get the hell out of there, back to where the &lt;code&gt;recv&lt;/code&gt; was called from.&lt;/p&gt;
&lt;p&gt;In any case, when we get a POSIX signal while inside &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt;, first the signal handler will flip our flag switch, then, back inside the blocking &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt;, the &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt; will return with an &lt;code&gt;EINTR&lt;/code&gt; exit code. We check the exit code and the flag switch and either start shutting down when we received our kill signal or continue when we didn’t:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;while (true) {                  // send&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;recv&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;poll retry loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  try {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    int timeout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;           &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; infinite&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;no timeout, i.e. block&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    socket&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;recv(timeout);       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or send, or poll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  } except (zmq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error_t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;e) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    if (e&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;num&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; EINTR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      throw;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      if (my_global_flag_is_switched) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exit(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);           &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or some fancier way &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exiting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; toe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; down&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the stairs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will often go well. It also often goes wrong, as my tests were showing. About half of the time one of the terminated children would hang…!@*$%&amp;#x26;&lt;/p&gt;
&lt;p&gt;The problem here is that the &lt;code&gt;SIGTERM&lt;/code&gt; signal is not guaranteed to be received inside the blocking ZeroMQ call. In fact, it will often be received when in some other function, because it may still be busy handling a previous message. When this happens, the flag will be flipped, but it is not checked! At some point the message loop returns to the &lt;code&gt;recv&lt;/code&gt; call and will just block there.&lt;/p&gt;
&lt;p&gt;An obvious looking solution to this specific problem is to put another switch-check in front of the &lt;code&gt;recv&lt;/code&gt;, i.e.:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (my_global_flag_is_switched) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exit(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);             &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or some fancier way &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exiting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hello darkness, my old friend  socket&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;recv(timeout);       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or send, or poll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this will certainly reduce the odds of going into a blocking call when &lt;code&gt;SIGTERM&lt;/code&gt; has been received, it still doesn’t guarantee anything. There is still soom innocent looking room in between the check and the blocking call. The signal could still be received just before the &lt;code&gt;recv&lt;/code&gt; call has been entered. Or, maybe more precisely, before one of the actually blocking system calls inside &lt;code&gt;recv&lt;/code&gt; has been entered; but also the process could simply have been put on hold by the OS exactly at the moment after the flag check. In any case, this setup will still hang indefinitely every now and then.&lt;/p&gt;
&lt;p&gt;So this way of interleaving POSIX and ZeroMQ calls and checks will never be enough, there will always be a possibility that your blocking call will hang.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;1213&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_kpJXLkNFcTnvN0Om-fc5127c6.ChUf-9Qp_Z13yUWa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Haaaaaaaaaang. Haaaaaaaaaaaaang.&lt;/p&gt;
&lt;h2 id=&quot;second-try-queue-it-all&quot;&gt;Second try: queue it all&lt;/h2&gt;
&lt;p&gt;I was Googling for alternative solutions and honestly found it really hard to find good resources on this (which is the main reason I’m now writing it all down for you in this article).&lt;/p&gt;
&lt;p&gt;Eventually, I found &lt;a href=&quot;http://250bpm.com/blog:12&quot;&gt;this article on EINTR in ZeroMQ&lt;/a&gt; by Martin Sustrik (ZeroMQ creator) himself. More precisely, in the comment section &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1608507&quot;&gt;Ambroz Bizjak suggested a solution&lt;/a&gt; to my problem which after some discussion even Sustrik seemed to be unaware of. The solution wasn’t completely fleshed out in the comments, so there was still some filling out for me to do. Luckily for you, you won’t have to repeat this exercise.&lt;/p&gt;
&lt;p&gt;The solution is that when going into the blocking ZeroMQ calls, you temporarily block the POSIX signals you want to listen for; &lt;code&gt;SIGTERM&lt;/code&gt; in our case. This can be done using &lt;code&gt;sigprocmask&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, instead of using your regular blocking ZeroMQ call, you use &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; to wait for something to happen on your sockets &lt;strong&gt;and your signal queue.&lt;/strong&gt; Because, as it turns out, when you temporarily block signals using &lt;code&gt;sigprocmask&lt;/code&gt;, they are put in a queue by the OS. You can then handle them at your earliest convenience.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; functions can monitor lists of sockets &lt;strong&gt;and&lt;/strong&gt; you can give them a &lt;strong&gt;signal mask&lt;/strong&gt; like the one you gave &lt;code&gt;sigprocmask&lt;/code&gt;, but then without the signal that you specifically wanted to block outside of the &lt;code&gt;pselect&lt;/code&gt; / &lt;code&gt;ppoll&lt;/code&gt; call. This will make &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; listen to those signals that you blocked earlier. When a signal came in (or a socket is ready for reading/writing) they will return. If you put the flag check after &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;, the signal will always be handled properly.&lt;/p&gt;
&lt;p&gt;One other critical modification is that in this case you should no longer use blocking ZeroMQ calls. This has also become unnecessary, because you already checked whether some data is incoming on the socket using &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Finally, note that also right after you blocked the signal with &lt;code&gt;sigprocmask&lt;/code&gt;, you should put one additional check for the signal flag, because the signal may yet have triggered somewhere just before you blocked it.&lt;/p&gt;
&lt;p&gt;All in all, the code would then become something like that of Ambroz Bizjak:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;set file descriptor to non&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blocking;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sigprocmask&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to block &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (stop) { // handle it }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;while (true) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  pselect&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with sigmask argument which doesn&apos;t block &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (stop) { // handle it }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  recv&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sigprocmask(old) to put back the old mask &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; use before we replaced it;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;integrating-into-zeromq&quot;&gt;Integrating into ZeroMQ&lt;/h2&gt;
&lt;p&gt;This is great in theory, but as already mentioned in the reply by Sustrik: this means we would need a &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; in ZeroMQ. I was originally using &lt;code&gt;zmq::poll&lt;/code&gt;, which internally uses regular POSIX &lt;code&gt;poll&lt;/code&gt;. We can in principle modify this fairly easily to take the additional argument necessary for &lt;code&gt;ppoll&lt;/code&gt;, namely the signal mask.&lt;/p&gt;
&lt;p&gt;However, then we need to decide on how to handle this internally in ZMQ. I cannot do this on my own, but decided to write a first implementation anyway. However, when I started thinking about actually doing this, a few new problems raised their ugly heads.&lt;/p&gt;
&lt;p&gt;The first idea I had was to again use a global flag that can be flipped from the signal handler when a signal is received… At this point I finally realized what Sustrik was talking about when he said we can’t use signal handlers in libraries. First of all: we don’t know which signals the user will want to actually mask. Maybe they want to act on several signals and so will need several global flags. So, long story short: this cannot be done generically inside a &lt;code&gt;zmq::ppoll&lt;/code&gt; or &lt;code&gt;zmq::pselect&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So then we only have two possible tools left to let the user know we caught a signal: the return value and the error code.&lt;/p&gt;
&lt;p&gt;The return value is constrained; the API should conform to existing APIs like those of POSIX &lt;code&gt;ppoll&lt;/code&gt; and &lt;code&gt;zmq::poll&lt;/code&gt;. We can only use return values of &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;, where &lt;code&gt;-1&lt;/code&gt; means an error occurred. So probably the only sensible option is to modify &lt;code&gt;zmq_poll&lt;/code&gt; (now I’m talking about the libzmq implementation; &lt;code&gt;zmq::poll&lt;/code&gt; is merely a C++ wrapper around &lt;code&gt;zmq_poll&lt;/code&gt;) to return &lt;code&gt;-1&lt;/code&gt; and set the &lt;code&gt;errno&lt;/code&gt; to &lt;code&gt;EINTR&lt;/code&gt; when the signal is received.&lt;/p&gt;
&lt;p&gt;So this sounds a bit like we’d be back at square one… Except that this time the &lt;code&gt;ppoll&lt;/code&gt; function would be &lt;strong&gt;the only place where the signal is unblocked&lt;/strong&gt;, so we know exactly where it will occur and, more importantly, where it will not. Problem solved!&lt;/p&gt;
&lt;p&gt;Now I just had to write it…&lt;/p&gt;
&lt;h2 id=&quot;ppoll-pselect-or-self-pipe&quot;&gt;Ppoll, pselect or self-pipe?&lt;/h2&gt;
&lt;p&gt;After a two week hiatus, I came back, tried to implement &lt;code&gt;zmq_ppoll&lt;/code&gt; by simply copy-pasting &lt;code&gt;zmq_poll&lt;/code&gt; and replacing &lt;code&gt;poll&lt;/code&gt; with &lt;code&gt;ppoll&lt;/code&gt;, but was unpleasantly surprised by the fact that &lt;code&gt;ppoll&lt;/code&gt; apparently doesn’t exist on macOS. &lt;code&gt;[pselect](&amp;#x3C;https://stackoverflow.com/a/46047380/1199693&gt;)&lt;/code&gt; does exist, so we’ll have to go with that.&lt;/p&gt;
&lt;p&gt;Luckily, the &lt;code&gt;zmq_poll&lt;/code&gt; implementation is really flexible, and already includes a &lt;code&gt;select&lt;/code&gt; -based path next to the &lt;code&gt;poll&lt;/code&gt; -based one. We modify that to take a &lt;code&gt;sigmask&lt;/code&gt; and Bob’s your uncle.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_AnAinknYq39MUSLc-37df9805.2E-MjPnF_Z1yMCU8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’m your uncle! &lt;a href=&quot;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&quot;&gt;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So indeed, let’s try out &lt;code&gt;pselect&lt;/code&gt;. I did have some reservations, because the web is rather full of reports of it not being implemented properly on macOS / FreeBSD… see &lt;a href=&quot;https://stackoverflow.com/questions/14045801/different-pselect-behaviour-on-osx-vs-linux&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=12857275&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=16321529&quot;&gt;here&lt;/a&gt;… Hopefully, as also reported &lt;a href=&quot;https://news.ycombinator.com/item?id=12904883&quot;&gt;here&lt;/a&gt;, in recent versions this is fixed. It seems like they could have taken inspiration by now from many existing, reportedly correct, implementations, like &lt;a href=&quot;http://lua-users.org/lists/lua-l/2015-01/msg00697.html&quot;&gt;this one&lt;/a&gt;. This does mean our implementation will only be really 100% robust on recent macOS versions, but so be it.&lt;/p&gt;
&lt;p&gt;At this point, under all these doubts about the stability of it all, I almost gave up on &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; to try out the so-called ” &lt;a href=&quot;http://cr.yp.to/docs/selfpipe.html&quot;&gt;self-pipe trick&lt;/a&gt; ” that is also &lt;a href=&quot;https://lwn.net/Articles/176911/&quot;&gt;floating around&lt;/a&gt; in these discussions. This could be a good alternative in some ways.&lt;/p&gt;
&lt;p&gt;The problem with the self-pipe trick is that you can’t fully implement it in all its gory details in a library. The trick involves sending a byte over a pipe &lt;em&gt;from a signal handler&lt;/em&gt;. As &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1654888&quot;&gt;Sustrik mentions&lt;/a&gt;, we cannot rely on signal handlers at all. We have to assume they can be overridden by users of our libraries. In fact, ROOT might install its own signal handlers, indeed invalidating the entire approach we’d be going for here. Though, in fact, the last signal handler that is set is the one that trumps others. When we only set the &lt;code&gt;SIGTERM&lt;/code&gt; handler when doing all this stuff and then set the handler back to its original value afterwards, we should be safe, except that we might be interfering with other signal handlers, but that will be necessary in most cases anyway, because also the &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; route will at some point need to install a signal handler. The cleaner alternative (when setting signal handlers are really out of the question) is to let the user of your library implement their own self-pipe signal handler. In my opinion, this is way too heavy a burden on the user.&lt;/p&gt;
&lt;p&gt;So in the end, I chose to go with &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt;, because it puts most of the code on the library side and avoids having to setup and maintain an extra pipe. The only thing you need with the &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; option is a simple signal handler and a flag to check. It seems like a simpler and more user-friendly option.&lt;/p&gt;
&lt;p&gt;Whatever you choose, some handling of POSIX signals will be necessary in a robust multi-process application. For instance, if a child process dies for some reason, a &lt;code&gt;SIGCHLD&lt;/code&gt; signal is sent to the parent, which could also interrupt blocking reads, sends and polls (if &lt;code&gt;SIG_IGN&lt;/code&gt; is not set for this signal). These must be handled either by using &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; or by using the self-pipe trick.&lt;/p&gt;
&lt;h2 id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;
&lt;p&gt;So, I implemented the &lt;code&gt;zmq::ppoll&lt;/code&gt; via &lt;code&gt;pselect&lt;/code&gt; route. And finally, after a lot of debugging, it seems to be working well!&lt;/p&gt;
&lt;p&gt;Its low level implementation (&lt;code&gt;zmq_ppoll&lt;/code&gt;) depends on many libzmq macros, defines and functions. Trying to build against this creates a giant string of dependency files. The problem with this is that libzmq does not expose all these internal headers, so for the time being I just copy pasted over all the necessary libzmq files. Amazingly, this just seems to work after a few tweaks. My compliments to the libzmq devs for creating such modular code!&lt;/p&gt;
&lt;p&gt;Regarding the few tweaks: there are a lot of precompiler variables which are used to configure the compiled libzmq code. It seems that for macOS, this configuration is perfectly comfortable basing &lt;code&gt;zmq_poll&lt;/code&gt; on &lt;code&gt;poll&lt;/code&gt;. This makes sense, but for our purposes it is really annoying, because we need all the stuff that would be compiled in the case &lt;code&gt;zmq_poll&lt;/code&gt; would be based on &lt;code&gt;select&lt;/code&gt;. A lot of necessary classes and typedefs are therefore not at all fed to the compiler from all the lazily copy-pasted headers and source files.&lt;/p&gt;
&lt;p&gt;This would become an issue if I was to submit all this &lt;code&gt;ppoll&lt;/code&gt; work to libzmq as a pull request. My need for &lt;code&gt;select&lt;/code&gt; would inflate the library a bit. This is a trade-off that the libzmq devs will have to decide on.&lt;/p&gt;
&lt;p&gt;If they don’t see this happening, I can still publish &lt;code&gt;zmq::ppoll&lt;/code&gt; as a separate library. I just need to flip the switch on all the &lt;code&gt;select&lt;/code&gt; vs &lt;code&gt;poll&lt;/code&gt; configured code. This can be done from &lt;code&gt;platform.hpp&lt;/code&gt;. And this is exactly what I’ve done in &lt;a href=&quot;https://github.com/roofit-dev/root/tree/MP_ZeroMQ-new_multiprocess/roofit/roofitZMQ&quot;&gt;the current RooFitZMQ implementation that you can find in this hidden away corner of GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;even-more-details&quot;&gt;Even more details&lt;/h2&gt;
&lt;p&gt;For the really technically interested reader (as if you would be anything else if you’ve reached this far down into the article), some final implementation details that may trip you up (as they did for me):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a &lt;code&gt;volatile sig_atomic_t&lt;/code&gt; value type for any values you set from within a signal handler. Changing other types is undefined behavior. It will usually work, but I guess in some rare cases it may not and you’ll be scrambling for explanations and will never sleep well again, knowing the mysterious bug that has eluded you for years and that you have heard whispered rumors about from your users is still lurking in the shadows.&lt;/li&gt;
&lt;li&gt;Handle errors (exceptions in the C++ case) wisely. That’s the short version, see the rest of this article for the long version.&lt;/li&gt;
&lt;li&gt;Make sure to set both your receives and your sends to non-blocking with the &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt; flag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A practical problem with the latter point is that at the beginning of your run, the connections may not have been made between the sockets. This can lead to the non-blocking send to drop out with an EAGAIN error. Now, you may think (like I did): fine, I’ll handle that error and retry the send. However, the same error will occur at the end of your program when you disconnected the other end of your socket on purpose (as I found out the hard way). At this time, you won’t want to retry infinitely, which would hang your program (which happened to me), so just covering up all your sends in retry loops that trigger on EAGAIN will be too coarse a solution (believe me, I tried).&lt;/p&gt;
&lt;p&gt;What I went with in the end is to define a &lt;code&gt;send_flag&lt;/code&gt; in my Messenger class which I pass as the &lt;code&gt;flag&lt;/code&gt; option to all send calls. Initially, &lt;code&gt;send_flag&lt;/code&gt; is zero, so the send calls will block. I then call a &lt;code&gt;test_connections&lt;/code&gt; method and after this completes successfully, I set &lt;code&gt;send_flag&lt;/code&gt; to &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt;. Now, once the connection drops out, send calls will give the EAGAIN error. But this time, the start-of-the-program cause of EAGAIN is ruled out, so I can assume that the program has ended. I catch the EAGAIN in my event loops and continue the loop when I get an EAGAIN. This means the code will first come across my &lt;code&gt;ppoll&lt;/code&gt; again before it comes back to the send that caused the EAGAIN. Inside &lt;code&gt;ppoll&lt;/code&gt;, it will handle the &lt;code&gt;SIGTERM&lt;/code&gt; signal that I expect has been sent from the master process and the event loop will be exited properly.&lt;/p&gt;
&lt;p&gt;Lol, you thought that would be it, but no, it’s still not that simple (I’m talking to my innocent, naive, past self here). There are still three other reasons EAGAIN could trigger!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Calls to receive (&lt;code&gt;recv&lt;/code&gt;) can also trigger an EAGAIN. To distinguish between send and receive EAGAIN triggers, we could throw different typed exceptions (remember, we’re doing C++ here, so every time I’m talking about error codes, what actually happened was a &lt;code&gt;zmq::error_t&lt;/code&gt; type exception was thrown… which also happens to carry along the traditional C style error code). As far as I can tell, the only reason &lt;code&gt;recv&lt;/code&gt; would trigger EAGAIN after a &lt;code&gt;ppoll&lt;/code&gt; (which I now call before every &lt;code&gt;recv&lt;/code&gt; call) is if &lt;code&gt;ppoll&lt;/code&gt; initially gets a read-ready signal for the socket, but the received data does not pass a ZMQ internal checksum test, so the socket becomes unreadable again when you actually try to read from it. In this case, which I hope is rare, things will probably break unless you try really hard to fix them, i.e. send a signal to the sender that something went wrong, or otherwise implementing a really robust messenging protocol. This therefore goes far beyond the scope of just combining ZMQ with POSIX signals and is described very well elsewhere (like in &lt;a href=&quot;http://zguide.zeromq.org/&quot;&gt;the awesome ZMQ guide&lt;/a&gt; I mentioned at the beginning of this article; in case you forgot, which I myself did, because it took me three weeks to get to the end of writing this post).&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;send&lt;/code&gt; call may have two other legitimate reasons for crapping out with EAGAIN. The first is that its receiving end may have hit its “high-water mark”, a ZMQ setting which you can look up in the ZMQ guide or elsewhere.&lt;/li&gt;
&lt;li&gt;The second reason &lt;code&gt;send&lt;/code&gt; could throw an EAGAIN is that the connection may have been severed unexpectedly. In my case, this would mean that in the following &lt;code&gt;ppoll&lt;/code&gt; call, no &lt;code&gt;SIGTERM&lt;/code&gt; signal will be received and so the code will just try to go on, probably hitting the same connection error again and again ad infinitum. This should also be handled properly, but I’m hoping it’s rare enough to not have to worry about it too much. Obviously, I will worry about it for the rest of my waking days. Will probably write another huge blog post about it at some point. Oh well!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We leave the latter problems to be solved as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;607&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Y4MItKsAbWEe8uMM-9a23482a.DWJ09j4z_Z1k6945.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The reader.&lt;/p&gt;
&lt;h2 id=&quot;to-be-continued&quot;&gt;To be continued&lt;/h2&gt;
&lt;p&gt;So stay tuned for the release of &lt;code&gt;zmq_ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update Oct 2021:&lt;/em&gt; &lt;code&gt;*zmq_ppoll*&lt;/code&gt; &lt;em&gt;is now included in&lt;/em&gt; &lt;a href=&quot;https://github.com/zeromq/libzmq/pull/4255&quot;&gt;&lt;em&gt;libzmq&lt;/em&gt;&lt;/a&gt;&lt;em&gt;!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you have any questions or other thoughts, let me know in the comments or on &lt;a href=&quot;https://twitter.com/egpbos&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/f2r1i6/combining_zeromq_posix_signals_use_ppoll_to/&quot;&gt;Reddit&lt;/a&gt;! Having spent so much time on this stuff, I guess sunk cost fallacy demands of me that I spend even more time on it by discussing it with as many people as possible;) Also, I guess I’m kind of a mental masochist. Figuring out this stuff has been extremely frustrating, but also extremely satisfying. So throw your problems at me, I’m hungry for more!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;606&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_rV5RjZZhWGP2x-2D-5a5d4e32.fG00B1uj_1y7Nbt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;My happy face (not mine, but close enough), thinking about solving even more complex messaging problems.&lt;/p&gt;
&lt;p&gt;Thanks to Inti Pelupessy and for reviewing this article.&lt;/p&gt;</description><pubDate>Wed, 12 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;use-ppoll-to-handle-eintr-once-and-for-all&quot;&gt;Use ppoll to handle EINTR once and for all&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_9673x3EO1AadXhPS-8582ce0f.BV_1Ju2O_2eA7ip.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What my first experience trying to send out signals was like. Can anybody hear me? Photo by Jason Rosewell on Unsplash&lt;/p&gt;
&lt;p&gt;I have been dabbling in using and mixing these two well known interprocess communication techniques for a few months now. Dabbling may not be the right word. More like desperately trying to find my way out of a dark room without a flash light.&lt;/p&gt;
&lt;p&gt;Speaking of which, if you’re ever in &lt;a href=&quot;https://en.wikipedia.org/wiki/Nijmegen&quot;&gt;Nijmegen&lt;/a&gt;, be sure to visit the &lt;a href=&quot;https://muzieum.nl/&quot;&gt;muZIEum&lt;/a&gt; and experience what it’s like to be blind. In their basement, they recreated everyday scenes and then made it completely, absolutely dark. It’s really a magnificent experience.&lt;/p&gt;
&lt;p&gt;Anyway, once you’ve done that, you’ll know how I have been feeling lately trying to get ZeroMQ to play nice with POSIX signals… I hope that after reading this, you won’t have to feel the same way, if you don’t want to (if you do, visit Nijmegen, or stop reading now).&lt;/p&gt;
&lt;p&gt;Specifically, I present here some &lt;strong&gt;pitfalls and problems&lt;/strong&gt; of using &lt;strong&gt;ZeroMQ&lt;/strong&gt; calls &lt;code&gt;send&lt;/code&gt;, &lt;code&gt;receive&lt;/code&gt; and &lt;code&gt;poll&lt;/code&gt;, which are blocking calls (they pause the program until they get what they were waiting for), in &lt;strong&gt;combination&lt;/strong&gt; with &lt;strong&gt;POSIX&lt;/strong&gt; signals that interrupt these calls. In my case, initially, these calls were external, but eventually, I also wanted to actively trigger them myself. Both situations require different approaches.&lt;/p&gt;
&lt;p&gt;Luckily, there is a &lt;strong&gt;solution to the problems&lt;/strong&gt;, which I’ll also come to at the end of this article after a long winded description of the process of me wrapping my head around all of this. Long story short: I implemented a &lt;code&gt;ppoll&lt;/code&gt; ZeroMQ call (yes, with double p).&lt;/p&gt;
&lt;p&gt;But let’s first set the scene before diving into details.&lt;/p&gt;
&lt;h2 id=&quot;backstory&quot;&gt;Backstory&lt;/h2&gt;
&lt;p&gt;Our story takes place in the &lt;a href=&quot;https://root.cern/&quot;&gt;ROOT C++ data analysis framework&lt;/a&gt; for particle physics experiments, specifically in the RooFit package. (For the short, technical essentials of the following chronicle, skip down to the next header Technical overview.)&lt;/p&gt;
&lt;p&gt;I’m building a system to run RooFit calculations in parallel on multiple processes. To do that, I need interprocess communication. For this, I chose ZeroMQ, because of its &lt;a href=&quot;http://zguide.zeromq.org/page:all&quot;&gt;really funny manual&lt;/a&gt; (and because other people seemed to like it, particularly Roel Aaij, who helped me get started with it).&lt;/p&gt;
&lt;p&gt;At this point, you may wonder why we didn’t use an existing task execution framework like &lt;a href=&quot;https://en.wikipedia.org/wiki/Threading_Building_Blocks&quot;&gt;TBB&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Cilk&quot;&gt;Cilk&lt;/a&gt;, but we had some specific design constaints that made this impossible (integration with the current RooFit C++ code and performance requirements), so we had to whip up our own thing.&lt;/p&gt;
&lt;p&gt;Everything was coming along nicely. With lots of valuable input from the team, Inti Pelupessy and I designed and built the MultiProcess system, it was working just fine, we benchmarked it, presented it and published a bit and things seemed to be hunky-dory. Matter of packing it up and shipping it. Or so we thought.&lt;/p&gt;
&lt;p&gt;The first version had some, let’s say, &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaghetti_code&quot;&gt;sub-optimal implementation choices&lt;/a&gt; (which I take full responsibility for). Also, in our final version, we wanted to make a few user-facing design changes. So we got together, made a better design and I started coding version two.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;484&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_h49Fzwhw4IyLttce-96e6ecef.BrHBnW_b_ZnKtpU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The redesign team at CERN past summer. So young. So naive (speaking for myself at least).&lt;/p&gt;
&lt;p&gt;To make the MultiProcess framework more maintainable, I split it into several conceptual classes. Most importantly, the so-called &lt;code&gt;TaskManager&lt;/code&gt; was taken apart. The &lt;code&gt;TaskManager&lt;/code&gt; did hardly anything to manage tasks. Instead it managed a task queue, interprocess communication and forking into multiple processes, i.e. everything needed behind the scenes to get workers (processes) to calculate their parts of the total calculation and then send the results back to the master process. Workers don’t need management, they just need someone to take all the red tape away from them so they can focus on what they do best! There is no political message here!&lt;/p&gt;
&lt;p&gt;So, now we have a &lt;code&gt;JobManager&lt;/code&gt; which keeps a list of &lt;code&gt;Job&lt;/code&gt; s, and explicitly spawns objects for the other previously bunched together tasks of the &lt;code&gt;TaskManager&lt;/code&gt; (are you confused yet?): a &lt;code&gt;Queue&lt;/code&gt;, a &lt;code&gt;Messenger&lt;/code&gt; and a &lt;code&gt;ProcessManager&lt;/code&gt;. The queue also runs an event loop on the queue process (which the master process talks to) and the worker processes (which talk to the queue as well) run a &lt;code&gt;worker_loop&lt;/code&gt; which is just a free function, yay C++, free the functions from their classist masters! Still no politics, I assure you.&lt;/p&gt;
&lt;p&gt;Now, one of the nice things of having monolithic classes is that you don’t have to worry too much about, say, separating your concerns. This means for instance that the old &lt;code&gt;TaskManager&lt;/code&gt; could use its messaging parts to tell its process management parts to shut down children after the Job was done.&lt;/p&gt;
&lt;p&gt;In the new situation, the &lt;code&gt;JobManager&lt;/code&gt; instantiates its &lt;code&gt;ProcessManager&lt;/code&gt; member to spawn child processes and after that instantiates its &lt;code&gt;Messenger&lt;/code&gt; member to setup our means of communication. In C++ it would be most natural to let the destructor of these classes clean up all connections and processes. However, when we do this after our Job is done, we can no longer use the &lt;code&gt;Messenger&lt;/code&gt; to communicate between processes, because there is a recursive dependency. We would need the &lt;code&gt;Messenger&lt;/code&gt; to tell the &lt;code&gt;ProcessManager&lt;/code&gt; to terminate the processes, but the processes cannot die before they killed the &lt;code&gt;Messenger&lt;/code&gt;, because through ZeroMQ it keeps alive an I/O thread that waits for messages from the ZeroMQ sockets that we haven’t killed yet because we needed them to kill the processes!&lt;/p&gt;
&lt;p&gt;In principle, you can do it by sending a terminate signal over the messenger, which triggers the destruction of the &lt;code&gt;JobManager&lt;/code&gt;, which then destroys all its component members. This has its own issues, not the least of which is that it creates an external dependency for destruction, which seems like a bad design choice.&lt;/p&gt;
&lt;p&gt;To get out of this swamp, there are several other possibilities, like making the messenger a singleton class like the &lt;code&gt;JobManager&lt;/code&gt; or the ZeroMQ context (yeah, now the skeletons come popping out of the closet), but I just couldn’t bear making yet another one of those.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;958&quot; height=&quot;487&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wNTLScaDrD53gnLf-f331d8a7.DYdSrnaR_Z6R5ey.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Honestly, my closet isn’t big enough to hold all the skeletons…&lt;/p&gt;
&lt;p&gt;In any case, I thought it would be nice to make the classes independent (even though the &lt;code&gt;Messenger&lt;/code&gt; still needs the &lt;code&gt;ProcessManager&lt;/code&gt; instance at creation time to tell it which process it is running on, but this can easily be passed on via the constructor, a feat which destructors unfortunately cannot perform).&lt;/p&gt;
&lt;p&gt;To this end, I decided to have the &lt;code&gt;ProcessManager&lt;/code&gt; just use POSIX signals to signal all its kids to die.&lt;/p&gt;
&lt;h2 id=&quot;technical-overview&quot;&gt;Technical overview&lt;/h2&gt;
&lt;p&gt;So, long story short: I have a master process, which spawns 1 + N children:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a queue process, running a loop to wait for messages and then act on them;&lt;/li&gt;
&lt;li&gt;N worker processes, also running a messaging loop.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;ProcessManager&lt;/code&gt; takes care of forking child processes in the constructor and killing them off by sending POSIX signals from the destructor.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Messenger&lt;/code&gt; sends around job descriptions and results from the master to the queue and from queue to workers. It uses ZeroMQ sockets for this. At the end of its life, it just shuts down all sockets, closes the ZeroMQ context and that’s that.&lt;/p&gt;
&lt;p&gt;Note that these instances are cloned to all forked children, but on each child there is only one instance, owned by the singleton &lt;code&gt;JobManager&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;All good so far.&lt;/p&gt;
&lt;p&gt;Now, the issue is this: since we can no longer use our messenger to send a termination message, the loop will run indefinitely. This is why we use the &lt;code&gt;SIGTERM&lt;/code&gt; signal to stop the process. To do this, we must install a signal handler using the POSIX &lt;code&gt;signal&lt;/code&gt; call. We use the signal handler to flip some globally accessible flag variable, which we check for in the message loops and exit the loops once it’s flipped.&lt;/p&gt;
&lt;p&gt;Again, seems simple enough.&lt;/p&gt;
&lt;p&gt;Unfortunately, it caused me a week or two of headaches.&lt;/p&gt;
&lt;h2 id=&quot;first-try-tying-knots&quot;&gt;First try: tying knots&lt;/h2&gt;
&lt;p&gt;The complication arises because ZeroMQ operations &lt;code&gt;send&lt;/code&gt;, &lt;code&gt;recv&lt;/code&gt; and &lt;code&gt;poll&lt;/code&gt;, which we use to wait for messages in the loops, are blocking functions that only exit when they have some data incoming or outgoing &lt;strong&gt;or&lt;/strong&gt; when they encounter some error, like &lt;strong&gt;a POSIX signal interrupting them&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When such an interrupt happens, the operation exits with an &lt;code&gt;EINTR&lt;/code&gt; exit code, which you can (and should!) check for. The thing is that it can happen for all kinds of signals and some may be harmless. For instance, profilers also use signals to measure a program’s time spent in certain functions. For those you may want the &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt; to just retry. Also, on other errors, you may want to just raise an exception and get the hell out of there, back to where the &lt;code&gt;recv&lt;/code&gt; was called from.&lt;/p&gt;
&lt;p&gt;In any case, when we get a POSIX signal while inside &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt;, first the signal handler will flip our flag switch, then, back inside the blocking &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt;, the &lt;code&gt;send&lt;/code&gt; / &lt;code&gt;recv&lt;/code&gt; / &lt;code&gt;poll&lt;/code&gt; will return with an &lt;code&gt;EINTR&lt;/code&gt; exit code. We check the exit code and the flag switch and either start shutting down when we received our kill signal or continue when we didn’t:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;while (true) {                  // send&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;recv&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;poll retry loop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  try {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    int timeout &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;           &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; infinite&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;no timeout, i.e. block&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    socket&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;recv(timeout);       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or send, or poll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  } except (zmq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error_t &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;e) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    if (e&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;num&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; !=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; EINTR&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      throw;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      if (my_global_flag_is_switched) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;        std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exit(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);           &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or some fancier way &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exiting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; toe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; down&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the stairs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will often go well. It also often goes wrong, as my tests were showing. About half of the time one of the terminated children would hang…!@*$%&amp;#x26;&lt;/p&gt;
&lt;p&gt;The problem here is that the &lt;code&gt;SIGTERM&lt;/code&gt; signal is not guaranteed to be received inside the blocking ZeroMQ call. In fact, it will often be received when in some other function, because it may still be busy handling a previous message. When this happens, the flag will be flipped, but it is not checked! At some point the message loop returns to the &lt;code&gt;recv&lt;/code&gt; call and will just block there.&lt;/p&gt;
&lt;p&gt;An obvious looking solution to this specific problem is to put another switch-check in front of the &lt;code&gt;recv&lt;/code&gt;, i.e.:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (my_global_flag_is_switched) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exit(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);             &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or some fancier way &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; exiting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; hello darkness, my old friend  socket&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;recv(timeout);       &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; or send, or poll&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this will certainly reduce the odds of going into a blocking call when &lt;code&gt;SIGTERM&lt;/code&gt; has been received, it still doesn’t guarantee anything. There is still soom innocent looking room in between the check and the blocking call. The signal could still be received just before the &lt;code&gt;recv&lt;/code&gt; call has been entered. Or, maybe more precisely, before one of the actually blocking system calls inside &lt;code&gt;recv&lt;/code&gt; has been entered; but also the process could simply have been put on hold by the OS exactly at the moment after the flag check. In any case, this setup will still hang indefinitely every now and then.&lt;/p&gt;
&lt;p&gt;So this way of interleaving POSIX and ZeroMQ calls and checks will never be enough, there will always be a possibility that your blocking call will hang.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;1213&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_kpJXLkNFcTnvN0Om-fc5127c6.ChUf-9Qp_Z13yUWa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Haaaaaaaaaang. Haaaaaaaaaaaaang.&lt;/p&gt;
&lt;h2 id=&quot;second-try-queue-it-all&quot;&gt;Second try: queue it all&lt;/h2&gt;
&lt;p&gt;I was Googling for alternative solutions and honestly found it really hard to find good resources on this (which is the main reason I’m now writing it all down for you in this article).&lt;/p&gt;
&lt;p&gt;Eventually, I found &lt;a href=&quot;http://250bpm.com/blog:12&quot;&gt;this article on EINTR in ZeroMQ&lt;/a&gt; by Martin Sustrik (ZeroMQ creator) himself. More precisely, in the comment section &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1608507&quot;&gt;Ambroz Bizjak suggested a solution&lt;/a&gt; to my problem which after some discussion even Sustrik seemed to be unaware of. The solution wasn’t completely fleshed out in the comments, so there was still some filling out for me to do. Luckily for you, you won’t have to repeat this exercise.&lt;/p&gt;
&lt;p&gt;The solution is that when going into the blocking ZeroMQ calls, you temporarily block the POSIX signals you want to listen for; &lt;code&gt;SIGTERM&lt;/code&gt; in our case. This can be done using &lt;code&gt;sigprocmask&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, instead of using your regular blocking ZeroMQ call, you use &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; to wait for something to happen on your sockets &lt;strong&gt;and your signal queue.&lt;/strong&gt; Because, as it turns out, when you temporarily block signals using &lt;code&gt;sigprocmask&lt;/code&gt;, they are put in a queue by the OS. You can then handle them at your earliest convenience.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; functions can monitor lists of sockets &lt;strong&gt;and&lt;/strong&gt; you can give them a &lt;strong&gt;signal mask&lt;/strong&gt; like the one you gave &lt;code&gt;sigprocmask&lt;/code&gt;, but then without the signal that you specifically wanted to block outside of the &lt;code&gt;pselect&lt;/code&gt; / &lt;code&gt;ppoll&lt;/code&gt; call. This will make &lt;code&gt;pselect&lt;/code&gt; and &lt;code&gt;ppoll&lt;/code&gt; listen to those signals that you blocked earlier. When a signal came in (or a socket is ready for reading/writing) they will return. If you put the flag check after &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;, the signal will always be handled properly.&lt;/p&gt;
&lt;p&gt;One other critical modification is that in this case you should no longer use blocking ZeroMQ calls. This has also become unnecessary, because you already checked whether some data is incoming on the socket using &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Finally, note that also right after you blocked the signal with &lt;code&gt;sigprocmask&lt;/code&gt;, you should put one additional check for the signal flag, because the signal may yet have triggered somewhere just before you blocked it.&lt;/p&gt;
&lt;p&gt;All in all, the code would then become something like that of Ambroz Bizjak:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;set file descriptor to non&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;blocking;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sigprocmask&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to block &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (stop) { // handle it }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;while (true) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  pselect&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with sigmask argument which doesn&apos;t block &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SIGINT&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (stop) { // handle it }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  recv&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;sigprocmask(old) to put back the old mask &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; use before we replaced it;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;integrating-into-zeromq&quot;&gt;Integrating into ZeroMQ&lt;/h2&gt;
&lt;p&gt;This is great in theory, but as already mentioned in the reply by Sustrik: this means we would need a &lt;code&gt;pselect&lt;/code&gt; or &lt;code&gt;ppoll&lt;/code&gt; in ZeroMQ. I was originally using &lt;code&gt;zmq::poll&lt;/code&gt;, which internally uses regular POSIX &lt;code&gt;poll&lt;/code&gt;. We can in principle modify this fairly easily to take the additional argument necessary for &lt;code&gt;ppoll&lt;/code&gt;, namely the signal mask.&lt;/p&gt;
&lt;p&gt;However, then we need to decide on how to handle this internally in ZMQ. I cannot do this on my own, but decided to write a first implementation anyway. However, when I started thinking about actually doing this, a few new problems raised their ugly heads.&lt;/p&gt;
&lt;p&gt;The first idea I had was to again use a global flag that can be flipped from the signal handler when a signal is received… At this point I finally realized what Sustrik was talking about when he said we can’t use signal handlers in libraries. First of all: we don’t know which signals the user will want to actually mask. Maybe they want to act on several signals and so will need several global flags. So, long story short: this cannot be done generically inside a &lt;code&gt;zmq::ppoll&lt;/code&gt; or &lt;code&gt;zmq::pselect&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So then we only have two possible tools left to let the user know we caught a signal: the return value and the error code.&lt;/p&gt;
&lt;p&gt;The return value is constrained; the API should conform to existing APIs like those of POSIX &lt;code&gt;ppoll&lt;/code&gt; and &lt;code&gt;zmq::poll&lt;/code&gt;. We can only use return values of &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;, where &lt;code&gt;-1&lt;/code&gt; means an error occurred. So probably the only sensible option is to modify &lt;code&gt;zmq_poll&lt;/code&gt; (now I’m talking about the libzmq implementation; &lt;code&gt;zmq::poll&lt;/code&gt; is merely a C++ wrapper around &lt;code&gt;zmq_poll&lt;/code&gt;) to return &lt;code&gt;-1&lt;/code&gt; and set the &lt;code&gt;errno&lt;/code&gt; to &lt;code&gt;EINTR&lt;/code&gt; when the signal is received.&lt;/p&gt;
&lt;p&gt;So this sounds a bit like we’d be back at square one… Except that this time the &lt;code&gt;ppoll&lt;/code&gt; function would be &lt;strong&gt;the only place where the signal is unblocked&lt;/strong&gt;, so we know exactly where it will occur and, more importantly, where it will not. Problem solved!&lt;/p&gt;
&lt;p&gt;Now I just had to write it…&lt;/p&gt;
&lt;h2 id=&quot;ppoll-pselect-or-self-pipe&quot;&gt;Ppoll, pselect or self-pipe?&lt;/h2&gt;
&lt;p&gt;After a two week hiatus, I came back, tried to implement &lt;code&gt;zmq_ppoll&lt;/code&gt; by simply copy-pasting &lt;code&gt;zmq_poll&lt;/code&gt; and replacing &lt;code&gt;poll&lt;/code&gt; with &lt;code&gt;ppoll&lt;/code&gt;, but was unpleasantly surprised by the fact that &lt;code&gt;ppoll&lt;/code&gt; apparently doesn’t exist on macOS. &lt;code&gt;[pselect](&amp;#x3C;https://stackoverflow.com/a/46047380/1199693&gt;)&lt;/code&gt; does exist, so we’ll have to go with that.&lt;/p&gt;
&lt;p&gt;Luckily, the &lt;code&gt;zmq_poll&lt;/code&gt; implementation is really flexible, and already includes a &lt;code&gt;select&lt;/code&gt; -based path next to the &lt;code&gt;poll&lt;/code&gt; -based one. We modify that to take a &lt;code&gt;sigmask&lt;/code&gt; and Bob’s your uncle.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_AnAinknYq39MUSLc-37df9805.2E-MjPnF_Z1yMCU8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’m your uncle! &lt;a href=&quot;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&quot;&gt;https://itkonekt.com/2018/12/17/robert-c-martin-uncle-bob/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So indeed, let’s try out &lt;code&gt;pselect&lt;/code&gt;. I did have some reservations, because the web is rather full of reports of it not being implemented properly on macOS / FreeBSD… see &lt;a href=&quot;https://stackoverflow.com/questions/14045801/different-pselect-behaviour-on-osx-vs-linux&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=12857275&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://news.ycombinator.com/item?id=16321529&quot;&gt;here&lt;/a&gt;… Hopefully, as also reported &lt;a href=&quot;https://news.ycombinator.com/item?id=12904883&quot;&gt;here&lt;/a&gt;, in recent versions this is fixed. It seems like they could have taken inspiration by now from many existing, reportedly correct, implementations, like &lt;a href=&quot;http://lua-users.org/lists/lua-l/2015-01/msg00697.html&quot;&gt;this one&lt;/a&gt;. This does mean our implementation will only be really 100% robust on recent macOS versions, but so be it.&lt;/p&gt;
&lt;p&gt;At this point, under all these doubts about the stability of it all, I almost gave up on &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; to try out the so-called ” &lt;a href=&quot;http://cr.yp.to/docs/selfpipe.html&quot;&gt;self-pipe trick&lt;/a&gt; ” that is also &lt;a href=&quot;https://lwn.net/Articles/176911/&quot;&gt;floating around&lt;/a&gt; in these discussions. This could be a good alternative in some ways.&lt;/p&gt;
&lt;p&gt;The problem with the self-pipe trick is that you can’t fully implement it in all its gory details in a library. The trick involves sending a byte over a pipe &lt;em&gt;from a signal handler&lt;/em&gt;. As &lt;a href=&quot;http://250bpm.com/blog:12/comments/show#post-1654888&quot;&gt;Sustrik mentions&lt;/a&gt;, we cannot rely on signal handlers at all. We have to assume they can be overridden by users of our libraries. In fact, ROOT might install its own signal handlers, indeed invalidating the entire approach we’d be going for here. Though, in fact, the last signal handler that is set is the one that trumps others. When we only set the &lt;code&gt;SIGTERM&lt;/code&gt; handler when doing all this stuff and then set the handler back to its original value afterwards, we should be safe, except that we might be interfering with other signal handlers, but that will be necessary in most cases anyway, because also the &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; route will at some point need to install a signal handler. The cleaner alternative (when setting signal handlers are really out of the question) is to let the user of your library implement their own self-pipe signal handler. In my opinion, this is way too heavy a burden on the user.&lt;/p&gt;
&lt;p&gt;So in the end, I chose to go with &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt;, because it puts most of the code on the library side and avoids having to setup and maintain an extra pipe. The only thing you need with the &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; option is a simple signal handler and a flag to check. It seems like a simpler and more user-friendly option.&lt;/p&gt;
&lt;p&gt;Whatever you choose, some handling of POSIX signals will be necessary in a robust multi-process application. For instance, if a child process dies for some reason, a &lt;code&gt;SIGCHLD&lt;/code&gt; signal is sent to the parent, which could also interrupt blocking reads, sends and polls (if &lt;code&gt;SIG_IGN&lt;/code&gt; is not set for this signal). These must be handled either by using &lt;code&gt;ppoll&lt;/code&gt; / &lt;code&gt;pselect&lt;/code&gt; or by using the self-pipe trick.&lt;/p&gt;
&lt;h2 id=&quot;the-result&quot;&gt;The result&lt;/h2&gt;
&lt;p&gt;So, I implemented the &lt;code&gt;zmq::ppoll&lt;/code&gt; via &lt;code&gt;pselect&lt;/code&gt; route. And finally, after a lot of debugging, it seems to be working well!&lt;/p&gt;
&lt;p&gt;Its low level implementation (&lt;code&gt;zmq_ppoll&lt;/code&gt;) depends on many libzmq macros, defines and functions. Trying to build against this creates a giant string of dependency files. The problem with this is that libzmq does not expose all these internal headers, so for the time being I just copy pasted over all the necessary libzmq files. Amazingly, this just seems to work after a few tweaks. My compliments to the libzmq devs for creating such modular code!&lt;/p&gt;
&lt;p&gt;Regarding the few tweaks: there are a lot of precompiler variables which are used to configure the compiled libzmq code. It seems that for macOS, this configuration is perfectly comfortable basing &lt;code&gt;zmq_poll&lt;/code&gt; on &lt;code&gt;poll&lt;/code&gt;. This makes sense, but for our purposes it is really annoying, because we need all the stuff that would be compiled in the case &lt;code&gt;zmq_poll&lt;/code&gt; would be based on &lt;code&gt;select&lt;/code&gt;. A lot of necessary classes and typedefs are therefore not at all fed to the compiler from all the lazily copy-pasted headers and source files.&lt;/p&gt;
&lt;p&gt;This would become an issue if I was to submit all this &lt;code&gt;ppoll&lt;/code&gt; work to libzmq as a pull request. My need for &lt;code&gt;select&lt;/code&gt; would inflate the library a bit. This is a trade-off that the libzmq devs will have to decide on.&lt;/p&gt;
&lt;p&gt;If they don’t see this happening, I can still publish &lt;code&gt;zmq::ppoll&lt;/code&gt; as a separate library. I just need to flip the switch on all the &lt;code&gt;select&lt;/code&gt; vs &lt;code&gt;poll&lt;/code&gt; configured code. This can be done from &lt;code&gt;platform.hpp&lt;/code&gt;. And this is exactly what I’ve done in &lt;a href=&quot;https://github.com/roofit-dev/root/tree/MP_ZeroMQ-new_multiprocess/roofit/roofitZMQ&quot;&gt;the current RooFitZMQ implementation that you can find in this hidden away corner of GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;even-more-details&quot;&gt;Even more details&lt;/h2&gt;
&lt;p&gt;For the really technically interested reader (as if you would be anything else if you’ve reached this far down into the article), some final implementation details that may trip you up (as they did for me):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use a &lt;code&gt;volatile sig_atomic_t&lt;/code&gt; value type for any values you set from within a signal handler. Changing other types is undefined behavior. It will usually work, but I guess in some rare cases it may not and you’ll be scrambling for explanations and will never sleep well again, knowing the mysterious bug that has eluded you for years and that you have heard whispered rumors about from your users is still lurking in the shadows.&lt;/li&gt;
&lt;li&gt;Handle errors (exceptions in the C++ case) wisely. That’s the short version, see the rest of this article for the long version.&lt;/li&gt;
&lt;li&gt;Make sure to set both your receives and your sends to non-blocking with the &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt; flag.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A practical problem with the latter point is that at the beginning of your run, the connections may not have been made between the sockets. This can lead to the non-blocking send to drop out with an EAGAIN error. Now, you may think (like I did): fine, I’ll handle that error and retry the send. However, the same error will occur at the end of your program when you disconnected the other end of your socket on purpose (as I found out the hard way). At this time, you won’t want to retry infinitely, which would hang your program (which happened to me), so just covering up all your sends in retry loops that trigger on EAGAIN will be too coarse a solution (believe me, I tried).&lt;/p&gt;
&lt;p&gt;What I went with in the end is to define a &lt;code&gt;send_flag&lt;/code&gt; in my Messenger class which I pass as the &lt;code&gt;flag&lt;/code&gt; option to all send calls. Initially, &lt;code&gt;send_flag&lt;/code&gt; is zero, so the send calls will block. I then call a &lt;code&gt;test_connections&lt;/code&gt; method and after this completes successfully, I set &lt;code&gt;send_flag&lt;/code&gt; to &lt;code&gt;ZMQ_DONTWAIT&lt;/code&gt;. Now, once the connection drops out, send calls will give the EAGAIN error. But this time, the start-of-the-program cause of EAGAIN is ruled out, so I can assume that the program has ended. I catch the EAGAIN in my event loops and continue the loop when I get an EAGAIN. This means the code will first come across my &lt;code&gt;ppoll&lt;/code&gt; again before it comes back to the send that caused the EAGAIN. Inside &lt;code&gt;ppoll&lt;/code&gt;, it will handle the &lt;code&gt;SIGTERM&lt;/code&gt; signal that I expect has been sent from the master process and the event loop will be exited properly.&lt;/p&gt;
&lt;p&gt;Lol, you thought that would be it, but no, it’s still not that simple (I’m talking to my innocent, naive, past self here). There are still three other reasons EAGAIN could trigger!&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Calls to receive (&lt;code&gt;recv&lt;/code&gt;) can also trigger an EAGAIN. To distinguish between send and receive EAGAIN triggers, we could throw different typed exceptions (remember, we’re doing C++ here, so every time I’m talking about error codes, what actually happened was a &lt;code&gt;zmq::error_t&lt;/code&gt; type exception was thrown… which also happens to carry along the traditional C style error code). As far as I can tell, the only reason &lt;code&gt;recv&lt;/code&gt; would trigger EAGAIN after a &lt;code&gt;ppoll&lt;/code&gt; (which I now call before every &lt;code&gt;recv&lt;/code&gt; call) is if &lt;code&gt;ppoll&lt;/code&gt; initially gets a read-ready signal for the socket, but the received data does not pass a ZMQ internal checksum test, so the socket becomes unreadable again when you actually try to read from it. In this case, which I hope is rare, things will probably break unless you try really hard to fix them, i.e. send a signal to the sender that something went wrong, or otherwise implementing a really robust messenging protocol. This therefore goes far beyond the scope of just combining ZMQ with POSIX signals and is described very well elsewhere (like in &lt;a href=&quot;http://zguide.zeromq.org/&quot;&gt;the awesome ZMQ guide&lt;/a&gt; I mentioned at the beginning of this article; in case you forgot, which I myself did, because it took me three weeks to get to the end of writing this post).&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;send&lt;/code&gt; call may have two other legitimate reasons for crapping out with EAGAIN. The first is that its receiving end may have hit its “high-water mark”, a ZMQ setting which you can look up in the ZMQ guide or elsewhere.&lt;/li&gt;
&lt;li&gt;The second reason &lt;code&gt;send&lt;/code&gt; could throw an EAGAIN is that the connection may have been severed unexpectedly. In my case, this would mean that in the following &lt;code&gt;ppoll&lt;/code&gt; call, no &lt;code&gt;SIGTERM&lt;/code&gt; signal will be received and so the code will just try to go on, probably hitting the same connection error again and again ad infinitum. This should also be handled properly, but I’m hoping it’s rare enough to not have to worry about it too much. Obviously, I will worry about it for the rest of my waking days. Will probably write another huge blog post about it at some point. Oh well!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We leave the latter problems to be solved as an exercise for the reader.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;607&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Y4MItKsAbWEe8uMM-9a23482a.DWJ09j4z_Z1k6945.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The reader.&lt;/p&gt;
&lt;h2 id=&quot;to-be-continued&quot;&gt;To be continued&lt;/h2&gt;
&lt;p&gt;So stay tuned for the release of &lt;code&gt;zmq_ppoll&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update Oct 2021:&lt;/em&gt; &lt;code&gt;*zmq_ppoll*&lt;/code&gt; &lt;em&gt;is now included in&lt;/em&gt; &lt;a href=&quot;https://github.com/zeromq/libzmq/pull/4255&quot;&gt;&lt;em&gt;libzmq&lt;/em&gt;&lt;/a&gt;&lt;em&gt;!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you have any questions or other thoughts, let me know in the comments or on &lt;a href=&quot;https://twitter.com/egpbos&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/f2r1i6/combining_zeromq_posix_signals_use_ppoll_to/&quot;&gt;Reddit&lt;/a&gt;! Having spent so much time on this stuff, I guess sunk cost fallacy demands of me that I spend even more time on it by discussing it with as many people as possible;) Also, I guess I’m kind of a mental masochist. Figuring out this stuff has been extremely frustrating, but also extremely satisfying. So throw your problems at me, I’m hungry for more!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;606&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_rV5RjZZhWGP2x-2D-5a5d4e32.fG00B1uj_1y7Nbt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;My happy face (not mine, but close enough), thinking about solving even more complex messaging problems.&lt;/p&gt;
&lt;p&gt;Thanks to Inti Pelupessy and for reviewing this article.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_h49Fzwhw4IyLttce-96e6ecef.BrHBnW_b.webp" medium="image"/><author>Patrick Bos</author></item><item><title>Workshop Machine Learning for Research 2020</title><link>https://blog2.esciencecenter.nl/posts/2020-02-11---workshop-machine-learning-for-research-2020</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-02-11---workshop-machine-learning-for-research-2020</guid><description>&lt;h2 id=&quot;for-one-full-week-we-worked-with-6-research-teams-from-different-disciplines-to-explore-if-and-how-machine-learning-could-help-them-answer-their-research-questions-here-is-a-brief-summary-of-what-we-did-how-it-went-and-what-we-learned&quot;&gt;For one full week we worked with 6 research teams from different disciplines to explore if and how machine learning could help them answer their research question(s). Here is a brief summary of what we did, how it went, and what we learned.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Feb 10, 2020&lt;/p&gt;
&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;2
DIALECT, Diabetes and Lifestyle Cohort Twente**** Team from: University of Twente and ZGT Almelo.
Field: Medicine&lt;/p&gt;
&lt;p&gt;The team from University of Twente and ZGT Almelo came to the workshop with a number of different data sets. The main work was done on diabetes type 2 patient data containing details on food intake. During the workshop, the team managed to experiment with many key machine learning techniques for such types of data.&lt;/p&gt;
&lt;p&gt;3
** &lt;strong&gt;Detection/Prediction of Freezing of Gait in Parkinson’s Disease&lt;/strong&gt;** Team from: University of Twente, Orikami, Radboud University
Field: Medicine&lt;/p&gt;
&lt;p&gt;This team came with motion sensor data of patients with Parkinson’s disease. Motion data were recorded during a lab experiment during which patients experienced “freezing gait”: a sudden, brief episode of ineffective stepping also described “as if the feet are glued to the floor”. The aim was to classify motion sensor data as freezing of gait epochs in order to improve freezing of gait detection (and prediction) algorithms. The complex nature of the data gave the team the chance to build deep learning networks and work with techniques to handle unbalanced data sets, such as up-sampling.&lt;/p&gt;
&lt;p&gt;4
Identification of Source Types from Measured Vibration Signals**** Team from: TNO
Field: Earth Sciences, Physics&lt;/p&gt;
&lt;p&gt;Presentation of Davide Moretti from TNO on how they had assembled a really nice test data set on vibration signals (left). And presentation of Sanne van den Boom from TNO on the impressive results they got from their deep learning classifier at the end of the workshop.The team from TNO came with a really interesting data set on vibration signals. They had collected vibration signals from 20 different sources, which included sources such as earthquakes, traffic, drilling, but also bouncing of a ball, a running washing machine or jumping. Using a deep learning model, they were able to beat classical ML tools (random forests etc.) and in the end managed to classify the source types very well! From there the team started to explore Bayesian approaches as possible next steps.&lt;/p&gt;
&lt;p&gt;5
Early prediction of psychiatric problems in developing twins**** Team from: Leiden University
Field: Medicine&lt;/p&gt;
&lt;p&gt;Presentation by Anna van Duijvenvoorde from University of Leiden.This team of researchers from the University of Leiden used the week to explore whether the features they had collected, among others, from MRI scans could be used to make predictions on psychiatric problems. During the workshop, the team managed to apply a wide range of different machine learning techniques, including unsupervised clustering approaches that revealed interesting correlations and aspects within their patient data.&lt;/p&gt;
&lt;p&gt;6Segmentation and Tracking of Single Cells from Live Cell Microscopy Images.**** Team from: TU Delft, AMOLF, Wageningen University
Field: Life Sciences&lt;/p&gt;
&lt;p&gt;This team was hoping to automate a very labor-intensive process which is an essential part of their research on living cells. Within those cells, the bacteria E. Coli are growing and dividing within microfludic chambers. To follow individual bacteria over longer periods of time, it is necessary to properly segment the light microscopy images. The group brought a nice dataset of time series of bacteria with a large number of hand-corrected masks which we then used as training labels. Using convolutional deep neural networks together with proper data augmentation techniques gave us very good results by the end of the workshop.&lt;/p&gt;
&lt;p&gt;First results based on a CNN used for segmenting bacteria from phasecontrast microscopy images.&lt;/p&gt;
&lt;h2 id=&quot;thanks-to&quot;&gt;Thanks to:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;All participants** and teams! We really had a great week and it was wonderful to see so much enthusiasm, curiosity and interesting research questions.&lt;/li&gt;
&lt;li&gt;All the &lt;strong&gt;mentors,&lt;/strong&gt; who were really a driving force behind this workshop! Thanks to all of you for spending so much time mentoring, but also preparing the workshop in advance and reviewing the numerous applications.**Mentors were: [Sonja Georgievska,] Christiaan Meijer, Jaro Camphuijsen [Patrick Bos], Meiert Grootes, Cunliang Geng, Erik Tjong Kim Sang, Faruk Diblen, [Dafne van Kuppevelt], [Felipe], Bouwe Andela, Maxwell Cai, [Florian Huber,] [Jisk Attema].&lt;/li&gt;
&lt;li&gt;SURF,** which provided key infrastructure for this workshop. A lot of the model training was done using Jupyter notebooks that were running on GPUs from LISA. Also thanks Maxwell (SURF) for joining us as a mentor and giving a great first day introduction to ML.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;eScience Center and SURF staff&lt;/strong&gt; for helping to set-up and manage the workshop (special thanks to Sacha van Breugel, Mateusz Kuzak, Carlos Martinez, Tom Bakker, Frank Seinstra, Johan Rheeder, Kim-Anh Holthaus).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Peter Steinbach&lt;/strong&gt; from HZBR, Germany, who gave me the idea to initiate this workshop. Generously shared his own experiences and helped to brainstorm. &lt;a href=&quot;https://indico.mpi-cbg.de/event/186/overview&quot;&gt;Here details on their deep learning hackathon in 2019.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-go-on-to-read-part-22-on-our-workshop-evaluation-how-did-it-work&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/workshop-machine-learning-for-research-2020-did-it-work-4c178f9dbb14&quot;&gt;&lt;strong&gt;→ Go on to read part 2/2 on our workshop evaluation: how did it work?&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;</description><pubDate>Tue, 11 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;for-one-full-week-we-worked-with-6-research-teams-from-different-disciplines-to-explore-if-and-how-machine-learning-could-help-them-answer-their-research-questions-here-is-a-brief-summary-of-what-we-did-how-it-went-and-what-we-learned&quot;&gt;For one full week we worked with 6 research teams from different disciplines to explore if and how machine learning could help them answer their research question(s). Here is a brief summary of what we did, how it went, and what we learned.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Feb 10, 2020&lt;/p&gt;
&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;2
DIALECT, Diabetes and Lifestyle Cohort Twente**** Team from: University of Twente and ZGT Almelo.
Field: Medicine&lt;/p&gt;
&lt;p&gt;The team from University of Twente and ZGT Almelo came to the workshop with a number of different data sets. The main work was done on diabetes type 2 patient data containing details on food intake. During the workshop, the team managed to experiment with many key machine learning techniques for such types of data.&lt;/p&gt;
&lt;p&gt;3
** &lt;strong&gt;Detection/Prediction of Freezing of Gait in Parkinson’s Disease&lt;/strong&gt;** Team from: University of Twente, Orikami, Radboud University
Field: Medicine&lt;/p&gt;
&lt;p&gt;This team came with motion sensor data of patients with Parkinson’s disease. Motion data were recorded during a lab experiment during which patients experienced “freezing gait”: a sudden, brief episode of ineffective stepping also described “as if the feet are glued to the floor”. The aim was to classify motion sensor data as freezing of gait epochs in order to improve freezing of gait detection (and prediction) algorithms. The complex nature of the data gave the team the chance to build deep learning networks and work with techniques to handle unbalanced data sets, such as up-sampling.&lt;/p&gt;
&lt;p&gt;4
Identification of Source Types from Measured Vibration Signals**** Team from: TNO
Field: Earth Sciences, Physics&lt;/p&gt;
&lt;p&gt;Presentation of Davide Moretti from TNO on how they had assembled a really nice test data set on vibration signals (left). And presentation of Sanne van den Boom from TNO on the impressive results they got from their deep learning classifier at the end of the workshop.The team from TNO came with a really interesting data set on vibration signals. They had collected vibration signals from 20 different sources, which included sources such as earthquakes, traffic, drilling, but also bouncing of a ball, a running washing machine or jumping. Using a deep learning model, they were able to beat classical ML tools (random forests etc.) and in the end managed to classify the source types very well! From there the team started to explore Bayesian approaches as possible next steps.&lt;/p&gt;
&lt;p&gt;5
Early prediction of psychiatric problems in developing twins**** Team from: Leiden University
Field: Medicine&lt;/p&gt;
&lt;p&gt;Presentation by Anna van Duijvenvoorde from University of Leiden.This team of researchers from the University of Leiden used the week to explore whether the features they had collected, among others, from MRI scans could be used to make predictions on psychiatric problems. During the workshop, the team managed to apply a wide range of different machine learning techniques, including unsupervised clustering approaches that revealed interesting correlations and aspects within their patient data.&lt;/p&gt;
&lt;p&gt;6Segmentation and Tracking of Single Cells from Live Cell Microscopy Images.**** Team from: TU Delft, AMOLF, Wageningen University
Field: Life Sciences&lt;/p&gt;
&lt;p&gt;This team was hoping to automate a very labor-intensive process which is an essential part of their research on living cells. Within those cells, the bacteria E. Coli are growing and dividing within microfludic chambers. To follow individual bacteria over longer periods of time, it is necessary to properly segment the light microscopy images. The group brought a nice dataset of time series of bacteria with a large number of hand-corrected masks which we then used as training labels. Using convolutional deep neural networks together with proper data augmentation techniques gave us very good results by the end of the workshop.&lt;/p&gt;
&lt;p&gt;First results based on a CNN used for segmenting bacteria from phasecontrast microscopy images.&lt;/p&gt;
&lt;h2 id=&quot;thanks-to&quot;&gt;Thanks to:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;All participants** and teams! We really had a great week and it was wonderful to see so much enthusiasm, curiosity and interesting research questions.&lt;/li&gt;
&lt;li&gt;All the &lt;strong&gt;mentors,&lt;/strong&gt; who were really a driving force behind this workshop! Thanks to all of you for spending so much time mentoring, but also preparing the workshop in advance and reviewing the numerous applications.**Mentors were: [Sonja Georgievska,] Christiaan Meijer, Jaro Camphuijsen [Patrick Bos], Meiert Grootes, Cunliang Geng, Erik Tjong Kim Sang, Faruk Diblen, [Dafne van Kuppevelt], [Felipe], Bouwe Andela, Maxwell Cai, [Florian Huber,] [Jisk Attema].&lt;/li&gt;
&lt;li&gt;SURF,** which provided key infrastructure for this workshop. A lot of the model training was done using Jupyter notebooks that were running on GPUs from LISA. Also thanks Maxwell (SURF) for joining us as a mentor and giving a great first day introduction to ML.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;eScience Center and SURF staff&lt;/strong&gt; for helping to set-up and manage the workshop (special thanks to Sacha van Breugel, Mateusz Kuzak, Carlos Martinez, Tom Bakker, Frank Seinstra, Johan Rheeder, Kim-Anh Holthaus).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Peter Steinbach&lt;/strong&gt; from HZBR, Germany, who gave me the idea to initiate this workshop. Generously shared his own experiences and helped to brainstorm. &lt;a href=&quot;https://indico.mpi-cbg.de/event/186/overview&quot;&gt;Here details on their deep learning hackathon in 2019.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-go-on-to-read-part-22-on-our-workshop-evaluation-how-did-it-work&quot;&gt;&lt;a href=&quot;https://blog2.esciencecenter.nl/workshop-machine-learning-for-research-2020-did-it-work-4c178f9dbb14&quot;&gt;&lt;strong&gt;→ Go on to read part 2/2 on our workshop evaluation: how did it work?&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;</content:encoded><author>Florian Huber</author></item><item><title>Workshop Machine Learning for Research 2020 … did it work?</title><link>https://blog2.esciencecenter.nl/posts/2020-02-11---workshop-machine-learning-for-research-2020-did-it-work</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-02-11---workshop-machine-learning-for-research-2020-did-it-work</guid><description>&lt;h2 id=&quot;evaluating-our-one-week-hands-on-workshop-on-applying-machine-learning-to-research&quot;&gt;Evaluating our one-week hands-on workshop on applying machine learning to research.&lt;/h2&gt;
&lt;p&gt;5
Stimulate diverse teams and be aware of (gender-)biases.****We wanted to attract diverse teams and in particular avoid gender-biases since IT and machine-learning are (still) heavily male dominated. It is very easy to simply add a sentence saying that you welcome female participants, but that’s probably not going to do the job if the rest of the text is full of gender-coded works (“competitive”, “hacking”, …).&lt;/p&gt;
&lt;p&gt;There are apps to check your text for masculine-coded words (e.g. &lt;a href=&quot;http://gender-decoder.katmatfield.com/&quot;&gt;http://gender-decoder.katmatfield.com/&lt;/a&gt;), but they only cover a short list of words and don’t get the context. So they can primarily serve to give you an idea of how subtle things can be. More particularly, we avoided wording that could make the workshop sound competitive, which started with not officially calling it a hackathon**!&lt;/p&gt;
&lt;p&gt;Although we can’t prove this did the trick, I definitely think that the many discussions we had with a wide range of people about this subject before setting up the workshop really helped us a lot. And the outcome was great, too. Out of all the team members, **40% were female **(of 101 applicants in total). Among the selected teams we worked with during the workshop this number even went up to &lt;strong&gt;59% female participants&lt;/strong&gt; (of the final 27 participants).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labs.spotify.com/2015/01/13/diversify-how-we-created-a-hackathon-with-50-50-female-male-participants/&quot;&gt;(See also this blog post on hackathons with high female participant numbers)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;6**
Join forces with SURF.**** Not only did Maxwell Cai from SURF make a very valuable addition to our list of mentors (also giving an interesting introductory lecture on ML), we also benefited from the compute infrastructure provided by SURF. During the workshop, we had access to GPUs via simple Jupyter notebooks that we used intensively to train our deep learning models (for 4 teams using deep learning we had 8 GTX 1080Ti GPUs which was fully sufficient for the type of tasks we had).&lt;/p&gt;
&lt;h2 id=&quot;things-wed-like-to-improve&quot;&gt;Things we’d like to improve:&lt;/h2&gt;
&lt;p&gt;The positives notwithstanding, there is of course also a long list of things we can improve on. Luckily, most items on that list were clearly very minor issues. The more important lessons we learned were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better representation of some research field****There are disciplines within the humanities and social sciences where I believe machine learning can add a lot of value. Out of 25 applications, only 2 came from those fields. So next time we will certainly make an effort to better target humanities and social science research institutions.&lt;/li&gt;
&lt;li&gt;Extend the pre-workshop training.**&lt;strong&gt;We had thought about it and did offer a free one-day Python course in the week before the workshop, which indeed turned out to be very helpful. But to give participants with less coding experience and little to no prior Python experience a bit more time to prepare, it would be better to organize such a training a bit more in advance.
Next time we plan to add a separate onboarding day&lt;/strong&gt;! **This will contain presentations of each team, first discussion rounds with the mentors and both basic and more intermediate Python courses to help people that have worked with it a little or which transition from very decent skills in similar languages (we had a lot of people working with ‘R’ or MATLAB).&lt;/li&gt;
&lt;li&gt;Stimulate more interaction between the teams. **This might not be so simple since the teams came from widely different research fields and had different levels of computational skills, from programming beginners to software developers. During the workshop we had lunch together, we went out for drinks, and we had standup updates to report on what each team was busy with. Still, next time we hope to be able to include more moments for teams to interact and learn from what other teams have done.&lt;/li&gt;
&lt;li&gt;**Some technical stuff:We quickly realized that it was essential to have at least one big screen per team together with flip-charts or whiteboards. It was easy to fix, but next time I would try to arrange more screens and sketching options.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-this-was-part-22-have-a-look-at-part-12-to-see-what-teams-were-working-on-during-the-workshop&quot;&gt;→ This was part 2/2. **&lt;a href=&quot;https://blog2.esciencecenter.nl/workshop-machine-learning-for-research-2020-39c4fc8218e8&quot;&gt;&lt;strong&gt;Have a look at part 1/2 to see what teams were working on during the workshop.&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;</description><pubDate>Tue, 11 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;evaluating-our-one-week-hands-on-workshop-on-applying-machine-learning-to-research&quot;&gt;Evaluating our one-week hands-on workshop on applying machine learning to research.&lt;/h2&gt;
&lt;p&gt;5
Stimulate diverse teams and be aware of (gender-)biases.****We wanted to attract diverse teams and in particular avoid gender-biases since IT and machine-learning are (still) heavily male dominated. It is very easy to simply add a sentence saying that you welcome female participants, but that’s probably not going to do the job if the rest of the text is full of gender-coded works (“competitive”, “hacking”, …).&lt;/p&gt;
&lt;p&gt;There are apps to check your text for masculine-coded words (e.g. &lt;a href=&quot;http://gender-decoder.katmatfield.com/&quot;&gt;http://gender-decoder.katmatfield.com/&lt;/a&gt;), but they only cover a short list of words and don’t get the context. So they can primarily serve to give you an idea of how subtle things can be. More particularly, we avoided wording that could make the workshop sound competitive, which started with not officially calling it a hackathon**!&lt;/p&gt;
&lt;p&gt;Although we can’t prove this did the trick, I definitely think that the many discussions we had with a wide range of people about this subject before setting up the workshop really helped us a lot. And the outcome was great, too. Out of all the team members, **40% were female **(of 101 applicants in total). Among the selected teams we worked with during the workshop this number even went up to &lt;strong&gt;59% female participants&lt;/strong&gt; (of the final 27 participants).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labs.spotify.com/2015/01/13/diversify-how-we-created-a-hackathon-with-50-50-female-male-participants/&quot;&gt;(See also this blog post on hackathons with high female participant numbers)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;6**
Join forces with SURF.**** Not only did Maxwell Cai from SURF make a very valuable addition to our list of mentors (also giving an interesting introductory lecture on ML), we also benefited from the compute infrastructure provided by SURF. During the workshop, we had access to GPUs via simple Jupyter notebooks that we used intensively to train our deep learning models (for 4 teams using deep learning we had 8 GTX 1080Ti GPUs which was fully sufficient for the type of tasks we had).&lt;/p&gt;
&lt;h2 id=&quot;things-wed-like-to-improve&quot;&gt;Things we’d like to improve:&lt;/h2&gt;
&lt;p&gt;The positives notwithstanding, there is of course also a long list of things we can improve on. Luckily, most items on that list were clearly very minor issues. The more important lessons we learned were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better representation of some research field****There are disciplines within the humanities and social sciences where I believe machine learning can add a lot of value. Out of 25 applications, only 2 came from those fields. So next time we will certainly make an effort to better target humanities and social science research institutions.&lt;/li&gt;
&lt;li&gt;Extend the pre-workshop training.**&lt;strong&gt;We had thought about it and did offer a free one-day Python course in the week before the workshop, which indeed turned out to be very helpful. But to give participants with less coding experience and little to no prior Python experience a bit more time to prepare, it would be better to organize such a training a bit more in advance.
Next time we plan to add a separate onboarding day&lt;/strong&gt;! **This will contain presentations of each team, first discussion rounds with the mentors and both basic and more intermediate Python courses to help people that have worked with it a little or which transition from very decent skills in similar languages (we had a lot of people working with ‘R’ or MATLAB).&lt;/li&gt;
&lt;li&gt;Stimulate more interaction between the teams. **This might not be so simple since the teams came from widely different research fields and had different levels of computational skills, from programming beginners to software developers. During the workshop we had lunch together, we went out for drinks, and we had standup updates to report on what each team was busy with. Still, next time we hope to be able to include more moments for teams to interact and learn from what other teams have done.&lt;/li&gt;
&lt;li&gt;**Some technical stuff:We quickly realized that it was essential to have at least one big screen per team together with flip-charts or whiteboards. It was easy to fix, but next time I would try to arrange more screens and sketching options.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-this-was-part-22-have-a-look-at-part-12-to-see-what-teams-were-working-on-during-the-workshop&quot;&gt;→ This was part 2/2. **&lt;a href=&quot;https://blog2.esciencecenter.nl/workshop-machine-learning-for-research-2020-39c4fc8218e8&quot;&gt;&lt;strong&gt;Have a look at part 1/2 to see what teams were working on during the workshop.&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;</content:encoded><author>Florian Huber</author></item><item><title>Monopolizing AI</title><link>https://blog2.esciencecenter.nl/posts/2020-02-07---monopolizing-ai</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-02-07---monopolizing-ai</guid><description>&lt;h2 id=&quot;the-field-of-machine-learning-and-ai-is-facing-an-increasing-divide&quot;&gt;The field of machine learning and AI is facing an increasing divide.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Feb 4, 2020&lt;/p&gt;
&lt;p&gt;**16&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Last edit: 07/02/2020&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It seems contradictory at first. On the one hand, deep learning has become incredibly accessible. Few decades ago it was only used by a comparably small number of computer scientists, but nowadays there are plenty of free, easy-to-use, open-access tools and frameworks to build and train your own deep learning models. And the internet is flooded with (often free) online courses and tutorials from entry level to expert level, instructing people on how to make use of deep learning.&lt;/p&gt;
&lt;p&gt;But on the other hand, there also is an increasing sense of divide among many “ML practitioners”, i.e. the people that actually apply machine-learning or deep learning to uncountable problems in industry and academia. Or rather the people that* want* to apply those techniques. Because more and more frequently it turns out that the best-performing deep learning solutions are moving way beyond the data- and compute-budget of researchers or mid-sized companies.&lt;/p&gt;
&lt;h2 id=&quot;where-does-the-divide-come-from&quot;&gt;Where does the divide come from?&lt;/h2&gt;
&lt;p&gt;The great success of deep learning over the last decade is rooted in a combination of three factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ever-growing data sets.&lt;/li&gt;
&lt;li&gt;Heavily increased compute power (in particular around GPUs/TPUs which were discovered to be extremely well suited for deep learning).&lt;/li&gt;
&lt;li&gt;Development of novel deep neural network architectures. Together with discoveries of numerous new ‘tricks’ to deal with deeper and deeper networks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few years back, cutting-edge results in deep learning could often be achieved by training a cleverly chosen network architecture on a number of standard GPUs. However, already back then it became clear that if it comes to big data sets (for instance on images, text, or user behavior), the big tech companies were often playing in a different league. And this is not only because they collect more data, but also because they have the financial resources to properly label** much more data.&lt;/p&gt;
&lt;h2 id=&quot;transfer-learning-i̶s̶-was-able-to-bridge-the-gap&quot;&gt;Transfer learning i̶s̶ was able to bridge the gap&lt;/h2&gt;
&lt;p&gt;One could still argue that techniques such as transfer learning can democratize the resulting huge networks. Transfer learning refers to building models from pre-trained networks which are then adapted by retraining on the desired data. Often this means only retraining a small part of the network which requires far less compute power. Within only a few years, this approach has become widely used in many fields of machine learning.**&lt;/p&gt;
&lt;p&gt;The need for transfer learning started with the &lt;a href=&quot;https://paperswithcode.com/sota/image-classification-on-imagenet&quot;&gt;rise of deeper and deeper networks in computer vision&lt;/a&gt;. In 2015, for instance, Resnet-152, a deep learning network with 152 layers won the ImageNet competition &lt;a href=&quot;https://arxiv.org/abs/1512.03385&quot;&gt;[He et al., 2015]&lt;/a&gt;. Such types of networks are very expensive to retrain from scratch (and at times technically challenging). It has hence become common practice to simply import one of the current standard image-based networks and continue from there.&lt;/p&gt;
&lt;p&gt;More recently, the same development took place in the field of natural language processing (NLP). At least since 2019 with the rise of &lt;a href=&quot;https://ruder.io/state-of-transfer-learning-in-nlp/&quot;&gt;BERT and similar models&lt;/a&gt;, state-of-the-art performance is now often only achievable by re-using very large, pre-trained networks.&lt;/p&gt;
&lt;p&gt;Another less debated example is the famous AlphaGo Zero from DeepMind. This made the headlines in 2017 when it started to learn playing Go by self-play from scratch. Within 1.5 days AlphaGo Zero became stronger than any human player. 1.5 days on google infrastructure that is. Go and AI enthusiasts were keen on reproducing this success but realized that &lt;a href=&quot;http://computer-go.org/pipermail/computer-go/2017-October/010307.html&quot;&gt;it would take 1700 years to train on commodity hardware&lt;/a&gt;. That was followed by an unprecedented effort to join forces across a large online community and &lt;a href=&quot;https://github.com/leela-zero/leela-zero&quot;&gt;build a similar deep network as a distributed effort, Leela Zero&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Still fine one could say. As long as data and compute power remain at least accessible enough so that larger consortia, collectives, or institutions can retrain those models. But all signs point towards a very near future where even this criteria becomes increasingly difficult to meet. Last week &lt;a href=&quot;https://arxiv.org/abs/2001.09977&quot;&gt;a team from google published their results on a new chatbot, Meena&lt;/a&gt;. Their best model was trained on 2,048 TPU v3 cores for 30 days! Taking the current price on the google cloud of 1&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mn&gt;04&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;02&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2020&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;500&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;/hour for one TPU v3 core ([source: google cloud on 04/02/2020](https://cloud.google.com/tpu/pricing)), this corresponds to 1,500,000 &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;cor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;so&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ce&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;04/02/2020&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ttp&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;tp&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;scor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, hence by far exceeding what most institutions can afford to spend just for the final model training. The true number of core hours will of course be even larger if we imagine that many training runs are necessary to settle on the final architecture and hyper-parameters. And with more and more refined network architectures and training algorithms, we can expect even more expensive models to appear over the next few years (expensive in terms of budget and energy consumption).&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;I don’t see a simple remedy to ensure that the most powerful AI tools are not reserved to the few tech giants. One route certainly is the continuous improvement of deep learning algorithms with respect to their efficiency from an energy perspective (an emerging field now is “green AI”). Usually cleverer model architectures and training algorithms will allow for similar or better results with less training and less parameters. Examples from recent years here would be regularization techniques such as “dropout”, or a &lt;a href=&quot;https://timdettmers.com/2019/07/11/sparse-networks-from-scratch/&quot;&gt;trend to sparser networks&lt;/a&gt;. Unlikely that this would stop the success of computationally expensive, huge, brute-force networks anytime soon. But it might offer good options for following the state-of-the-art with some delay (maybe few years behind “cutting edge”).&lt;/p&gt;
&lt;p&gt;Another option worth considering in my eyes, is large-scale public investments in AI compute infrastructure. Say on national, or better even European scale. It would make me much less worried if we wouldn’t have to rely on google, facebook and Co. to release their newest models, and instead had powerful institutions that could provide the research community (and the public) with relevant large-scale models and compute power.&lt;/p&gt;
&lt;p&gt;In any case, I believe it is essential to watch this divide closely. Not only because it means that academia and the public risk being outpaced (and thereby potentially missing vital opportunities). I also believe it should be observed and interpreted in the light of what &lt;a href=&quot;https://en.wikipedia.org/wiki/Surveillance_capitalism&quot;&gt;Shoshana Zuboff termed “surveillance capitalism”,&lt;/a&gt; which points at a far bigger threat.&lt;/p&gt;
&lt;h3 id=&quot;resourceslinks&quot;&gt;Resources/links:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;“&lt;a href=&quot;https://arxiv.org/pdf/1906.02243.pdf&quot;&gt;Energy and Policy Considerations for Deep Learning in NLP&lt;/a&gt;” by Emma Strubell, Ananya Ganesh, and Andrew McCallum.
Great article on cloud compute costs and energy consumption of current state-of-the-art models.*&lt;/li&gt;
&lt;li&gt;Currently, there are many interesting research projects working on more efficient, more robust, more accessible deep learning techniques. One of them is &lt;a href=&quot;https://efficientdeeplearning.nl/&quot;&gt;efficientdeeplearning.nl&lt;/a&gt;, which also includes the eScience Center.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.publicaffairsbooks.com/titles/shoshana-zuboff/the-age-of-surveillance-capitalism/9781610395694&quot;&gt;“The Age of Surveillance Capitalism”&lt;/a&gt; by Shoshana Zuboff.
&lt;em&gt;Exciting book that adds another facet to the increasing agglomeration of behavioral data and compute power by the big tech companies.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Fri, 07 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-field-of-machine-learning-and-ai-is-facing-an-increasing-divide&quot;&gt;The field of machine learning and AI is facing an increasing divide.&lt;/h2&gt;
&lt;p&gt;][Florian Huber]·Feb 4, 2020&lt;/p&gt;
&lt;p&gt;**16&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Last edit: 07/02/2020&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It seems contradictory at first. On the one hand, deep learning has become incredibly accessible. Few decades ago it was only used by a comparably small number of computer scientists, but nowadays there are plenty of free, easy-to-use, open-access tools and frameworks to build and train your own deep learning models. And the internet is flooded with (often free) online courses and tutorials from entry level to expert level, instructing people on how to make use of deep learning.&lt;/p&gt;
&lt;p&gt;But on the other hand, there also is an increasing sense of divide among many “ML practitioners”, i.e. the people that actually apply machine-learning or deep learning to uncountable problems in industry and academia. Or rather the people that* want* to apply those techniques. Because more and more frequently it turns out that the best-performing deep learning solutions are moving way beyond the data- and compute-budget of researchers or mid-sized companies.&lt;/p&gt;
&lt;h2 id=&quot;where-does-the-divide-come-from&quot;&gt;Where does the divide come from?&lt;/h2&gt;
&lt;p&gt;The great success of deep learning over the last decade is rooted in a combination of three factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ever-growing data sets.&lt;/li&gt;
&lt;li&gt;Heavily increased compute power (in particular around GPUs/TPUs which were discovered to be extremely well suited for deep learning).&lt;/li&gt;
&lt;li&gt;Development of novel deep neural network architectures. Together with discoveries of numerous new ‘tricks’ to deal with deeper and deeper networks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few years back, cutting-edge results in deep learning could often be achieved by training a cleverly chosen network architecture on a number of standard GPUs. However, already back then it became clear that if it comes to big data sets (for instance on images, text, or user behavior), the big tech companies were often playing in a different league. And this is not only because they collect more data, but also because they have the financial resources to properly label** much more data.&lt;/p&gt;
&lt;h2 id=&quot;transfer-learning-i̶s̶-was-able-to-bridge-the-gap&quot;&gt;Transfer learning i̶s̶ was able to bridge the gap&lt;/h2&gt;
&lt;p&gt;One could still argue that techniques such as transfer learning can democratize the resulting huge networks. Transfer learning refers to building models from pre-trained networks which are then adapted by retraining on the desired data. Often this means only retraining a small part of the network which requires far less compute power. Within only a few years, this approach has become widely used in many fields of machine learning.**&lt;/p&gt;
&lt;p&gt;The need for transfer learning started with the &lt;a href=&quot;https://paperswithcode.com/sota/image-classification-on-imagenet&quot;&gt;rise of deeper and deeper networks in computer vision&lt;/a&gt;. In 2015, for instance, Resnet-152, a deep learning network with 152 layers won the ImageNet competition &lt;a href=&quot;https://arxiv.org/abs/1512.03385&quot;&gt;[He et al., 2015]&lt;/a&gt;. Such types of networks are very expensive to retrain from scratch (and at times technically challenging). It has hence become common practice to simply import one of the current standard image-based networks and continue from there.&lt;/p&gt;
&lt;p&gt;More recently, the same development took place in the field of natural language processing (NLP). At least since 2019 with the rise of &lt;a href=&quot;https://ruder.io/state-of-transfer-learning-in-nlp/&quot;&gt;BERT and similar models&lt;/a&gt;, state-of-the-art performance is now often only achievable by re-using very large, pre-trained networks.&lt;/p&gt;
&lt;p&gt;Another less debated example is the famous AlphaGo Zero from DeepMind. This made the headlines in 2017 when it started to learn playing Go by self-play from scratch. Within 1.5 days AlphaGo Zero became stronger than any human player. 1.5 days on google infrastructure that is. Go and AI enthusiasts were keen on reproducing this success but realized that &lt;a href=&quot;http://computer-go.org/pipermail/computer-go/2017-October/010307.html&quot;&gt;it would take 1700 years to train on commodity hardware&lt;/a&gt;. That was followed by an unprecedented effort to join forces across a large online community and &lt;a href=&quot;https://github.com/leela-zero/leela-zero&quot;&gt;build a similar deep network as a distributed effort, Leela Zero&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Still fine one could say. As long as data and compute power remain at least accessible enough so that larger consortia, collectives, or institutions can retrain those models. But all signs point towards a very near future where even this criteria becomes increasingly difficult to meet. Last week &lt;a href=&quot;https://arxiv.org/abs/2001.09977&quot;&gt;a team from google published their results on a new chatbot, Meena&lt;/a&gt;. Their best model was trained on 2,048 TPU v3 cores for 30 days! Taking the current price on the google cloud of 1&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;f&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;T&lt;/mi&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mi&gt;U&lt;/mi&gt;&lt;mi&gt;v&lt;/mi&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mn&gt;04&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;02&lt;/mn&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mn&gt;2020&lt;/mn&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mo&gt;:&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;.&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;u&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;h&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;500&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;000&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;/hour for one TPU v3 core ([source: google cloud on 04/02/2020](https://cloud.google.com/tpu/pricing)), this corresponds to 1,500,000 &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1076em;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.1389em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.109em;&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;cor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;so&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ce&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ec&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;04/02/2020&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;ttp&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;//&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;oo&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0197em;&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;co&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;tp&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0359em;&quot;&gt;g&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;scor&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;es&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, hence by far exceeding what most institutions can afford to spend just for the final model training. The true number of core hours will of course be even larger if we imagine that many training runs are necessary to settle on the final architecture and hyper-parameters. And with more and more refined network architectures and training algorithms, we can expect even more expensive models to appear over the next few years (expensive in terms of budget and energy consumption).&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;I don’t see a simple remedy to ensure that the most powerful AI tools are not reserved to the few tech giants. One route certainly is the continuous improvement of deep learning algorithms with respect to their efficiency from an energy perspective (an emerging field now is “green AI”). Usually cleverer model architectures and training algorithms will allow for similar or better results with less training and less parameters. Examples from recent years here would be regularization techniques such as “dropout”, or a &lt;a href=&quot;https://timdettmers.com/2019/07/11/sparse-networks-from-scratch/&quot;&gt;trend to sparser networks&lt;/a&gt;. Unlikely that this would stop the success of computationally expensive, huge, brute-force networks anytime soon. But it might offer good options for following the state-of-the-art with some delay (maybe few years behind “cutting edge”).&lt;/p&gt;
&lt;p&gt;Another option worth considering in my eyes, is large-scale public investments in AI compute infrastructure. Say on national, or better even European scale. It would make me much less worried if we wouldn’t have to rely on google, facebook and Co. to release their newest models, and instead had powerful institutions that could provide the research community (and the public) with relevant large-scale models and compute power.&lt;/p&gt;
&lt;p&gt;In any case, I believe it is essential to watch this divide closely. Not only because it means that academia and the public risk being outpaced (and thereby potentially missing vital opportunities). I also believe it should be observed and interpreted in the light of what &lt;a href=&quot;https://en.wikipedia.org/wiki/Surveillance_capitalism&quot;&gt;Shoshana Zuboff termed “surveillance capitalism”,&lt;/a&gt; which points at a far bigger threat.&lt;/p&gt;
&lt;h3 id=&quot;resourceslinks&quot;&gt;Resources/links:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;“&lt;a href=&quot;https://arxiv.org/pdf/1906.02243.pdf&quot;&gt;Energy and Policy Considerations for Deep Learning in NLP&lt;/a&gt;” by Emma Strubell, Ananya Ganesh, and Andrew McCallum.
Great article on cloud compute costs and energy consumption of current state-of-the-art models.*&lt;/li&gt;
&lt;li&gt;Currently, there are many interesting research projects working on more efficient, more robust, more accessible deep learning techniques. One of them is &lt;a href=&quot;https://efficientdeeplearning.nl/&quot;&gt;efficientdeeplearning.nl&lt;/a&gt;, which also includes the eScience Center.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.publicaffairsbooks.com/titles/shoshana-zuboff/the-age-of-surveillance-capitalism/9781610395694&quot;&gt;“The Age of Surveillance Capitalism”&lt;/a&gt; by Shoshana Zuboff.
&lt;em&gt;Exciting book that adds another facet to the increasing agglomeration of behavioral data and compute power by the big tech companies.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><author>Florian Huber</author></item><item><title>Environmental processes are linked, but how?</title><link>https://blog2.esciencecenter.nl/posts/2020-01-23---environmental-processes-are-linked-but-how</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-01-23---environmental-processes-are-linked-but-how</guid><description>&lt;p&gt;An introduction to copulas.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Climate Change Challenge Badge http://www.fao.org/publications/card/en/c/fd64a988-1439-4fc5-8ae5-cb6429f65192&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;489&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MWTDoObOSXfwg40FYLT84g-dfd3e472.DMwxqcij_Z1Ul3Np.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Climate change challenge badge, FAO&lt;/p&gt;
&lt;p&gt;Competition for natural resources such as water and land is increasing due to population growth, industrial development, agricultural intensification, and climate change. With respect to the latter, increasing variation in air temperature and precipitation affects agriculture (for instance crop production), contributing to risks for food security. When studying the crop responses to those changes, the aim is to answer questions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do warm days in one location affect the weather in another location?&lt;/li&gt;
&lt;li&gt;If the days are very wet over the last months, will the next month be the same?&lt;/li&gt;
&lt;li&gt;Do cold days increase crop production?&lt;/li&gt;
&lt;li&gt;Will the production price increase in the next ten years due to a heatwave?&lt;/li&gt;
&lt;li&gt;What is the probability of a flood in one location on a specific day in a year?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We know that weather, land and water change continuously over space and time. The changes in one are related to changes in the other. The main aspect of recent environmental studies has been to describe those variations and interactions.&lt;/p&gt;
&lt;h3 id=&quot;how-to-describe-interactions&quot;&gt;How to describe interactions&lt;/h3&gt;
&lt;p&gt;For a moment assume one pair of processes that are linked together, such as crop production and air temperature. We want to describe their dependence, that is how they are connected. To do so, one way is to use a function. In 1959, the mathematician Abe Sklar called this function a copula. The name copula comes from the Latin for link or tie. A copula is a bi-variate function (including two variables or processes) that shows, for example, how the crop production is related to the air temperature.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;405&quot; height=&quot;390&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_P86dff9vP6dGZ7AZjVWPWA-819392fc.BvpYtk-C_26orEM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Graph of a copula /kɒpjʊlə/&lt;/p&gt;
&lt;p&gt;Now let’s assume more processes like crop production, air temperature, and rainfall. We can define a multivariate function (including more than two processes) that describes the link between those processes.&lt;/p&gt;
&lt;h3 id=&quot;the-type-of-functions-of-a-copula&quot;&gt;The type of functions of a copula&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;399&quot; height=&quot;383&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LzkKah0q4yuL1bHIIcMxvA-1d1e0957.nFX6nVJi_1P1Iji.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A copula is a joint probability distribution function ( Nelsen 2006 ). In this graph, the function C(.,.) is a copula, x and y axes denote two processes whereas the z-axis indicates the joint probability values.&lt;/p&gt;
&lt;p&gt;In probability, a joint probability distribution is a function describing the probability of processes that happen together. A copula is a joint probability distribution function.&lt;/p&gt;
&lt;h3 id=&quot;the-power-of-copula-based-methods&quot;&gt;The power of copula-based methods&lt;/h3&gt;
&lt;p&gt;Nowadays copula is famous in addressing financial problems. However, it is still in its infancy in environmental science. The findings on the application of copulas indicate that copula-based methods can be used for several types of data sets and problems. Therefore, there is a growing interest in the use of copulas in hydrology, disaster management, agriculture, weather, and climate. In this context, copulas have great potential for describing complex dependencies found in, for example, wicked problems like climate change and heatwaves. With this in mind, case studies and functions developed in recent copula-based studies could have a role to play in new areas, for instance, methodological development, promising application, and education.&lt;/p&gt;
&lt;h3 id=&quot;the-weakness-of-copula-based-methods&quot;&gt;The weakness of copula-based methods&lt;/h3&gt;
&lt;p&gt;One concern about the application of copulas is that available software are limited to a few packages mostly in R programming language. Also, the computational cost of copula-based methods when working with high-dimensional problems is relatively great. Regarding the environmental processes, the application of copulas faces a limitation that emerges from the problems related to the visualizations and interpretations in a high-dimensional space.&lt;/p&gt;
&lt;p&gt;More about copulas? I recommend the following references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://link.springer.com/book/10.1007%2F978-1-4757-3076-0&quot;&gt;An Introduction to Copulas.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://link.springer.com/book/10.1007%2F1-4020-4415-1&quot;&gt;Extremes In Nature: An Approach Using Copulas.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.1061/(ASCE)1084-0699(2007)12:4(347)&quot;&gt;Everything You Always Wanted to Know about Copula Modeling but Were Afraid to Ask&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 23 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;An introduction to copulas.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Climate Change Challenge Badge http://www.fao.org/publications/card/en/c/fd64a988-1439-4fc5-8ae5-cb6429f65192&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;489&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MWTDoObOSXfwg40FYLT84g-dfd3e472.DMwxqcij_Z1Ul3Np.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Climate change challenge badge, FAO&lt;/p&gt;
&lt;p&gt;Competition for natural resources such as water and land is increasing due to population growth, industrial development, agricultural intensification, and climate change. With respect to the latter, increasing variation in air temperature and precipitation affects agriculture (for instance crop production), contributing to risks for food security. When studying the crop responses to those changes, the aim is to answer questions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How do warm days in one location affect the weather in another location?&lt;/li&gt;
&lt;li&gt;If the days are very wet over the last months, will the next month be the same?&lt;/li&gt;
&lt;li&gt;Do cold days increase crop production?&lt;/li&gt;
&lt;li&gt;Will the production price increase in the next ten years due to a heatwave?&lt;/li&gt;
&lt;li&gt;What is the probability of a flood in one location on a specific day in a year?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We know that weather, land and water change continuously over space and time. The changes in one are related to changes in the other. The main aspect of recent environmental studies has been to describe those variations and interactions.&lt;/p&gt;
&lt;h3 id=&quot;how-to-describe-interactions&quot;&gt;How to describe interactions&lt;/h3&gt;
&lt;p&gt;For a moment assume one pair of processes that are linked together, such as crop production and air temperature. We want to describe their dependence, that is how they are connected. To do so, one way is to use a function. In 1959, the mathematician Abe Sklar called this function a copula. The name copula comes from the Latin for link or tie. A copula is a bi-variate function (including two variables or processes) that shows, for example, how the crop production is related to the air temperature.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;405&quot; height=&quot;390&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_P86dff9vP6dGZ7AZjVWPWA-819392fc.BvpYtk-C_26orEM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Graph of a copula /kɒpjʊlə/&lt;/p&gt;
&lt;p&gt;Now let’s assume more processes like crop production, air temperature, and rainfall. We can define a multivariate function (including more than two processes) that describes the link between those processes.&lt;/p&gt;
&lt;h3 id=&quot;the-type-of-functions-of-a-copula&quot;&gt;The type of functions of a copula&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;399&quot; height=&quot;383&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LzkKah0q4yuL1bHIIcMxvA-1d1e0957.nFX6nVJi_1P1Iji.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A copula is a joint probability distribution function ( Nelsen 2006 ). In this graph, the function C(.,.) is a copula, x and y axes denote two processes whereas the z-axis indicates the joint probability values.&lt;/p&gt;
&lt;p&gt;In probability, a joint probability distribution is a function describing the probability of processes that happen together. A copula is a joint probability distribution function.&lt;/p&gt;
&lt;h3 id=&quot;the-power-of-copula-based-methods&quot;&gt;The power of copula-based methods&lt;/h3&gt;
&lt;p&gt;Nowadays copula is famous in addressing financial problems. However, it is still in its infancy in environmental science. The findings on the application of copulas indicate that copula-based methods can be used for several types of data sets and problems. Therefore, there is a growing interest in the use of copulas in hydrology, disaster management, agriculture, weather, and climate. In this context, copulas have great potential for describing complex dependencies found in, for example, wicked problems like climate change and heatwaves. With this in mind, case studies and functions developed in recent copula-based studies could have a role to play in new areas, for instance, methodological development, promising application, and education.&lt;/p&gt;
&lt;h3 id=&quot;the-weakness-of-copula-based-methods&quot;&gt;The weakness of copula-based methods&lt;/h3&gt;
&lt;p&gt;One concern about the application of copulas is that available software are limited to a few packages mostly in R programming language. Also, the computational cost of copula-based methods when working with high-dimensional problems is relatively great. Regarding the environmental processes, the application of copulas faces a limitation that emerges from the problems related to the visualizations and interpretations in a high-dimensional space.&lt;/p&gt;
&lt;p&gt;More about copulas? I recommend the following references:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://link.springer.com/book/10.1007%2F978-1-4757-3076-0&quot;&gt;An Introduction to Copulas.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://link.springer.com/book/10.1007%2F1-4020-4415-1&quot;&gt;Extremes In Nature: An Approach Using Copulas.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doi.org/10.1061/(ASCE)1084-0699(2007)12:4(347)&quot;&gt;Everything You Always Wanted to Know about Copula Modeling but Were Afraid to Ask&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_P86dff9vP6dGZ7AZjVWPWA-819392fc.BvpYtk-C.png" medium="image"/><author>Fakhereh (Sarah) Alidoost</author></item><item><title>Parallel programming in Python</title><link>https://blog2.esciencecenter.nl/posts/2020-01-16---parallel-programming-in-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-01-16---parallel-programming-in-python</guid><description>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Depending on your level of Python expertise, you might implement such an algorithm in different ways.&lt;/p&gt;
&lt;p&gt;In an introductory Python course we could write this function as follows.&lt;/p&gt;
&lt;p&gt;import randomdef calc_pi(N):
M = 0  for i in range(N):
# Simulate impact coordinates
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# True if impact happens inside the circle &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if x**2 + y**2 &amp;#x26;lt; 1.0:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  M += 1  return 4 * M / NThis implementation has serious shortcomings when it comes to performance. We learn how to fix this in the second week of learning Python, when we encounter NumPy! We show here another way of implementing the same idea. In this case we are taking advantage of NumPy’s recommended vector notation. Used smartly, it avoids the need of for loops.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;import numpy as npdef calc_pi_numpy(N):&lt;/p&gt;
&lt;h1 id=&quot;simulate-impact-coordinates&quot;&gt;Simulate impact coordinates&lt;/h1&gt;
&lt;p&gt;pts = np.random.uniform(-1, 1, (2, N))  # Count number of impacts inside the circle
M = np.count_nonzero((pts**2).sum(axis=0) &amp;#x3C; 1)  return 4 * M / NThis implementation is a lot faster than the first one, but it still only uses a single processor. Surely, we can do better than that! We can parallelize this algorithm by running it several times and then computing the mean of the outputs.&lt;/p&gt;
&lt;p&gt;The problem of computing π is representative of a family of problems known as embarrassingly parallel**. Roughly, this means that parallelizing the algorithm &lt;a href=&quot;https://en.wikipedia.org/wiki/Embarrassingly_parallel&quot;&gt;should be easy&lt;/a&gt;. If we want to use, say, 80000 random points, and we have 8 cores, we can split our problem in 8 problems of 10000 points each. This will give 8 different results, that we will collect together using a mean.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Parallel programming in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;501&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/parallel-programming-in-python-7a254843.B9uASILu_Z2cAW7g.webp&quot; srcset=&quot;&quot;&gt;
The GIL&lt;/p&gt;
&lt;h2 id=&quot;the-gil&quot;&gt;The GIL&lt;/h2&gt;
&lt;p&gt;There are many ways of parallelizing programs in Python, but not many of them are actually very good for problems like this. The reason is the Global Interpreter Lock or GIL. The GIL is infamous for killing any naive attempts at parallel programming in Python in its tracks.&lt;/p&gt;
&lt;p&gt;The designers of Python chose ease-of-use over the use of power, a design principle that is in part responsible for the popularity of the language today. In the case of the GIL this means that any operation that requires interaction with the Python interpreter is locked to what is effectively a single thread. Multi-threading in Python is useful only for doing IO operations or native function calls that resolve outside the ever present eye of the Python interpreter. There are two solutions to this problem: running multiple Python instances or doing all of your work outside of Python.&lt;/p&gt;
&lt;p&gt;For a lot of small-scale parallel work, running multiple instances of Python is not a very good solution: there is the overhead of copying data between the different Python instances. We can do better than this! &lt;strong&gt;What if we just kill the GIL?&lt;/strong&gt; We’ll see soon that the package Numba allows us to do it easily by just using a decorator in our function. We can then use any other tool for parallelizing Python to run the algorithm in parallel, in this case: Dask.&lt;/p&gt;
&lt;p&gt;One way of using Dask is through its NumPy-esque &lt;code&gt;daskarray&lt;/code&gt; interface. This will give some speedup because the underlying NumPy routines are not choked by the GIL. However, we can do a lot better if we eliminate the GIL entirely using Numba.&lt;/p&gt;
&lt;h2 id=&quot;lets-do-it&quot;&gt;Let’s do it&lt;/h2&gt;
&lt;p&gt;First, we want to know how many cores we have. In Python this can be easily figured out easily using the multiprocessing package:&lt;/p&gt;
&lt;p&gt;import multiprocessing
ncpus = multiprocessing.cpu_count()
print(“We have {} cores to work on!”.format(ncpus))Now, we use Numba to comfortably avoid the GIL by simply using the &lt;code&gt;@jit&lt;/code&gt; decorator around our function. Numba compiles the Python code to native machine code to make it perform faster. We have to forget what we learned about using NumPy here.&lt;/p&gt;
&lt;p&gt;from numba import jit@jit(nopython=True, nogil=True) # Required to kill the GIL
def calc_pi_nogil(N):
M = 0  for i in range(N):
# Simulate impact coordinates
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# True if impact happens inside the circle &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if x**2 + y**2 &amp;#x26;lt; 1.0:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  M += 1  return 4 * M / NIronically, our implementation is identical to the first very slow Python version, with the exception of the `@jit` line!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We set out multiple jobs for computing π and take the mean of the results.&lt;/p&gt;
&lt;p&gt;from dask import delayed@delayed
def mean(&lt;em&gt;args):
return sum(args) / len(args)# Call calc_pi_nogil 10 times with N = 10 million
x = mean(&lt;/em&gt;(delayed(calc_pi_nogil)(10**7) for i in range(10)))The workflow can be visualized using:&lt;/p&gt;
&lt;p&gt;x.visualize()
&lt;img alt=&quot;Parallel programming in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;335&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/parallel-programming-in-python-8c13deee.C5xqKtdm_ZHRr0.webp&quot; srcset=&quot;&quot;&gt;
A recipe for computing π fasterAnd evaluated using:&lt;/p&gt;
&lt;p&gt;x.compute()Try it out yourself! Fire up a Jupyter notebook, &lt;code&gt;pip install dask numba&lt;/code&gt;, and you’re good to go.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Erratum 2020/01/16: There are some issues with the code presented in this post, these are largely due to Medium replacing double quotes with unicode characters. A functioning example code is available in this Gist:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/jhidding/e08c3096b5c54bf2138ca248625de029&quot;&gt;https://gist.github.com/jhidding/e08c3096b5c54bf2138ca248625de029&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 16 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;**SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;Depending on your level of Python expertise, you might implement such an algorithm in different ways.&lt;/p&gt;
&lt;p&gt;In an introductory Python course we could write this function as follows.&lt;/p&gt;
&lt;p&gt;import randomdef calc_pi(N):
M = 0  for i in range(N):
# Simulate impact coordinates
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# True if impact happens inside the circle &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if x**2 + y**2 &amp;#x26;lt; 1.0:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  M += 1  return 4 * M / NThis implementation has serious shortcomings when it comes to performance. We learn how to fix this in the second week of learning Python, when we encounter NumPy! We show here another way of implementing the same idea. In this case we are taking advantage of NumPy’s recommended vector notation. Used smartly, it avoids the need of for loops.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;import numpy as npdef calc_pi_numpy(N):&lt;/p&gt;
&lt;h1 id=&quot;simulate-impact-coordinates&quot;&gt;Simulate impact coordinates&lt;/h1&gt;
&lt;p&gt;pts = np.random.uniform(-1, 1, (2, N))  # Count number of impacts inside the circle
M = np.count_nonzero((pts**2).sum(axis=0) &amp;#x3C; 1)  return 4 * M / NThis implementation is a lot faster than the first one, but it still only uses a single processor. Surely, we can do better than that! We can parallelize this algorithm by running it several times and then computing the mean of the outputs.&lt;/p&gt;
&lt;p&gt;The problem of computing π is representative of a family of problems known as embarrassingly parallel**. Roughly, this means that parallelizing the algorithm &lt;a href=&quot;https://en.wikipedia.org/wiki/Embarrassingly_parallel&quot;&gt;should be easy&lt;/a&gt;. If we want to use, say, 80000 random points, and we have 8 cores, we can split our problem in 8 problems of 10000 points each. This will give 8 different results, that we will collect together using a mean.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Parallel programming in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;501&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/parallel-programming-in-python-7a254843.B9uASILu_Z2cAW7g.webp&quot; srcset=&quot;&quot;&gt;
The GIL&lt;/p&gt;
&lt;h2 id=&quot;the-gil&quot;&gt;The GIL&lt;/h2&gt;
&lt;p&gt;There are many ways of parallelizing programs in Python, but not many of them are actually very good for problems like this. The reason is the Global Interpreter Lock or GIL. The GIL is infamous for killing any naive attempts at parallel programming in Python in its tracks.&lt;/p&gt;
&lt;p&gt;The designers of Python chose ease-of-use over the use of power, a design principle that is in part responsible for the popularity of the language today. In the case of the GIL this means that any operation that requires interaction with the Python interpreter is locked to what is effectively a single thread. Multi-threading in Python is useful only for doing IO operations or native function calls that resolve outside the ever present eye of the Python interpreter. There are two solutions to this problem: running multiple Python instances or doing all of your work outside of Python.&lt;/p&gt;
&lt;p&gt;For a lot of small-scale parallel work, running multiple instances of Python is not a very good solution: there is the overhead of copying data between the different Python instances. We can do better than this! &lt;strong&gt;What if we just kill the GIL?&lt;/strong&gt; We’ll see soon that the package Numba allows us to do it easily by just using a decorator in our function. We can then use any other tool for parallelizing Python to run the algorithm in parallel, in this case: Dask.&lt;/p&gt;
&lt;p&gt;One way of using Dask is through its NumPy-esque &lt;code&gt;daskarray&lt;/code&gt; interface. This will give some speedup because the underlying NumPy routines are not choked by the GIL. However, we can do a lot better if we eliminate the GIL entirely using Numba.&lt;/p&gt;
&lt;h2 id=&quot;lets-do-it&quot;&gt;Let’s do it&lt;/h2&gt;
&lt;p&gt;First, we want to know how many cores we have. In Python this can be easily figured out easily using the multiprocessing package:&lt;/p&gt;
&lt;p&gt;import multiprocessing
ncpus = multiprocessing.cpu_count()
print(“We have {} cores to work on!”.format(ncpus))Now, we use Numba to comfortably avoid the GIL by simply using the &lt;code&gt;@jit&lt;/code&gt; decorator around our function. Numba compiles the Python code to native machine code to make it perform faster. We have to forget what we learned about using NumPy here.&lt;/p&gt;
&lt;p&gt;from numba import jit@jit(nopython=True, nogil=True) # Required to kill the GIL
def calc_pi_nogil(N):
M = 0  for i in range(N):
# Simulate impact coordinates
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# True if impact happens inside the circle &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;if x**2 + y**2 &amp;#x26;lt; 1.0:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  M += 1  return 4 * M / NIronically, our implementation is identical to the first very slow Python version, with the exception of the `@jit` line!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We set out multiple jobs for computing π and take the mean of the results.&lt;/p&gt;
&lt;p&gt;from dask import delayed@delayed
def mean(&lt;em&gt;args):
return sum(args) / len(args)# Call calc_pi_nogil 10 times with N = 10 million
x = mean(&lt;/em&gt;(delayed(calc_pi_nogil)(10**7) for i in range(10)))The workflow can be visualized using:&lt;/p&gt;
&lt;p&gt;x.visualize()
&lt;img alt=&quot;Parallel programming in Python&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;335&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/parallel-programming-in-python-8c13deee.C5xqKtdm_ZHRr0.webp&quot; srcset=&quot;&quot;&gt;
A recipe for computing π fasterAnd evaluated using:&lt;/p&gt;
&lt;p&gt;x.compute()Try it out yourself! Fire up a Jupyter notebook, &lt;code&gt;pip install dask numba&lt;/code&gt;, and you’re good to go.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;Erratum 2020/01/16: There are some issues with the code presented in this post, these are largely due to Medium replacing double quotes with unicode characters. A functioning example code is available in this Gist:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/jhidding/e08c3096b5c54bf2138ca248625de029&quot;&gt;https://gist.github.com/jhidding/e08c3096b5c54bf2138ca248625de029&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/parallel-programming-in-python-7a254843.B9uASILu.jpeg" medium="image"/><author>Johan Hidding</author></item><item><title>Some things that scientists can learn from the arts</title><link>https://blog2.esciencecenter.nl/posts/2020-01-08---some-things-that-scientists-can-learn-from-the-arts</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2020-01-08---some-things-that-scientists-can-learn-from-the-arts</guid><description>&lt;p&gt;Artists and scientists have more in common than you may think&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2340&quot; height=&quot;3292&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZeyQS1ahBIX8YP6nFtg4AQ-e8b08ca4.iNp615uh_ZQFFT7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ascidiacea (1899) by Dr. Ernst Haeckel via Wikipedia&lt;/p&gt;
&lt;p&gt;Knowledge isn’t easy to classify. Where does mathematics finish and physics begin? What about the boundary between biology and chemistry? After all, our taxonomy of knowledge is more a practical than a descriptive one: it allows us to compose the academic syllabi with something more detailed and informative than &lt;em&gt;knowledge 101&lt;/em&gt;, &lt;em&gt;knowledge 102&lt;/em&gt;, and so on.&lt;/p&gt;
&lt;p&gt;While some boundaries between disciplines are fuzzy, others seem to be crystal clear. One of the less disputed ones is that between arts and sciences. The difference seems to be so clear that artists and scientists are often presented as opposite and even irreconcilable characters. But this border is also diffuse and permeable. A lot has been said, for instance, about the contribution of science to the arts through new materials and technologies, and arts are often mentioned as a source of inspiration for science.&lt;/p&gt;
&lt;p&gt;And therein lies the rub. All that talk about “inspiration” sounds subtle, almost esoteric, and many scientists will raise their eyebrows when hearing about it. But what if I tell you that during my (still young) scientific career I’ve found that the arts, apart from being pleasant and enjoyable, have provided me with some useful tools for my everyday work as a scientist.&lt;/p&gt;
&lt;p&gt;With this small list, I hope to convince even the most pragmatic of readers.&lt;/p&gt;
&lt;h2 id=&quot;literature&quot;&gt;Literature&lt;/h2&gt;
&lt;p&gt;Writing is one of the main activities of any scientific researcher. Basic knowledge of different writing styles and strategies can be very useful. It is true that scientific publications tend to use a very odd style (so odd that sometimes it is hard to believe that they have been written by a human being). Very often the scientific writer is forced to follow this odd style, why then learn about different writing styles?&lt;/p&gt;
&lt;p&gt;Well, for a start, scientists write more than papers. They also compose emails, press releases, blogs, posters… Each of these formats has its own style. Strange things may happen when the “scientific paper style” is used for something else, such as a &lt;a href=&quot;https://www.huffpost.com/entry/geeky-marriage-proposal_n_2761709?guccounter=1&amp;#x26;guce_referrer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8&amp;#x26;guce_referrer_sig=AQAAAFlKdqhByeG0BaadlR9__fDH3cDF6j81WUe-jqjQi-iet_Sqq6fNeUaLlRWDACCf2t6rjDOVdTKeSCKYeqm_6i_45pr2yrO3HMDiEs-URvC6GnCfAWC6sA-RGG9R1GXfjtBnT0_VeCSlY3CPqGJZPYUgkBR2tgxOavE13VndDb79&quot;&gt;marriage proposal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;821&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wNaFhH5r5r7f0FL1-89ccb634.q6TGNtP2_27hGDE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Alfons Morales on Unsplash&lt;/p&gt;
&lt;p&gt;The best way of improving your writing style is to read people who write well. A very pleasant way indeed.&lt;/p&gt;
&lt;h2 id=&quot;performing-arts&quot;&gt;Performing arts&lt;/h2&gt;
&lt;p&gt;Think of a scientific conference you’ve recently attended. Ask yourself how many talks you remember and why. Very often, your memory will be triggered by something not fundamental to the talk, such as a great explanation of a known concept or a really funny joke.&lt;/p&gt;
&lt;p&gt;In any talk, the presenter’s speaking skills are as relevant as the content itself. A talk with good content but filled with hesitation and anxiety can become almost painful to watch for the audience. On the other hand, a talk with more humble contents but with a brilliant speaker will (at least) be remembered when the congress finishes.&lt;/p&gt;
&lt;p&gt;Not paying attention to the cues of the audience, being unable to dynamically adapt the relative importance of each section, speaking too softly or being long-winded, all of these are subtle details that can ruin a talk within minutes.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_h8NCn48fImZc2jpK-7440d9a4.C_i81zZX_oeVQM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Matthias Wagner on Unsplash&lt;/p&gt;
&lt;p&gt;Some basic notions of theater, storytelling, timing and audience engagement (magic is great for this) can be very helpful.&lt;/p&gt;
&lt;p&gt;To quoting The Simpsons: “Every good scientist is half &lt;a href=&quot;https://en.wikipedia.org/wiki/B._F._Skinner&quot;&gt;B. F. Skinner&lt;/a&gt; and half &lt;a href=&quot;https://es.wikipedia.org/wiki/P._T._Barnum&quot;&gt;P. T. Barnum&lt;/a&gt;.”&lt;/p&gt;
&lt;h2 id=&quot;graphic-design&quot;&gt;Graphic design&lt;/h2&gt;
&lt;p&gt;Do you know what a graphic designer’s worst nightmare is? To be locked in a room during a scientific poster session. Slides can also be quite terrifying for them.&lt;/p&gt;
&lt;p&gt;Scientists use visual tools all the time. Figures, plots, tables — not to mention there are even artistic sub-genres such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Technical_illustration&quot;&gt;technical&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Biological_illustration&quot;&gt;naturalist illustration&lt;/a&gt;. But scientists rarely receive specific training in the appropriate use of these visual tools.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;641&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PuWjAi9qh5p_s4InUMmn_w-a49f47a1.Bwk7ayQF_1afUjp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Punica granatum, by Prof. Dr. Otto Wilhelm Thomé (1885)&lt;/p&gt;
&lt;p&gt;Most people (and scientists are no exception) don’t know that there are certain rules about design. Some of them are subtle, such as not using the same figures in a paper and in a poster or slides (each format should be read from a different distance, and with a different level of attention). Others are well known, but very often broken for no good reason (such as minimizing the use of text or using a proper font size). Last but not least, there are mistakes so obvious that it is surprising they still persist (such as using crazy color combinations or adding a slide with 25 references… that will remain on screen for 3 seconds).&lt;/p&gt;
&lt;p&gt;A personal tip: a few years ago, I collaborated with the human resources department of a tech company. We spent several days reading the curricula of mathematicians, physicists and engineers. I cannot stress enough the strategic advantage of having an aesthetically, well-designed curriculum.&lt;/p&gt;
&lt;p&gt;Spending some time learning the basics of visual communication will definitely pay off.&lt;/p&gt;
&lt;h2 id=&quot;understanding-creativity&quot;&gt;Understanding creativity&lt;/h2&gt;
&lt;p&gt;Another shared feature of scientists and artists is that they both have creative jobs.&lt;/p&gt;
&lt;p&gt;Understanding how creative processes work is more complicated than it may seem. We, scientists, tend to struggle with the fact that hitting our head against a problem when we are blocked rarely gives any result. Even worse, it is usually counterproductive. Often, the best way to find a solution is to explore alternative paths, or even abandon the lab and go for a walk, do some sports or just have a beer.&lt;/p&gt;
&lt;p&gt;In the world of arts, traditionally more bohemian, everybody is aware of this. To the point that, for instance, some design agencies implement protocols to guarantee that several options are always explored before choosing one at the beginning of a project.&lt;/p&gt;
&lt;p&gt;And that’s it for now. Feel free to add your own experiences in the comments section below.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The craft of scientific writing. Michael Alley.&lt;/li&gt;
&lt;li&gt;The craft of scientific presentations. Michael Alley.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=fDzGkD9QqD8&amp;#x26;feature=youtu.be&quot;&gt;The art and science of data visualization&lt;/a&gt;, Moritz Stefaner&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nature.com/articles/d41586-019-01431-z?utm_source=Nature+Briefing&amp;#x26;utm_campaign=9c58c75666-briefing-dy-wk-20200102&amp;#x26;utm_medium=email&amp;#x26;utm_term=0_c9dfd39373-9c58c75666-42144719&quot;&gt;How small changes to a paper can help to smooth the review process&lt;/a&gt;. Nature&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nature.com/articles/d41586-019-02918-5?utm_source=Nature+Briefing&amp;#x26;utm_campaign=9c58c75666-briefing-dy-wk-20200102&amp;#x26;utm_medium=email&amp;#x26;utm_term=0_c9dfd39373-9c58c75666-42144719&quot;&gt;Novelist Cormac McCarthy’s tips on how to write a great science paper&lt;/a&gt;. Nature&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://well.blogs.nytimes.com/2014/04/30/want-to-be-more-creative-take-a-walk/?ref=health&quot;&gt;Want to be More Creative? Take a Walk.&lt;/a&gt; Gretchen Reynolds. &lt;em&gt;The New York Times.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sciencedaily.com/releases/2014/07/140721142211.htm&quot;&gt;Try, try again? Study says no: Trying harder makes it more difficult to learn some aspects of language, neuroscientists find.&lt;/a&gt;Anne Trafton. &lt;em&gt;Science daily.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This blog entry is adapted from its Spanish version, that appeared first in&lt;/em&gt; &lt;a href=&quot;https://fuga.naukas.com/2017/12/12/cosas-ciencia-artes/&quot;&gt;&lt;em&gt;Naukas&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Wed, 08 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Artists and scientists have more in common than you may think&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2340&quot; height=&quot;3292&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZeyQS1ahBIX8YP6nFtg4AQ-e8b08ca4.iNp615uh_ZQFFT7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ascidiacea (1899) by Dr. Ernst Haeckel via Wikipedia&lt;/p&gt;
&lt;p&gt;Knowledge isn’t easy to classify. Where does mathematics finish and physics begin? What about the boundary between biology and chemistry? After all, our taxonomy of knowledge is more a practical than a descriptive one: it allows us to compose the academic syllabi with something more detailed and informative than &lt;em&gt;knowledge 101&lt;/em&gt;, &lt;em&gt;knowledge 102&lt;/em&gt;, and so on.&lt;/p&gt;
&lt;p&gt;While some boundaries between disciplines are fuzzy, others seem to be crystal clear. One of the less disputed ones is that between arts and sciences. The difference seems to be so clear that artists and scientists are often presented as opposite and even irreconcilable characters. But this border is also diffuse and permeable. A lot has been said, for instance, about the contribution of science to the arts through new materials and technologies, and arts are often mentioned as a source of inspiration for science.&lt;/p&gt;
&lt;p&gt;And therein lies the rub. All that talk about “inspiration” sounds subtle, almost esoteric, and many scientists will raise their eyebrows when hearing about it. But what if I tell you that during my (still young) scientific career I’ve found that the arts, apart from being pleasant and enjoyable, have provided me with some useful tools for my everyday work as a scientist.&lt;/p&gt;
&lt;p&gt;With this small list, I hope to convince even the most pragmatic of readers.&lt;/p&gt;
&lt;h2 id=&quot;literature&quot;&gt;Literature&lt;/h2&gt;
&lt;p&gt;Writing is one of the main activities of any scientific researcher. Basic knowledge of different writing styles and strategies can be very useful. It is true that scientific publications tend to use a very odd style (so odd that sometimes it is hard to believe that they have been written by a human being). Very often the scientific writer is forced to follow this odd style, why then learn about different writing styles?&lt;/p&gt;
&lt;p&gt;Well, for a start, scientists write more than papers. They also compose emails, press releases, blogs, posters… Each of these formats has its own style. Strange things may happen when the “scientific paper style” is used for something else, such as a &lt;a href=&quot;https://www.huffpost.com/entry/geeky-marriage-proposal_n_2761709?guccounter=1&amp;#x26;guce_referrer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8&amp;#x26;guce_referrer_sig=AQAAAFlKdqhByeG0BaadlR9__fDH3cDF6j81WUe-jqjQi-iet_Sqq6fNeUaLlRWDACCf2t6rjDOVdTKeSCKYeqm_6i_45pr2yrO3HMDiEs-URvC6GnCfAWC6sA-RGG9R1GXfjtBnT0_VeCSlY3CPqGJZPYUgkBR2tgxOavE13VndDb79&quot;&gt;marriage proposal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;821&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wNaFhH5r5r7f0FL1-89ccb634.q6TGNtP2_27hGDE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Alfons Morales on Unsplash&lt;/p&gt;
&lt;p&gt;The best way of improving your writing style is to read people who write well. A very pleasant way indeed.&lt;/p&gt;
&lt;h2 id=&quot;performing-arts&quot;&gt;Performing arts&lt;/h2&gt;
&lt;p&gt;Think of a scientific conference you’ve recently attended. Ask yourself how many talks you remember and why. Very often, your memory will be triggered by something not fundamental to the talk, such as a great explanation of a known concept or a really funny joke.&lt;/p&gt;
&lt;p&gt;In any talk, the presenter’s speaking skills are as relevant as the content itself. A talk with good content but filled with hesitation and anxiety can become almost painful to watch for the audience. On the other hand, a talk with more humble contents but with a brilliant speaker will (at least) be remembered when the congress finishes.&lt;/p&gt;
&lt;p&gt;Not paying attention to the cues of the audience, being unable to dynamically adapt the relative importance of each section, speaking too softly or being long-winded, all of these are subtle details that can ruin a talk within minutes.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_h8NCn48fImZc2jpK-7440d9a4.C_i81zZX_oeVQM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Matthias Wagner on Unsplash&lt;/p&gt;
&lt;p&gt;Some basic notions of theater, storytelling, timing and audience engagement (magic is great for this) can be very helpful.&lt;/p&gt;
&lt;p&gt;To quoting The Simpsons: “Every good scientist is half &lt;a href=&quot;https://en.wikipedia.org/wiki/B._F._Skinner&quot;&gt;B. F. Skinner&lt;/a&gt; and half &lt;a href=&quot;https://es.wikipedia.org/wiki/P._T._Barnum&quot;&gt;P. T. Barnum&lt;/a&gt;.”&lt;/p&gt;
&lt;h2 id=&quot;graphic-design&quot;&gt;Graphic design&lt;/h2&gt;
&lt;p&gt;Do you know what a graphic designer’s worst nightmare is? To be locked in a room during a scientific poster session. Slides can also be quite terrifying for them.&lt;/p&gt;
&lt;p&gt;Scientists use visual tools all the time. Figures, plots, tables — not to mention there are even artistic sub-genres such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Technical_illustration&quot;&gt;technical&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Biological_illustration&quot;&gt;naturalist illustration&lt;/a&gt;. But scientists rarely receive specific training in the appropriate use of these visual tools.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;641&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PuWjAi9qh5p_s4InUMmn_w-a49f47a1.Bwk7ayQF_1afUjp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Punica granatum, by Prof. Dr. Otto Wilhelm Thomé (1885)&lt;/p&gt;
&lt;p&gt;Most people (and scientists are no exception) don’t know that there are certain rules about design. Some of them are subtle, such as not using the same figures in a paper and in a poster or slides (each format should be read from a different distance, and with a different level of attention). Others are well known, but very often broken for no good reason (such as minimizing the use of text or using a proper font size). Last but not least, there are mistakes so obvious that it is surprising they still persist (such as using crazy color combinations or adding a slide with 25 references… that will remain on screen for 3 seconds).&lt;/p&gt;
&lt;p&gt;A personal tip: a few years ago, I collaborated with the human resources department of a tech company. We spent several days reading the curricula of mathematicians, physicists and engineers. I cannot stress enough the strategic advantage of having an aesthetically, well-designed curriculum.&lt;/p&gt;
&lt;p&gt;Spending some time learning the basics of visual communication will definitely pay off.&lt;/p&gt;
&lt;h2 id=&quot;understanding-creativity&quot;&gt;Understanding creativity&lt;/h2&gt;
&lt;p&gt;Another shared feature of scientists and artists is that they both have creative jobs.&lt;/p&gt;
&lt;p&gt;Understanding how creative processes work is more complicated than it may seem. We, scientists, tend to struggle with the fact that hitting our head against a problem when we are blocked rarely gives any result. Even worse, it is usually counterproductive. Often, the best way to find a solution is to explore alternative paths, or even abandon the lab and go for a walk, do some sports or just have a beer.&lt;/p&gt;
&lt;p&gt;In the world of arts, traditionally more bohemian, everybody is aware of this. To the point that, for instance, some design agencies implement protocols to guarantee that several options are always explored before choosing one at the beginning of a project.&lt;/p&gt;
&lt;p&gt;And that’s it for now. Feel free to add your own experiences in the comments section below.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The craft of scientific writing. Michael Alley.&lt;/li&gt;
&lt;li&gt;The craft of scientific presentations. Michael Alley.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=fDzGkD9QqD8&amp;#x26;feature=youtu.be&quot;&gt;The art and science of data visualization&lt;/a&gt;, Moritz Stefaner&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nature.com/articles/d41586-019-01431-z?utm_source=Nature+Briefing&amp;#x26;utm_campaign=9c58c75666-briefing-dy-wk-20200102&amp;#x26;utm_medium=email&amp;#x26;utm_term=0_c9dfd39373-9c58c75666-42144719&quot;&gt;How small changes to a paper can help to smooth the review process&lt;/a&gt;. Nature&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nature.com/articles/d41586-019-02918-5?utm_source=Nature+Briefing&amp;#x26;utm_campaign=9c58c75666-briefing-dy-wk-20200102&amp;#x26;utm_medium=email&amp;#x26;utm_term=0_c9dfd39373-9c58c75666-42144719&quot;&gt;Novelist Cormac McCarthy’s tips on how to write a great science paper&lt;/a&gt;. Nature&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://well.blogs.nytimes.com/2014/04/30/want-to-be-more-creative-take-a-walk/?ref=health&quot;&gt;Want to be More Creative? Take a Walk.&lt;/a&gt; Gretchen Reynolds. &lt;em&gt;The New York Times.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sciencedaily.com/releases/2014/07/140721142211.htm&quot;&gt;Try, try again? Study says no: Trying harder makes it more difficult to learn some aspects of language, neuroscientists find.&lt;/a&gt;Anne Trafton. &lt;em&gt;Science daily.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This blog entry is adapted from its Spanish version, that appeared first in&lt;/em&gt; &lt;a href=&quot;https://fuga.naukas.com/2017/12/12/cosas-ciencia-artes/&quot;&gt;&lt;em&gt;Naukas&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_wNaFhH5r5r7f0FL1-89ccb634.q6TGNtP2.webp" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>The success of reliable integration of renewable energy</title><link>https://blog2.esciencecenter.nl/posts/2019-12-17---the-success-of-reliable-integration-of-renewable-energy</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-12-17---the-success-of-reliable-integration-of-renewable-energy</guid><description>&lt;p&gt;&lt;strong&gt;Countries, companies and individuals are increasingly aware of the need to keep our world clean by supporting sustainable energy. The landscape is evolving rapidly. Of the various mechanisms considered currently, the potential of solar energy is particularly promising. One of the evolving technologies used to harness radiant light from the sun is photovoltaics technology. Photovoltaic cells are cheap, environmentally friendly, thin, light and very flexible. Developing low-cost and environmentally friendly devices that can be scaled up to industrial production is crucial for the successful and reliable integration of renewable energy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Sophie de Kort&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1558&quot; height=&quot;1233&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1A6Sam1ej7Qddvg-p9A6UQ-fbdb0577.B3fX9Y9w_1z133s.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Dr. Björn Baumeier, Dr. Nicolas Renaud, Dr. Alexey Lyulin, Vivek Sundaram, Dr. Jens Wehner, Dr. Felipe Zapata&lt;/p&gt;
&lt;p&gt;In the project MULTIXMAS, Dr. Björn Baumeier and Dr. Alexey Lyulin from TU Eindhoven together with the Netherlands eScience Center, are developing bottom-up simulations of charge-carriers dynamics in large-scale polymer morphologies of some organic solar cells, combining multiscale structure equilibration of a nanomaterial using classical molecular-dynamic simulations with excited state electronic structure theory.&lt;/p&gt;
&lt;p&gt;The development of such a multiscale computer simulation approach is the central building block of this project. According to Lyulin, associate professor within the Theory of Polymers and Soft Matter (TPS) Group of the Applied Physics Department at TU Eindhoven, this is an extremely challenging task.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kKCbraELy5Nj7k8zlDNQng-bb621ec4.DSk9r0li_Z2sPIlk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;827&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r95bmmrBPyNxPQA3Q2zAAA-ab4239b6.Dai16rYX_Z2qxXb0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;avoiding-the-creation-of-a-computational-frankenstein-monster&quot;&gt;Avoiding the creation of a computational Frankenstein monster&lt;/h2&gt;
&lt;p&gt;Baumeier, assistant professor at TU Eindhoven´s Scientific Computing Group, says his research is driven both by curiosity and with an eye on applications.&lt;/p&gt;
&lt;p&gt;“Molecular materials offer a fascinating playground in this regard since they exhibit electronic behavior that makes them suitable to be used in devices such as organic light-emitting diodes (see OLED displays in mobile phones or TVs) or solar cells. In all cases, the behavior we see and use at the device scale is the result of a very intricate interplay of elementary processes that occur on nano- and macroscales. My goal is to use simulations based on first principles to understand fundamentally how these processes and their interactions give rise to the observable behavior and with this knowledge drive the optimization of materials forward. These simulations need to be accurate and predictive which constitutes challenges on various levels: the multiscale nature of the problem means that one needs combinations of several models, which in turn requires a careful control of the individual methods and how they are combined to avoid the creation of a computational Frankenstein monster.”&lt;/p&gt;
&lt;h2 id=&quot;diversity-and-expertise&quot;&gt;Diversity and expertise&lt;/h2&gt;
&lt;p&gt;Collaboration plays a central role in his group’s research, says Baumeier “From the nature of the problem, it requires expertise in several fields to successfully tackle it. At group level we have people with diverse backgrounds who need to work together to achieve a common goal. The collaboration with eScience Engineers Dr. Nicolas Renaud and Dr. Felipe Zapata, added greatly to this diversity by bringing both domain knowledge and the particular eScience skills that were only marginally present before.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Felipe and Nicolas have helped with developments that now allow us to address bigger and therefore more relevant systems than before.” — Dr. B. Baumeier&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Baumeier continues: “One of the restrictions of our simulation software is that it is computationally very demanding. This is particularly true for the excited-state quantum-chemical calculations we perform with the help of Green’s functions. Felipe and Nicolas have helped with developments that now allow us to address bigger and therefore more relevant systems than before. Their initial outsiders’ view to the workflow has also been useful in identifying areas of improvement.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1062&quot; height=&quot;625&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_K-NUx4P82PnRtroHCScxYA-297ea601.BFKhHutN_ZFByjF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“On the technical side the eScience Center brought a lot of new ideas and opinions to the project, which was very refreshing. I underestimated how important good communication between the parties is to get the process working smoothly.” — Dr. Jens Wehner, Eindhoven University of Technology&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;lasting-collaboration&quot;&gt;Lasting collaboration&lt;/h2&gt;
&lt;p&gt;Methods developed in MULTIXMAS are not material-specific and will be part of the open-source VOTCA package. Bexause MULTIXMAS’s developments will enter the open source VOTCA software(&lt;a href=&quot;http://www.votca.org,/&quot;&gt;&lt;em&gt;www.votca.org&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, github.com/votca)&lt;/em&gt;,the concept of openness and sharing best practices is very important. Lyulin: “As a general toolkit for multiscale simulation of excitation dynamics in complex molecular systems, with extendable interfaces to standard quantum-chemistry software, we expect a large number of users and long-lasting collaborations beyond the project’s runtime.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__kbstCnwWfoVNM5geC7WFA-c379a299.BhFxeq4D_Z2612gn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kKCbraELy5Nj7k8zlDNQng-bb621ec4.DSk9r0li_Z2sPIlk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Baumeier agrees: “Openness has been an essential aspect of our work before the project and it continues to be one during the project. I am a strong advocate of open-source software in scientific research and it has always been important for me to be open in our own work and also to be able to make use of other’s research. Frankly, not doing it would be a waste of resources. If we do our job well, our work can be used in a variety of contexts besides the polymer solar cell use case we are currently working on.”&lt;/p&gt;
&lt;p&gt;The goal is to bring the quality of simulations, both from a scientific and a software point of view, to a higher level.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“If we do our job well, our work can be used in a variety of contexts besides the polymer solar cell use case we are working on.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are already some groups internationally who use and contribute to the research software and Baumeier expects this user group to increase with performance, feature, and usability enhancements.&lt;/p&gt;
&lt;p&gt;Read more about project &lt;a href=&quot;https://www.esciencecenter.nl/project/multixmas&quot;&gt;MULTIXMAS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://www.baumeiergroup.com/&quot;&gt;Baumeier Research Group&lt;/a&gt;, &lt;a href=&quot;https://www.facebook.com/baumeier.group&quot;&gt;Facebook&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/baumeiergroup&quot;&gt;Twitter&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 17 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Countries, companies and individuals are increasingly aware of the need to keep our world clean by supporting sustainable energy. The landscape is evolving rapidly. Of the various mechanisms considered currently, the potential of solar energy is particularly promising. One of the evolving technologies used to harness radiant light from the sun is photovoltaics technology. Photovoltaic cells are cheap, environmentally friendly, thin, light and very flexible. Developing low-cost and environmentally friendly devices that can be scaled up to industrial production is crucial for the successful and reliable integration of renewable energy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Sophie de Kort&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1558&quot; height=&quot;1233&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1A6Sam1ej7Qddvg-p9A6UQ-fbdb0577.B3fX9Y9w_1z133s.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Dr. Björn Baumeier, Dr. Nicolas Renaud, Dr. Alexey Lyulin, Vivek Sundaram, Dr. Jens Wehner, Dr. Felipe Zapata&lt;/p&gt;
&lt;p&gt;In the project MULTIXMAS, Dr. Björn Baumeier and Dr. Alexey Lyulin from TU Eindhoven together with the Netherlands eScience Center, are developing bottom-up simulations of charge-carriers dynamics in large-scale polymer morphologies of some organic solar cells, combining multiscale structure equilibration of a nanomaterial using classical molecular-dynamic simulations with excited state electronic structure theory.&lt;/p&gt;
&lt;p&gt;The development of such a multiscale computer simulation approach is the central building block of this project. According to Lyulin, associate professor within the Theory of Polymers and Soft Matter (TPS) Group of the Applied Physics Department at TU Eindhoven, this is an extremely challenging task.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kKCbraELy5Nj7k8zlDNQng-bb621ec4.DSk9r0li_Z2sPIlk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;827&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r95bmmrBPyNxPQA3Q2zAAA-ab4239b6.Dai16rYX_Z2qxXb0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;avoiding-the-creation-of-a-computational-frankenstein-monster&quot;&gt;Avoiding the creation of a computational Frankenstein monster&lt;/h2&gt;
&lt;p&gt;Baumeier, assistant professor at TU Eindhoven´s Scientific Computing Group, says his research is driven both by curiosity and with an eye on applications.&lt;/p&gt;
&lt;p&gt;“Molecular materials offer a fascinating playground in this regard since they exhibit electronic behavior that makes them suitable to be used in devices such as organic light-emitting diodes (see OLED displays in mobile phones or TVs) or solar cells. In all cases, the behavior we see and use at the device scale is the result of a very intricate interplay of elementary processes that occur on nano- and macroscales. My goal is to use simulations based on first principles to understand fundamentally how these processes and their interactions give rise to the observable behavior and with this knowledge drive the optimization of materials forward. These simulations need to be accurate and predictive which constitutes challenges on various levels: the multiscale nature of the problem means that one needs combinations of several models, which in turn requires a careful control of the individual methods and how they are combined to avoid the creation of a computational Frankenstein monster.”&lt;/p&gt;
&lt;h2 id=&quot;diversity-and-expertise&quot;&gt;Diversity and expertise&lt;/h2&gt;
&lt;p&gt;Collaboration plays a central role in his group’s research, says Baumeier “From the nature of the problem, it requires expertise in several fields to successfully tackle it. At group level we have people with diverse backgrounds who need to work together to achieve a common goal. The collaboration with eScience Engineers Dr. Nicolas Renaud and Dr. Felipe Zapata, added greatly to this diversity by bringing both domain knowledge and the particular eScience skills that were only marginally present before.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Felipe and Nicolas have helped with developments that now allow us to address bigger and therefore more relevant systems than before.” — Dr. B. Baumeier&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Baumeier continues: “One of the restrictions of our simulation software is that it is computationally very demanding. This is particularly true for the excited-state quantum-chemical calculations we perform with the help of Green’s functions. Felipe and Nicolas have helped with developments that now allow us to address bigger and therefore more relevant systems than before. Their initial outsiders’ view to the workflow has also been useful in identifying areas of improvement.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1062&quot; height=&quot;625&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_K-NUx4P82PnRtroHCScxYA-297ea601.BFKhHutN_ZFByjF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“On the technical side the eScience Center brought a lot of new ideas and opinions to the project, which was very refreshing. I underestimated how important good communication between the parties is to get the process working smoothly.” — Dr. Jens Wehner, Eindhoven University of Technology&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;lasting-collaboration&quot;&gt;Lasting collaboration&lt;/h2&gt;
&lt;p&gt;Methods developed in MULTIXMAS are not material-specific and will be part of the open-source VOTCA package. Bexause MULTIXMAS’s developments will enter the open source VOTCA software(&lt;a href=&quot;http://www.votca.org,/&quot;&gt;&lt;em&gt;www.votca.org&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, github.com/votca)&lt;/em&gt;,the concept of openness and sharing best practices is very important. Lyulin: “As a general toolkit for multiscale simulation of excitation dynamics in complex molecular systems, with extendable interfaces to standard quantum-chemistry software, we expect a large number of users and long-lasting collaborations beyond the project’s runtime.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__kbstCnwWfoVNM5geC7WFA-c379a299.BhFxeq4D_Z2612gn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kKCbraELy5Nj7k8zlDNQng-bb621ec4.DSk9r0li_Z2sPIlk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Baumeier agrees: “Openness has been an essential aspect of our work before the project and it continues to be one during the project. I am a strong advocate of open-source software in scientific research and it has always been important for me to be open in our own work and also to be able to make use of other’s research. Frankly, not doing it would be a waste of resources. If we do our job well, our work can be used in a variety of contexts besides the polymer solar cell use case we are currently working on.”&lt;/p&gt;
&lt;p&gt;The goal is to bring the quality of simulations, both from a scientific and a software point of view, to a higher level.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“If we do our job well, our work can be used in a variety of contexts besides the polymer solar cell use case we are working on.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are already some groups internationally who use and contribute to the research software and Baumeier expects this user group to increase with performance, feature, and usability enhancements.&lt;/p&gt;
&lt;p&gt;Read more about project &lt;a href=&quot;https://www.esciencecenter.nl/project/multixmas&quot;&gt;MULTIXMAS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://www.baumeiergroup.com/&quot;&gt;Baumeier Research Group&lt;/a&gt;, &lt;a href=&quot;https://www.facebook.com/baumeier.group&quot;&gt;Facebook&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/baumeiergroup&quot;&gt;Twitter&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_1A6Sam1ej7Qddvg-p9A6UQ-fbdb0577.B3fX9Y9w.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Are you a researcher? You may not know it yet, but good software skills are just what you need</title><link>https://blog2.esciencecenter.nl/posts/2019-12-16---are-you-a-researcher-you-may-not-know-it-yet-but-good-softwa</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-12-16---are-you-a-researcher-you-may-not-know-it-yet-but-good-softwa</guid><description>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;The previous example may look like (and actually is) quite silly. But remember that code is alive. Something that today is a simple function tomorrow may be more complicated. Imagine that a collaborator edits your function like this:&lt;/p&gt;
&lt;p&gt;sum(x,y):
return (x - y)The edit is ok, the code will compile, but the function will just not do what it is expected to do. The tests will notice immediately that something went wrong.&lt;/p&gt;
&lt;p&gt;Code is not only alive but complex. A week later, your function may become part of a bigger picture, with several functions calling each other. A single error may create a domino effect. Unit tests make easy identifying where exactly the error is happening.&lt;/p&gt;
&lt;p&gt;Other side advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Running the battery of tests allows users/collaborators to check that they installed your code properly&lt;/li&gt;
&lt;li&gt;Tests can be used as complementary documentation&lt;/li&gt;
&lt;li&gt;Writing code with unit tests in mind increases the modularity and quality of code&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;i-am-interested-how-should-i-start&quot;&gt;I am interested! How should I start?&lt;/h3&gt;
&lt;p&gt;Although the idea behind unit tests is general and simple, the specific practical implementation depends on the programming language you are using. Perhaps you can guess how to start: just Google “unit testing” + your programming language*.&lt;/p&gt;
&lt;h3 id=&quot;version-control&quot;&gt;Version control&lt;/h3&gt;
&lt;p&gt;As I said, code is alive. Code grows, changes, gets updated. The idea behind version control is to keep an ordered and commented registry of all the changes that the code has suffered. It allows, for instance, comparing the same file at different stages in time. Or rolling back to a previous version in case of regretting one or several edits.&lt;/p&gt;
&lt;p&gt;Additionally, services such as GitHub, GitLab or BitBucket allow easy publishing and sharing of code under version control. This is particularly useful if you are writing code with a team or if you want to make your code available in a practical way.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Are you a researcher? You may not know it yet, but good software skills are just what you need&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;486&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/are-you-a-researcher-you-may-not-know-it-27eabb68.Cba5TgGu_Z2mf1ut.webp&quot; srcset=&quot;&quot;&gt;
Example of a GitHub timeline. The “commits” appear in chronological order, and each of them corresponds to a modification important enough to deserve a comment. By clicking on the commits (source &lt;a href=&quot;https://github.com/PabRod/academic-record/commits/master&quot;&gt;here&lt;/a&gt;) you can see a detailed overview of the changes.&lt;/p&gt;
&lt;h3 id=&quot;i-am-interested-how-should-i-start-1&quot;&gt;I am interested! How should I start?&lt;/h3&gt;
&lt;p&gt;Currently, the most popular version control system is git, which is free and open source. The first encounter can be a bit shocking if you are not used to the console. Feel free to use a graphical user interface, especially at the beginning, if that makes you more comfortable.&lt;/p&gt;
&lt;h3 id=&quot;wait-a-minute-is-this-not-too-complicated&quot;&gt;Wait a minute! Is this not too complicated?&lt;/h3&gt;
&lt;p&gt;After knowing about these methods some researchers react considering them too complicated. These same researchers tend to develop their own artisanal methods, that end up being equally (or more) complicated and much more inefficient and insecure. This should not be surprising, as the complexity is not in the method, but in the problems we are trying to solve.&lt;/p&gt;
&lt;p&gt;Writing a scientific paper, a piece of software or a thesis is a complex process not only from a scientific point of view, but also from that of information management. Software engineers have extensive experience in exactly these kinds of problems… why not use their tools of proven efficiency instead of painfully reinventing the wheel?&lt;/p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://journals.plos.org/plosbiology/article?id=10.1371%2Fjournal.pbio.1001745&quot;&gt;Best practices for scientific computing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*This post is strongly based in another post of the author, &lt;em&gt;&lt;a href=&quot;https://culturacientifica.com/2018/05/18/algunas-cosas-que-los-cientificos-pueden-aprender-de-los-programadores/&quot;&gt;&lt;em&gt;Algunas cosas que los científicos pueden aprender de los programadores&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, written in Spanish for *&lt;a href=&quot;https://naukas.com&quot;&gt;&lt;em&gt;Naukas.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 16 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;The previous example may look like (and actually is) quite silly. But remember that code is alive. Something that today is a simple function tomorrow may be more complicated. Imagine that a collaborator edits your function like this:&lt;/p&gt;
&lt;p&gt;sum(x,y):
return (x - y)The edit is ok, the code will compile, but the function will just not do what it is expected to do. The tests will notice immediately that something went wrong.&lt;/p&gt;
&lt;p&gt;Code is not only alive but complex. A week later, your function may become part of a bigger picture, with several functions calling each other. A single error may create a domino effect. Unit tests make easy identifying where exactly the error is happening.&lt;/p&gt;
&lt;p&gt;Other side advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Running the battery of tests allows users/collaborators to check that they installed your code properly&lt;/li&gt;
&lt;li&gt;Tests can be used as complementary documentation&lt;/li&gt;
&lt;li&gt;Writing code with unit tests in mind increases the modularity and quality of code&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;i-am-interested-how-should-i-start&quot;&gt;I am interested! How should I start?&lt;/h3&gt;
&lt;p&gt;Although the idea behind unit tests is general and simple, the specific practical implementation depends on the programming language you are using. Perhaps you can guess how to start: just Google “unit testing” + your programming language*.&lt;/p&gt;
&lt;h3 id=&quot;version-control&quot;&gt;Version control&lt;/h3&gt;
&lt;p&gt;As I said, code is alive. Code grows, changes, gets updated. The idea behind version control is to keep an ordered and commented registry of all the changes that the code has suffered. It allows, for instance, comparing the same file at different stages in time. Or rolling back to a previous version in case of regretting one or several edits.&lt;/p&gt;
&lt;p&gt;Additionally, services such as GitHub, GitLab or BitBucket allow easy publishing and sharing of code under version control. This is particularly useful if you are writing code with a team or if you want to make your code available in a practical way.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Are you a researcher? You may not know it yet, but good software skills are just what you need&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;486&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/are-you-a-researcher-you-may-not-know-it-27eabb68.Cba5TgGu_Z2mf1ut.webp&quot; srcset=&quot;&quot;&gt;
Example of a GitHub timeline. The “commits” appear in chronological order, and each of them corresponds to a modification important enough to deserve a comment. By clicking on the commits (source &lt;a href=&quot;https://github.com/PabRod/academic-record/commits/master&quot;&gt;here&lt;/a&gt;) you can see a detailed overview of the changes.&lt;/p&gt;
&lt;h3 id=&quot;i-am-interested-how-should-i-start-1&quot;&gt;I am interested! How should I start?&lt;/h3&gt;
&lt;p&gt;Currently, the most popular version control system is git, which is free and open source. The first encounter can be a bit shocking if you are not used to the console. Feel free to use a graphical user interface, especially at the beginning, if that makes you more comfortable.&lt;/p&gt;
&lt;h3 id=&quot;wait-a-minute-is-this-not-too-complicated&quot;&gt;Wait a minute! Is this not too complicated?&lt;/h3&gt;
&lt;p&gt;After knowing about these methods some researchers react considering them too complicated. These same researchers tend to develop their own artisanal methods, that end up being equally (or more) complicated and much more inefficient and insecure. This should not be surprising, as the complexity is not in the method, but in the problems we are trying to solve.&lt;/p&gt;
&lt;p&gt;Writing a scientific paper, a piece of software or a thesis is a complex process not only from a scientific point of view, but also from that of information management. Software engineers have extensive experience in exactly these kinds of problems… why not use their tools of proven efficiency instead of painfully reinventing the wheel?&lt;/p&gt;
&lt;h3 id=&quot;references&quot;&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://journals.plos.org/plosbiology/article?id=10.1371%2Fjournal.pbio.1001745&quot;&gt;Best practices for scientific computing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*This post is strongly based in another post of the author, &lt;em&gt;&lt;a href=&quot;https://culturacientifica.com/2018/05/18/algunas-cosas-que-los-cientificos-pueden-aprender-de-los-programadores/&quot;&gt;&lt;em&gt;Algunas cosas que los científicos pueden aprender de los programadores&lt;/em&gt;&lt;/a&gt;&lt;/em&gt;, written in Spanish for *&lt;a href=&quot;https://naukas.com&quot;&gt;&lt;em&gt;Naukas.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/are-you-a-researcher-you-may-not-know-it-27eabb68.Cba5TgGu.jpeg" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Experiences of a computational evangelist</title><link>https://blog2.esciencecenter.nl/posts/2019-12-16---experiences-of-a-computational-evangelist</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-12-16---experiences-of-a-computational-evangelist</guid><description>&lt;p&gt;What I’ve learned spreading the gospel of computational best practices among scientists&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_U-HMVgB8PS9IQXF0-845426ce.DM0BbbUC_Z1yd6n.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NESA by Makers on Unsplash&lt;/p&gt;
&lt;p&gt;Just a few days ago, I gave a talk at the &lt;a href=&quot;https://blog.esciencecenter.nl/fair-software-at-the-2019-escience-symposium-6117f310aa34&quot;&gt;FAIR (Findable, Accessible, Interoperable and Reusable) software parallel session&lt;/a&gt; of the &lt;a href=&quot;https://www.esciencesymposium2019.nl/&quot;&gt;National eScience Symposium 2019&lt;/a&gt;. During the questions session, several topics were raised: the impossibility of true reproducibility, the challenges of the interaction between &lt;em&gt;FAIRness&lt;/em&gt; and privacy, the problem of long-term software sustainability, the potential problems of including libraries with restrictive licenses, and so on.&lt;/p&gt;
&lt;p&gt;Just a few weeks ago, I was still enrolled as a mathematical modeler in an aquatic ecology department. Although my former colleagues are interested in improving the quality and FAIRness of their research code, I never heard any of the previously mentioned concerns. I don’t mean that those concerns aren’t important, it is just that I felt an enormous gap between researchers’ concerns and &lt;em&gt;state-of-the-art&lt;/em&gt; ones. To begin with, most researchers I’ve collaborated with didn’t know of the mere existence of public repositories, coding guidelines, version control systems or unit tests. Like me, they were just never told.&lt;/p&gt;
&lt;p&gt;In my opinion, this is the elephant in the room: the narrowest bottleneck of FAIR scientific software is the fact that those who are aware of its importance are still a minority. And those who are aware and have the time and motivation to take effective actions are a minority inside the minority.&lt;/p&gt;
&lt;p&gt;As a result, thousands of researchers are not only not producing FAIR software, but also managing their projects using the most inefficient and frustrating system: blood and sweat. As a side effect, millions of lines of code are rotting in researchers’ hard disks, the reproducibility crisis is a trending topic and job dissatisfaction is becoming endemic among young researchers (okay, maybe this last one has other causes too).&lt;/p&gt;
&lt;p&gt;Everything starts with the way most scientists are introduced to programming: a course on scripting if they are lucky, or plain “baptism by fire” if they are not. The only guideline seems to be: if it works, it is good programming. Isn’t it?&lt;/p&gt;
&lt;p&gt;Those of us who have been lucky enough to learn “good programming” know that the answer is no. Even more, we know how extremely useful good programming skills can be for researchers… and we try to do our best to spread the word and teach others. When I started teaching these topics to whoever wanted to pay attention to me, I made some mistakes. I would certainly include the following advice if I could send a letter to my past self. Unfortunately, I cannot, but I can send a letter to you, dear reader. Hopefully, you’ll find it interesting.&lt;/p&gt;
&lt;h3 id=&quot;motivation-you-already-need-best-practices&quot;&gt;Motivation: you already need best practices&lt;/h3&gt;
&lt;p&gt;Or put differently: this is not a computer geeks’ thing.&lt;/p&gt;
&lt;p&gt;Let’s use a bit of empathy here. Imagine you’ve studied biology, probably dreaming of traveling to exotic locations, swimming with sharks in the Caribbean and taking water samples from Antarctica… and one day you see yourself behind a desk, analyzing thousands of rows of taxonomic data. Sure, you understand the importance of this kind of work, but most likely this is not your favorite hour of the day. Why would you invest even more time in learning computational skills?&lt;/p&gt;
&lt;p&gt;Well, answer me this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do you keep a bunch of copies of your manuscripts at different stages?&lt;/li&gt;
&lt;li&gt;Did your code work yesterday, but not today after what seemed to be a minor edition?&lt;/li&gt;
&lt;li&gt;Are you unable to understand the code you wrote yourself just a few months ago?&lt;/li&gt;
&lt;li&gt;Are you interested in sharing your code with coauthors, or even with readers?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And maybe more importantly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are you interested in making your computational work more enjoyable?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Did you answer yes to any of them? You are not alone! Those problems have been the daily routine of thousands of people all around the world for decades. And you know what? Some of them developed really handy tools, known under the umbrella term of “best practices” to tackle them.&lt;/p&gt;
&lt;h3 id=&quot;goal-plant-a-seed&quot;&gt;Goal: plant a seed&lt;/h3&gt;
&lt;p&gt;Making your students discover that there are tools that can help them is a minimum. Convincing them that anyone can use those tools and showing where to start is already a big success.&lt;/p&gt;
&lt;p&gt;Pro tip: make sure that they have installed and set up all they need. The real magic happens when the students go home and try by themselves.&lt;/p&gt;
&lt;h3 id=&quot;start-with-their-basics-not-with-yours&quot;&gt;Start with their basics, not with yours&lt;/h3&gt;
&lt;p&gt;The precise meaning of the term “basic” is given by your students, not by you.&lt;/p&gt;
&lt;p&gt;For instance, if they are interested in unit testing, make sure they know a bit of factoring beforehand. If not, start with factoring even if this reduces the time available for unit testing.&lt;/p&gt;
&lt;p&gt;It is highly unlikely that someone who walks into a best practices seminar for the first time comes out of it, two hours later, as the new Donald Knuth. Most importantly, this is not the purpose of such a seminar. Switching from Windows to Ubuntu, learning the basics of Python, getting introduced to Vim, pyTest, Git and (if there’s time) to Continuous Integration may be a bit too ambitious for a two-hour introduction (I didn’t try to go so far myself, but this list is inspired by true events). It doesn’t matter how cool those tools are, keep calm and start with the basics. Keep advanced topics for advanced stages. One step at a time.&lt;/p&gt;
&lt;h3 id=&quot;take-advantage-of-what-they-already-know&quot;&gt;Take advantage of what they already know&lt;/h3&gt;
&lt;p&gt;If your students are familiar with a language you hate (say, MATLAB) it may be tempting to ask them to switch to your favorite one. It will be much easier to stick to their language of choice to teach some generally applicable principles, such as version control or unit testing. Switching from one language to another is extremely stressful for beginners.&lt;/p&gt;
&lt;h3 id=&quot;avoid-the-command-console&quot;&gt;Avoid the command console&lt;/h3&gt;
&lt;p&gt;Before crucifying me, let me explain myself. Yes, I love the command console, and I am allergic to (most) graphical user interfaces. One of the aspects I love about the console is that it forces me to keep in mind a clear structure of what I am doing. But when it comes to teaching, I don’t want to keep things in my mind. I want to share them as explicitly as possible. Graphical user interfaces are great for this.&lt;/p&gt;
&lt;p&gt;Last but not least, in a world dominated by graphical interfaces, the command console is very scary for most beginners. Yes, I know they &lt;em&gt;should not&lt;/em&gt; be scared (whatever that means), but the fact is that they are. Especially in the early stages, I suggest to avoid it as much as possible.&lt;/p&gt;
&lt;h3 id=&quot;make-education-acronym-free-again&quot;&gt;Make education acronym-free again&lt;/h3&gt;
&lt;p&gt;If like me, you are Spanish, the acronyms &lt;em&gt;PSOE&lt;/em&gt;, &lt;em&gt;IVA&lt;/em&gt; or &lt;em&gt;IRPF&lt;/em&gt; will be crystal clear for you. But most likely you, dear reader, are not from Spain. What did you feel while reading those acronyms? Probably something between slight annoyance and absolute nothingness. Well, beginners feel the same when they read &lt;em&gt;CI&lt;/em&gt;, &lt;em&gt;GUI&lt;/em&gt; or &lt;em&gt;CMD&lt;/em&gt; for the first time. And not only beginners: each time I see an acronym in the title of a talk I take it as a cue to skip it and go get a coffee.&lt;/p&gt;
&lt;p&gt;Using acronyms (and other jargon) with beginners is the quickest way to sound cryptic. Also, the easiest one to avoid.&lt;/p&gt;
&lt;h3 id=&quot;but-i-already-have-a-system&quot;&gt;But I already have a system!&lt;/h3&gt;
&lt;p&gt;“Why do I need Git? I have Dropbox!”, “I store my code in email drafts”, “The code compiles, why do I need tests?”…&lt;/p&gt;
&lt;p&gt;These kinds of questions will arise. Answer them once, and don’t insist much more, especially if they keep thinking their solution is good enough. For most people, it takes some time to abandon an old routine… but they are listening.&lt;/p&gt;
&lt;p&gt;The previous list doesn’t try to be exhaustive. This is just an open reflection on my own experience. Feel free to comment on your own. After all, all of us were beginners once.&lt;/p&gt;</description><pubDate>Mon, 16 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What I’ve learned spreading the gospel of computational best practices among scientists&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_U-HMVgB8PS9IQXF0-845426ce.DM0BbbUC_Z1yd6n.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NESA by Makers on Unsplash&lt;/p&gt;
&lt;p&gt;Just a few days ago, I gave a talk at the &lt;a href=&quot;https://blog.esciencecenter.nl/fair-software-at-the-2019-escience-symposium-6117f310aa34&quot;&gt;FAIR (Findable, Accessible, Interoperable and Reusable) software parallel session&lt;/a&gt; of the &lt;a href=&quot;https://www.esciencesymposium2019.nl/&quot;&gt;National eScience Symposium 2019&lt;/a&gt;. During the questions session, several topics were raised: the impossibility of true reproducibility, the challenges of the interaction between &lt;em&gt;FAIRness&lt;/em&gt; and privacy, the problem of long-term software sustainability, the potential problems of including libraries with restrictive licenses, and so on.&lt;/p&gt;
&lt;p&gt;Just a few weeks ago, I was still enrolled as a mathematical modeler in an aquatic ecology department. Although my former colleagues are interested in improving the quality and FAIRness of their research code, I never heard any of the previously mentioned concerns. I don’t mean that those concerns aren’t important, it is just that I felt an enormous gap between researchers’ concerns and &lt;em&gt;state-of-the-art&lt;/em&gt; ones. To begin with, most researchers I’ve collaborated with didn’t know of the mere existence of public repositories, coding guidelines, version control systems or unit tests. Like me, they were just never told.&lt;/p&gt;
&lt;p&gt;In my opinion, this is the elephant in the room: the narrowest bottleneck of FAIR scientific software is the fact that those who are aware of its importance are still a minority. And those who are aware and have the time and motivation to take effective actions are a minority inside the minority.&lt;/p&gt;
&lt;p&gt;As a result, thousands of researchers are not only not producing FAIR software, but also managing their projects using the most inefficient and frustrating system: blood and sweat. As a side effect, millions of lines of code are rotting in researchers’ hard disks, the reproducibility crisis is a trending topic and job dissatisfaction is becoming endemic among young researchers (okay, maybe this last one has other causes too).&lt;/p&gt;
&lt;p&gt;Everything starts with the way most scientists are introduced to programming: a course on scripting if they are lucky, or plain “baptism by fire” if they are not. The only guideline seems to be: if it works, it is good programming. Isn’t it?&lt;/p&gt;
&lt;p&gt;Those of us who have been lucky enough to learn “good programming” know that the answer is no. Even more, we know how extremely useful good programming skills can be for researchers… and we try to do our best to spread the word and teach others. When I started teaching these topics to whoever wanted to pay attention to me, I made some mistakes. I would certainly include the following advice if I could send a letter to my past self. Unfortunately, I cannot, but I can send a letter to you, dear reader. Hopefully, you’ll find it interesting.&lt;/p&gt;
&lt;h3 id=&quot;motivation-you-already-need-best-practices&quot;&gt;Motivation: you already need best practices&lt;/h3&gt;
&lt;p&gt;Or put differently: this is not a computer geeks’ thing.&lt;/p&gt;
&lt;p&gt;Let’s use a bit of empathy here. Imagine you’ve studied biology, probably dreaming of traveling to exotic locations, swimming with sharks in the Caribbean and taking water samples from Antarctica… and one day you see yourself behind a desk, analyzing thousands of rows of taxonomic data. Sure, you understand the importance of this kind of work, but most likely this is not your favorite hour of the day. Why would you invest even more time in learning computational skills?&lt;/p&gt;
&lt;p&gt;Well, answer me this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do you keep a bunch of copies of your manuscripts at different stages?&lt;/li&gt;
&lt;li&gt;Did your code work yesterday, but not today after what seemed to be a minor edition?&lt;/li&gt;
&lt;li&gt;Are you unable to understand the code you wrote yourself just a few months ago?&lt;/li&gt;
&lt;li&gt;Are you interested in sharing your code with coauthors, or even with readers?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And maybe more importantly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are you interested in making your computational work more enjoyable?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Did you answer yes to any of them? You are not alone! Those problems have been the daily routine of thousands of people all around the world for decades. And you know what? Some of them developed really handy tools, known under the umbrella term of “best practices” to tackle them.&lt;/p&gt;
&lt;h3 id=&quot;goal-plant-a-seed&quot;&gt;Goal: plant a seed&lt;/h3&gt;
&lt;p&gt;Making your students discover that there are tools that can help them is a minimum. Convincing them that anyone can use those tools and showing where to start is already a big success.&lt;/p&gt;
&lt;p&gt;Pro tip: make sure that they have installed and set up all they need. The real magic happens when the students go home and try by themselves.&lt;/p&gt;
&lt;h3 id=&quot;start-with-their-basics-not-with-yours&quot;&gt;Start with their basics, not with yours&lt;/h3&gt;
&lt;p&gt;The precise meaning of the term “basic” is given by your students, not by you.&lt;/p&gt;
&lt;p&gt;For instance, if they are interested in unit testing, make sure they know a bit of factoring beforehand. If not, start with factoring even if this reduces the time available for unit testing.&lt;/p&gt;
&lt;p&gt;It is highly unlikely that someone who walks into a best practices seminar for the first time comes out of it, two hours later, as the new Donald Knuth. Most importantly, this is not the purpose of such a seminar. Switching from Windows to Ubuntu, learning the basics of Python, getting introduced to Vim, pyTest, Git and (if there’s time) to Continuous Integration may be a bit too ambitious for a two-hour introduction (I didn’t try to go so far myself, but this list is inspired by true events). It doesn’t matter how cool those tools are, keep calm and start with the basics. Keep advanced topics for advanced stages. One step at a time.&lt;/p&gt;
&lt;h3 id=&quot;take-advantage-of-what-they-already-know&quot;&gt;Take advantage of what they already know&lt;/h3&gt;
&lt;p&gt;If your students are familiar with a language you hate (say, MATLAB) it may be tempting to ask them to switch to your favorite one. It will be much easier to stick to their language of choice to teach some generally applicable principles, such as version control or unit testing. Switching from one language to another is extremely stressful for beginners.&lt;/p&gt;
&lt;h3 id=&quot;avoid-the-command-console&quot;&gt;Avoid the command console&lt;/h3&gt;
&lt;p&gt;Before crucifying me, let me explain myself. Yes, I love the command console, and I am allergic to (most) graphical user interfaces. One of the aspects I love about the console is that it forces me to keep in mind a clear structure of what I am doing. But when it comes to teaching, I don’t want to keep things in my mind. I want to share them as explicitly as possible. Graphical user interfaces are great for this.&lt;/p&gt;
&lt;p&gt;Last but not least, in a world dominated by graphical interfaces, the command console is very scary for most beginners. Yes, I know they &lt;em&gt;should not&lt;/em&gt; be scared (whatever that means), but the fact is that they are. Especially in the early stages, I suggest to avoid it as much as possible.&lt;/p&gt;
&lt;h3 id=&quot;make-education-acronym-free-again&quot;&gt;Make education acronym-free again&lt;/h3&gt;
&lt;p&gt;If like me, you are Spanish, the acronyms &lt;em&gt;PSOE&lt;/em&gt;, &lt;em&gt;IVA&lt;/em&gt; or &lt;em&gt;IRPF&lt;/em&gt; will be crystal clear for you. But most likely you, dear reader, are not from Spain. What did you feel while reading those acronyms? Probably something between slight annoyance and absolute nothingness. Well, beginners feel the same when they read &lt;em&gt;CI&lt;/em&gt;, &lt;em&gt;GUI&lt;/em&gt; or &lt;em&gt;CMD&lt;/em&gt; for the first time. And not only beginners: each time I see an acronym in the title of a talk I take it as a cue to skip it and go get a coffee.&lt;/p&gt;
&lt;p&gt;Using acronyms (and other jargon) with beginners is the quickest way to sound cryptic. Also, the easiest one to avoid.&lt;/p&gt;
&lt;h3 id=&quot;but-i-already-have-a-system&quot;&gt;But I already have a system!&lt;/h3&gt;
&lt;p&gt;“Why do I need Git? I have Dropbox!”, “I store my code in email drafts”, “The code compiles, why do I need tests?”…&lt;/p&gt;
&lt;p&gt;These kinds of questions will arise. Answer them once, and don’t insist much more, especially if they keep thinking their solution is good enough. For most people, it takes some time to abandon an old routine… but they are listening.&lt;/p&gt;
&lt;p&gt;The previous list doesn’t try to be exhaustive. This is just an open reflection on my own experience. Feel free to comment on your own. After all, all of us were beginners once.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_U-HMVgB8PS9IQXF0-845426ce.DM0BbbUC.webp" medium="image"/><author>Pablo Rodríguez-Sánchez</author></item><item><title>Between pencil and paper</title><link>https://blog2.esciencecenter.nl/posts/2019-12-11---between-pencil-and-paper</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-12-11---between-pencil-and-paper</guid><description>&lt;h2 id=&quot;how-artistic-elements-can-enrich-scientific-writing&quot;&gt;How artistic elements can enrich scientific writing&lt;/h2&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;I did a similar thing with figures. Matplotlib has this &lt;a href=&quot;http://jakevdp.github.io/blog/2013/07/10/XKCD-plots-in-matplotlib/&quot;&gt;awesome package&lt;/a&gt; that let’s you render all plots in a sketchy style, as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Between pencil and paper&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;331&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/between-pencil-and-paper-69248166.EARbDJAX_1gaTz5.webp&quot; srcset=&quot;&quot;&gt;
Example figure from my PhD thesis — rendered with matplotlib using xkcd-styleI used this style throughout my thesis and also in recent publications. One reviewer said: “I like this style and I think it makes the paper much more attractive and accessible (…) I assume the authors intend to convey that the results are to be seen with some uncertainty, and in this respect I would support the consistent use of the sketchy style”*.&lt;/p&gt;
&lt;p&gt;But he also warned: &lt;em&gt;“I believe that there will be some readers who will strongly object to this style and put the seriousness of the paper into question”&lt;/em&gt;. I couldn’t have said it better myself, and indeed, I have met some of those readers.&lt;/p&gt;
&lt;p&gt;Despite the criticism, I kept using these figures. For some reason, the reviewer’s comment about uncertainty stuck with me. Is it really about uncertainty? To some extent, yes, but isn’t that what error bars are for?&lt;/p&gt;
&lt;p&gt;To me, the most important aspect of these figures is that they convey a sense of subjectivity. A hand-drawn style makes the human dimension explicit. I am not flawless. Therefore, neither are my figures.&lt;/p&gt;
&lt;p&gt;What else can we do to make our research more attractive? Well, why not expand on this idea of a well-composed symphony? As suggested above, humor and (graphical) style can blend in to create a harmonic piece.&lt;/p&gt;
&lt;p&gt;Why not go one step further? What I really like about music is that it can do justice to an unresolved situation. It can leave you puzzled, fascinated, compassionate. When it comes to lyrics, sometimes the message gets stronger if the lyrics are vague.&lt;/p&gt;
&lt;p&gt;So I set out to write a sonnet about the circulation of the atmosphere. I had long been unable to put my thoughts on paper, because there were some nuances that I simply couldn’t capture accurately in words. The poetic license to &lt;em&gt;not&lt;/em&gt; be exact was a huge relief, and I recommend everyone to try it.&lt;/p&gt;
&lt;p&gt;For those interested, I copied the sonnet below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Between pencil and paper&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;645&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/between-pencil-and-paper-8b9596bf.CtS1YNYk_42H3y.webp&quot; srcset=&quot;&quot;&gt;
The sonnet printed on the first pages of my PhD thesis.This morning I presented some of my results to a friendly, scientific audience. Instead of focusing solely on content, I used some of my time to exchange thoughts on science communication. It was good to see that people welcome the initiative to express ourselves more freely.&lt;/p&gt;
&lt;p&gt;The best piece of advice was to stay close to your own style, and therein don’t feel limited by “the way in which a paper is supposed to be written”, or “how it’s always done”.&lt;/p&gt;
&lt;p&gt;By sharing my thoughts and experience, I hope to inspire others to experiment as well. I’m really interested to hear what you think about blending art and science. What are your experiences? And do you know other examples, or do you have ideas on where/how to share forms of science communication that do not fit with traditional journals?&lt;/p&gt;</description><pubDate>Wed, 11 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;how-artistic-elements-can-enrich-scientific-writing&quot;&gt;How artistic elements can enrich scientific writing&lt;/h2&gt;
&lt;p&gt;Subscribe*Remember me for faster sign in&lt;/p&gt;
&lt;p&gt;I did a similar thing with figures. Matplotlib has this &lt;a href=&quot;http://jakevdp.github.io/blog/2013/07/10/XKCD-plots-in-matplotlib/&quot;&gt;awesome package&lt;/a&gt; that let’s you render all plots in a sketchy style, as shown below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Between pencil and paper&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;331&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/between-pencil-and-paper-69248166.EARbDJAX_1gaTz5.webp&quot; srcset=&quot;&quot;&gt;
Example figure from my PhD thesis — rendered with matplotlib using xkcd-styleI used this style throughout my thesis and also in recent publications. One reviewer said: “I like this style and I think it makes the paper much more attractive and accessible (…) I assume the authors intend to convey that the results are to be seen with some uncertainty, and in this respect I would support the consistent use of the sketchy style”*.&lt;/p&gt;
&lt;p&gt;But he also warned: &lt;em&gt;“I believe that there will be some readers who will strongly object to this style and put the seriousness of the paper into question”&lt;/em&gt;. I couldn’t have said it better myself, and indeed, I have met some of those readers.&lt;/p&gt;
&lt;p&gt;Despite the criticism, I kept using these figures. For some reason, the reviewer’s comment about uncertainty stuck with me. Is it really about uncertainty? To some extent, yes, but isn’t that what error bars are for?&lt;/p&gt;
&lt;p&gt;To me, the most important aspect of these figures is that they convey a sense of subjectivity. A hand-drawn style makes the human dimension explicit. I am not flawless. Therefore, neither are my figures.&lt;/p&gt;
&lt;p&gt;What else can we do to make our research more attractive? Well, why not expand on this idea of a well-composed symphony? As suggested above, humor and (graphical) style can blend in to create a harmonic piece.&lt;/p&gt;
&lt;p&gt;Why not go one step further? What I really like about music is that it can do justice to an unresolved situation. It can leave you puzzled, fascinated, compassionate. When it comes to lyrics, sometimes the message gets stronger if the lyrics are vague.&lt;/p&gt;
&lt;p&gt;So I set out to write a sonnet about the circulation of the atmosphere. I had long been unable to put my thoughts on paper, because there were some nuances that I simply couldn’t capture accurately in words. The poetic license to &lt;em&gt;not&lt;/em&gt; be exact was a huge relief, and I recommend everyone to try it.&lt;/p&gt;
&lt;p&gt;For those interested, I copied the sonnet below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Between pencil and paper&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;645&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/between-pencil-and-paper-8b9596bf.CtS1YNYk_42H3y.webp&quot; srcset=&quot;&quot;&gt;
The sonnet printed on the first pages of my PhD thesis.This morning I presented some of my results to a friendly, scientific audience. Instead of focusing solely on content, I used some of my time to exchange thoughts on science communication. It was good to see that people welcome the initiative to express ourselves more freely.&lt;/p&gt;
&lt;p&gt;The best piece of advice was to stay close to your own style, and therein don’t feel limited by “the way in which a paper is supposed to be written”, or “how it’s always done”.&lt;/p&gt;
&lt;p&gt;By sharing my thoughts and experience, I hope to inspire others to experiment as well. I’m really interested to hear what you think about blending art and science. What are your experiences? And do you know other examples, or do you have ideas on where/how to share forms of science communication that do not fit with traditional journals?&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/between-pencil-and-paper-69248166.EARbDJAX.png" medium="image"/><author>Peter Kalverla</author></item><item><title>Managing the crowd: a big data approach</title><link>https://blog2.esciencecenter.nl/posts/2019-12-09---managing-the-crowd-a-big-data-approach</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-12-09---managing-the-crowd-a-big-data-approach</guid><description>&lt;p&gt;Crowd disasters have taken many lives. The Love Parade disaster (Duisburg, 2010), the Ellis Park Stadium disaster (Johannesburg, 2001), the PhilSports Stadium stampede (Manila, 2006) are just a few recent examples. Nevertheless, controlling crowds remains an unsolved problem, one that arises from the fact that in dense crowds, a “normal” situation may suddenly turn into a dangerous situation in the event of panic and that these changes are very difficult to predict as well as prevent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2560&quot; height=&quot;1706&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dC65WeOXSSMeMyLsB9Ey5Q-b01d2f53.JGhy6-Dp_22rWDe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The project “Detecting Anomalous Behavior in Stadium Crowds” was started in 2016. This project, led by Professor Sander Klous from the University of Amsterdam (UvA) and supported by the Netherlands eScience Center, attempts to model crowd behavior based on data gathered from the Wi-Fi signals of the smart phones of the participants in a crowd.&lt;/p&gt;
&lt;p&gt;Dr Sonja Georgievska, eScience Research Engineer at the eScience Center, has been closely involved in the project, which recently ended. In the following interview, she talks about the aims and challenges of the project and looks back at the progress that was made.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Would you briefly describe the project and its aims?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The project was a collaboration between the University of Amsterdam, The Amsterdam ArenA (presently Johan Cruijff ArenA) Research and Innovation Lab, and the Netherlands eScience Center. It was one of the alliance projects, in which both the eScience Center and the project partners collaborate and mutually benefit from knowledge exchange, in this case regarding Big Data Analytics.&lt;/p&gt;
&lt;p&gt;The scientific goal was to enable the detection of dangerous crowd behavior such as high-density spots, in real time, for the purposes of avoiding crowd disasters. Amsterdam ArenA was a so-called living lab, where data about the movements of concert visitors was anonymously collected via the Wi-Fi probing signals from their smart phones and the Wi-Fi network. The data collection and user localization analytics were performed by the team of Sander Klous, professor of Big Data Ecosystems for Business and Society.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What was your role in the project?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, we wrote the project proposal together with the project partners. I subsequently worked on analytical methods for detecting dangerous crowd behavior based on the collected localization data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1867&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9LVsRWtXWQ0ysGRfAmbJZg-f9f0df37.B2H4j4T__Z1MnNQw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How long were you involved?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;About 1.5 years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What were some of the challenges you faced in the project?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our initial plans were to use data from crowd simulators to train machine learning algorithms to recognize dangerous situations. The trained neural network would then be able to recognize such situations live, when applied on the visitors’ locations as estimated from phone data. However, after analyzing the “localization” data, we quickly realized that our goals are unattainable due to the localization ambiguity observed from the data.&lt;/p&gt;
&lt;p&gt;Digging deeper into this problem, I found out that it was in theory unsolvable. So we needed another plan. I subsequently proposed we use a probabilistic model instead, so as to be able to estimate the crowd density based on the data at hand. This approach, inspired by statistical mechanics, takes advantage of the large amount of data and bypasses the ambiguity problem. We also applied the same “big data” approach to other issues related to imperfections of the data source. However, this was not the end of the challenges. Another problem was to find ways to analyze experimentally our methodology, because a theoretical validation by itself cannot yield practical error estimates. Thus, most of my efforts and time, as well as that of the PhD student Philip Rutten, were spent on this last part.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Were the project aims achieved?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The solutions to the aforementioned problems were documented in the article “ &lt;a href=&quot;https://link.springer.com/epdf/10.1186/s40537-019-0194-3?author_access_token=LQ3AsWc2lq7dXDR1BnVo7m_BpE1tBhCbnbw3BuzI2RPQC37zeIK9tWYgVfnoEwKL8vmjNY0D5TTQLTqxST1MSryuuybsO3YJtCNOHMgWC2iZV1wP3MuOYWAG_Zy1KHz2Wuf0trh_piZtkvLtacc2_A%3D%3D&quot;&gt;Detecting high indoor crowd density with Wi‑Fi localization: a statistical mechanics approach&lt;/a&gt; ”, published this year in the &lt;em&gt;Journal of Big Data&lt;/em&gt;. So yes, we are happy with the output.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;2667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NtSb4Dm-5QgnbSwyKG6rCw-9fec2cf3.BdZP23b5_2tpKDn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What was the single most important insight you gained from this project (e.g. on crowd behavior and algorithmic prediction?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Despite the imperfections in the data source, in this case signals from smart phones, and despite some remaining theoretical limitations for tracking individual users, the availability of so much data, technology and the big-data-analytics approach allowed us to analyze the crowd as a whole. To do this, we combined classical mathematics from the 19th and 20th century, physics from the 20th century, and big data technologies from the 21st century in one package, which was very exciting in itself!&lt;/p&gt;
&lt;p&gt;Read more about the &lt;a href=&quot;https://esciencecenter.nl/project/detecting-anomalous-behavior-in-stadium-crowds&quot;&gt;project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://esciencecenter.nl/profile/dr.-sonja-georgievska&quot;&gt;Sonja Georgievska&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 09 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Crowd disasters have taken many lives. The Love Parade disaster (Duisburg, 2010), the Ellis Park Stadium disaster (Johannesburg, 2001), the PhilSports Stadium stampede (Manila, 2006) are just a few recent examples. Nevertheless, controlling crowds remains an unsolved problem, one that arises from the fact that in dense crowds, a “normal” situation may suddenly turn into a dangerous situation in the event of panic and that these changes are very difficult to predict as well as prevent.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2560&quot; height=&quot;1706&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dC65WeOXSSMeMyLsB9Ey5Q-b01d2f53.JGhy6-Dp_22rWDe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The project “Detecting Anomalous Behavior in Stadium Crowds” was started in 2016. This project, led by Professor Sander Klous from the University of Amsterdam (UvA) and supported by the Netherlands eScience Center, attempts to model crowd behavior based on data gathered from the Wi-Fi signals of the smart phones of the participants in a crowd.&lt;/p&gt;
&lt;p&gt;Dr Sonja Georgievska, eScience Research Engineer at the eScience Center, has been closely involved in the project, which recently ended. In the following interview, she talks about the aims and challenges of the project and looks back at the progress that was made.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Would you briefly describe the project and its aims?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The project was a collaboration between the University of Amsterdam, The Amsterdam ArenA (presently Johan Cruijff ArenA) Research and Innovation Lab, and the Netherlands eScience Center. It was one of the alliance projects, in which both the eScience Center and the project partners collaborate and mutually benefit from knowledge exchange, in this case regarding Big Data Analytics.&lt;/p&gt;
&lt;p&gt;The scientific goal was to enable the detection of dangerous crowd behavior such as high-density spots, in real time, for the purposes of avoiding crowd disasters. Amsterdam ArenA was a so-called living lab, where data about the movements of concert visitors was anonymously collected via the Wi-Fi probing signals from their smart phones and the Wi-Fi network. The data collection and user localization analytics were performed by the team of Sander Klous, professor of Big Data Ecosystems for Business and Society.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What was your role in the project?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, we wrote the project proposal together with the project partners. I subsequently worked on analytical methods for detecting dangerous crowd behavior based on the collected localization data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1867&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9LVsRWtXWQ0ysGRfAmbJZg-f9f0df37.B2H4j4T__Z1MnNQw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How long were you involved?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;About 1.5 years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What were some of the challenges you faced in the project?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Our initial plans were to use data from crowd simulators to train machine learning algorithms to recognize dangerous situations. The trained neural network would then be able to recognize such situations live, when applied on the visitors’ locations as estimated from phone data. However, after analyzing the “localization” data, we quickly realized that our goals are unattainable due to the localization ambiguity observed from the data.&lt;/p&gt;
&lt;p&gt;Digging deeper into this problem, I found out that it was in theory unsolvable. So we needed another plan. I subsequently proposed we use a probabilistic model instead, so as to be able to estimate the crowd density based on the data at hand. This approach, inspired by statistical mechanics, takes advantage of the large amount of data and bypasses the ambiguity problem. We also applied the same “big data” approach to other issues related to imperfections of the data source. However, this was not the end of the challenges. Another problem was to find ways to analyze experimentally our methodology, because a theoretical validation by itself cannot yield practical error estimates. Thus, most of my efforts and time, as well as that of the PhD student Philip Rutten, were spent on this last part.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Were the project aims achieved?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The solutions to the aforementioned problems were documented in the article “ &lt;a href=&quot;https://link.springer.com/epdf/10.1186/s40537-019-0194-3?author_access_token=LQ3AsWc2lq7dXDR1BnVo7m_BpE1tBhCbnbw3BuzI2RPQC37zeIK9tWYgVfnoEwKL8vmjNY0D5TTQLTqxST1MSryuuybsO3YJtCNOHMgWC2iZV1wP3MuOYWAG_Zy1KHz2Wuf0trh_piZtkvLtacc2_A%3D%3D&quot;&gt;Detecting high indoor crowd density with Wi‑Fi localization: a statistical mechanics approach&lt;/a&gt; ”, published this year in the &lt;em&gt;Journal of Big Data&lt;/em&gt;. So yes, we are happy with the output.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;2667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NtSb4Dm-5QgnbSwyKG6rCw-9fec2cf3.BdZP23b5_2tpKDn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What was the single most important insight you gained from this project (e.g. on crowd behavior and algorithmic prediction?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Despite the imperfections in the data source, in this case signals from smart phones, and despite some remaining theoretical limitations for tracking individual users, the availability of so much data, technology and the big-data-analytics approach allowed us to analyze the crowd as a whole. To do this, we combined classical mathematics from the 19th and 20th century, physics from the 20th century, and big data technologies from the 21st century in one package, which was very exciting in itself!&lt;/p&gt;
&lt;p&gt;Read more about the &lt;a href=&quot;https://esciencecenter.nl/project/detecting-anomalous-behavior-in-stadium-crowds&quot;&gt;project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://esciencecenter.nl/profile/dr.-sonja-georgievska&quot;&gt;Sonja Georgievska&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_dC65WeOXSSMeMyLsB9Ey5Q-b01d2f53.JGhy6-Dp.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>FAIR Software at the 2019 eScience Symposium</title><link>https://blog2.esciencecenter.nl/posts/2019-12-02---fair-software-at-the-2019-escience-symposium</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-12-02---fair-software-at-the-2019-escience-symposium</guid><description>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;An important part of giving proper attribution is to make your software citable and to cite others when you build upon their work. Stephan and others have developed the Citation File Format (&lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;https://citation-file-format.github.io/&lt;/a&gt;), a metadata format for both humans and machines. While these citation files can be read and manually written, there is also an entire toolbox available to support creation, validation, and conversion of CFF files, and automation is on the horizon, with build plugins and automated updates.&lt;/p&gt;
&lt;p&gt;Stephan’s slides are available at:
&lt;a href=&quot;https://sdruskat.net/2019-11-21-nl-escience-symposium/&quot;&gt;https://sdruskat.net/2019-11-21-nl-escience-symposium/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;pablo-rodríguez-sánchez-how-software-development-shaped-the-way-i-write-science&quot;&gt;Pablo Rodríguez-Sánchez: How software development shaped the way I write science&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;FAIR Software at the 2019 eScience Symposium&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/fair-software-at-the-2019-escience-sympo-80880d4e.C-xnprtE_1smpKU.webp&quot; srcset=&quot;&quot;&gt;
Pablo Rodríguez-Sánchez is working as an RSE at the Netherlands eScience Center. His talk was about how software development shaped the way he writes about his research.&lt;/p&gt;
&lt;p&gt;With a great example of communication between Johannes Kepler and Galileo Galilei, Pablo confronted the audience with the fact that, despite great advances in the means of information and communication technology, some parts of scientific communication have not improved over the last four hundred years.&lt;/p&gt;
&lt;p&gt;Pablo defines a scientific paper as a trustworthy and useful piece of encapsulated knowledge, and argues that there are actually many parallels between scientific papers and software. Both should adhere to the properties: consistency, reproducibility, being properly written, having references/dependencies, written by a team, and evolving over time. Instead of only using software development tools to write his paper, Pablo, inspired in what &lt;a href=&quot;https://www.carlboettiger.info/2012/05/06/research-workflow.html&quot;&gt;other researchers&lt;/a&gt; did before, takes it one step further and writes software packages whose output is the paper.&lt;/p&gt;
&lt;p&gt;Using a combination of markdown and knitr, Pablo writes his papers as software packages in a way that all of the content of the paper, graphs and all can be fully reproduced by others who run the software.&lt;/p&gt;
&lt;p&gt;Pablo’s slides are available at:
&lt;a href=&quot;https://pabrod.github.io/NLeSC_symp19-en.html#NLeSC_symp19&quot;&gt;https://pabrod.github.io/NLeSC_symp19-en.html#NLeSC_symp19&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;panel-discussion&quot;&gt;Panel Discussion&lt;/h2&gt;
&lt;p&gt;Following the tree talks our speakers gathered on one side of the table for the panel discussion. While Ben was chairing the discussion, James was analyzing the questions that were submitted to mentimeter. The discussion involved questions such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What does metadata mean in the context of software?&lt;/li&gt;
&lt;li&gt;How to make software dependencies FAIR as well?&lt;/li&gt;
&lt;li&gt;Should FAIR Software imply open source?&lt;/li&gt;
&lt;li&gt;Does FAIR/Open Software conflict with the university’s striving for spin-offs/patents/commercialization?&lt;/li&gt;
&lt;li&gt;The discussions are all quite abstract, what can we do concretely?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anna-Lena, Stephan, Pablo and also several attendees of the session shared their insights, experiences, perspectives and some speculations, making it a lively and inspiring session.&lt;/p&gt;
&lt;p&gt;With regard to the question what to do concretely, Pablo mentioned “that the main bottleneck for FAIR software is, still, much more basic: many researchers who would like to share their code with FAIRness just don’t know how to begin.” In an effort to provide some concrete pointers on where to begin with making software FAIR, the Netherlands eScience Center and DANS developed &lt;a href=&quot;http://fair-software.nl&quot;&gt;fair-software.nl&lt;/a&gt;, which was officially launched later that day at the symposium.&lt;/p&gt;
&lt;p&gt;If you would like to join the discussion on FAIR Software, the session’s organizers and the speakers of this session will be using the #fair-software on the &lt;a href=&quot;http://ukrse.slack.com&quot;&gt;RSE slack server&lt;/a&gt; to continue the discussion on FAIR Software.&lt;/p&gt;</description><pubDate>Mon, 02 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;An important part of giving proper attribution is to make your software citable and to cite others when you build upon their work. Stephan and others have developed the Citation File Format (&lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;https://citation-file-format.github.io/&lt;/a&gt;), a metadata format for both humans and machines. While these citation files can be read and manually written, there is also an entire toolbox available to support creation, validation, and conversion of CFF files, and automation is on the horizon, with build plugins and automated updates.&lt;/p&gt;
&lt;p&gt;Stephan’s slides are available at:
&lt;a href=&quot;https://sdruskat.net/2019-11-21-nl-escience-symposium/&quot;&gt;https://sdruskat.net/2019-11-21-nl-escience-symposium/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;pablo-rodríguez-sánchez-how-software-development-shaped-the-way-i-write-science&quot;&gt;Pablo Rodríguez-Sánchez: How software development shaped the way I write science&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;FAIR Software at the 2019 eScience Symposium&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;700&quot; height=&quot;467&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/fair-software-at-the-2019-escience-sympo-80880d4e.C-xnprtE_1smpKU.webp&quot; srcset=&quot;&quot;&gt;
Pablo Rodríguez-Sánchez is working as an RSE at the Netherlands eScience Center. His talk was about how software development shaped the way he writes about his research.&lt;/p&gt;
&lt;p&gt;With a great example of communication between Johannes Kepler and Galileo Galilei, Pablo confronted the audience with the fact that, despite great advances in the means of information and communication technology, some parts of scientific communication have not improved over the last four hundred years.&lt;/p&gt;
&lt;p&gt;Pablo defines a scientific paper as a trustworthy and useful piece of encapsulated knowledge, and argues that there are actually many parallels between scientific papers and software. Both should adhere to the properties: consistency, reproducibility, being properly written, having references/dependencies, written by a team, and evolving over time. Instead of only using software development tools to write his paper, Pablo, inspired in what &lt;a href=&quot;https://www.carlboettiger.info/2012/05/06/research-workflow.html&quot;&gt;other researchers&lt;/a&gt; did before, takes it one step further and writes software packages whose output is the paper.&lt;/p&gt;
&lt;p&gt;Using a combination of markdown and knitr, Pablo writes his papers as software packages in a way that all of the content of the paper, graphs and all can be fully reproduced by others who run the software.&lt;/p&gt;
&lt;p&gt;Pablo’s slides are available at:
&lt;a href=&quot;https://pabrod.github.io/NLeSC_symp19-en.html#NLeSC_symp19&quot;&gt;https://pabrod.github.io/NLeSC_symp19-en.html#NLeSC_symp19&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;panel-discussion&quot;&gt;Panel Discussion&lt;/h2&gt;
&lt;p&gt;Following the tree talks our speakers gathered on one side of the table for the panel discussion. While Ben was chairing the discussion, James was analyzing the questions that were submitted to mentimeter. The discussion involved questions such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What does metadata mean in the context of software?&lt;/li&gt;
&lt;li&gt;How to make software dependencies FAIR as well?&lt;/li&gt;
&lt;li&gt;Should FAIR Software imply open source?&lt;/li&gt;
&lt;li&gt;Does FAIR/Open Software conflict with the university’s striving for spin-offs/patents/commercialization?&lt;/li&gt;
&lt;li&gt;The discussions are all quite abstract, what can we do concretely?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anna-Lena, Stephan, Pablo and also several attendees of the session shared their insights, experiences, perspectives and some speculations, making it a lively and inspiring session.&lt;/p&gt;
&lt;p&gt;With regard to the question what to do concretely, Pablo mentioned “that the main bottleneck for FAIR software is, still, much more basic: many researchers who would like to share their code with FAIRness just don’t know how to begin.” In an effort to provide some concrete pointers on where to begin with making software FAIR, the Netherlands eScience Center and DANS developed &lt;a href=&quot;http://fair-software.nl&quot;&gt;fair-software.nl&lt;/a&gt;, which was officially launched later that day at the symposium.&lt;/p&gt;
&lt;p&gt;If you would like to join the discussion on FAIR Software, the session’s organizers and the speakers of this session will be using the #fair-software on the &lt;a href=&quot;http://ukrse.slack.com&quot;&gt;RSE slack server&lt;/a&gt; to continue the discussion on FAIR Software.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/fair-software-at-the-2019-escience-sympo-80880d4e.C-xnprtE.jpg" medium="image"/><author>Ben van Werkhoven</author></item><item><title>Accelerating the search for dark matter</title><link>https://blog2.esciencecenter.nl/posts/2019-11-28---accelerating-the-search-for-dark-matter</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-11-28---accelerating-the-search-for-dark-matter</guid><description>&lt;p&gt;Astronomical observations show that roughly 80% of the mass of the universe is made up of dark matter, a material that cannot be directly observed because emits no light or energy. Although dark matter has never been detected directly, astronomers know it exists because something in the universe is exerting significant gravitational forces on visible matter. Nevertheless, its exact nature remains unknown.**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Kim-Anh Holthaus&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;1600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-bcace106.Cuv2Xrpc_10RTic.webp&quot; srcset=&quot;&quot;&gt;
Left to right: Faruk Diblen, Bob Stienen, Luc Hendriks, Rena Bakhshi and Sascha CaronToday, one of the biggest objectives within the fields of physics and astronomy is to determine the nature of Dark Matter. It is widely expected that any success in doing so will come about by bringing together and sharing all worldwide available experimental data.&lt;/p&gt;
&lt;h2 id=&quot;harnessing-interdisciplinarity&quot;&gt;Harnessing interdisciplinarity&lt;/h2&gt;
&lt;p&gt;The iDark project aims to combine the worldwide data within the most general models of Dark Matter. Led by Dr Sascha Caron and supported by the Netherlands eScience Center, iDark was launched in 2015 as a platform to bring together expertise in particle physics, physics, astrophysics, eScience and machine learning. Its aim is to test the models, determine the allowed parameter space for dark matter and help focus the effort for experimental searches.&lt;/p&gt;
&lt;p&gt;“The project comprises two main technological components”, says Faruk Diblen, eScience Research Engineer and part of the project team. “On the one hand it focuses on using cutting-edge Artificial Intelligence to classify models for hypothetical dark matter, and on the other it aims to develop an open science platform on which interactive data visualization can be done in a collaborative way.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-7347bcdb.CLQtXzTY_1loWpt.webp&quot; srcset=&quot;&quot;&gt;
iDark builds on research carried out Dr Caron, whose main focus is on physics beyond the Standard Model, especially on the search for candidates for Dark Matter. “Over the past twenty odd years, I have been trying to automate searches for new physics and Dark Matter, which can be done with or without the use of candidate models. My research is based on analyzing large amounts of data, grouping data, learning patterns and searching for anomalies. As such, it is strongly linked to eScience, data science, high-performance computing and machine learning.”&lt;/p&gt;
&lt;h2 id=&quot;spot-the-collaboration&quot;&gt;SPOT the collaboration&lt;/h2&gt;
&lt;p&gt;One of the tools that have so far been developed within the project is SPOT, a platform that allows researchers to share and present their data sets publicly through interactive dashboards.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-d422315b.uuKUUfic_6Ebq8.webp&quot; srcset=&quot;&quot;&gt;
“SPOT came about through the hard work of my fellow engineer, Jisk Attema, who worked on the software in his spare time and realized that it could be used for iDark. While developing SPOT for iDark project, we realized that it can also be used in many other domains in which numerical data is the primary data type. It helps scientists to make visualizations of multi-dimensional data and open science.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“While developing SPOT for iDark project, we realized that it can also be used in many other domains in which numerical data is the primary data type.”&lt;/p&gt;
&lt;p&gt;According to Bob Stienen, PhD researcher at Radboud University and closely involved in iDark, the collaboration between the different groups has provided a major boost to the project. “iDark is structured in three distinct research directions, all of which intersect in their aim to make the interpretation of high-dimensional data easier. Although I worked on one aspect (machine learning), my research benefited immensely from the expertise and resources provided by the Netherlands eScience Center.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-35aea07b.DBc5tZDR_2nrIIB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The experts from the eScience Center brought new knowledge on developing web-based data platforms…we wouldn’t have had the ability to work on such large-scale software projects without them.”*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Caron agrees: “The experts from the eScience Center brought new knowledge on developing web-based data platforms. The input provided by Rena and Faruk (eScience Engineers, ed.) was invaluable and only reinforced my view that research depends on successful teamwork and on everyone contributing their own unique skills and expertise. We wouldn’t have had the ability to work on such large-scale software projects without them.”&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://esciencecenter.nl/project/idark&quot;&gt;iDark&lt;/a&gt;
Read more about &lt;a href=&quot;https://www.nikhef.nl/~scaron/&quot;&gt;Sascha Caron&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 28 Nov 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Astronomical observations show that roughly 80% of the mass of the universe is made up of dark matter, a material that cannot be directly observed because emits no light or energy. Although dark matter has never been detected directly, astronomers know it exists because something in the universe is exerting significant gravitational forces on visible matter. Nevertheless, its exact nature remains unknown.**&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Kim-Anh Holthaus&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;1600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-bcace106.Cuv2Xrpc_10RTic.webp&quot; srcset=&quot;&quot;&gt;
Left to right: Faruk Diblen, Bob Stienen, Luc Hendriks, Rena Bakhshi and Sascha CaronToday, one of the biggest objectives within the fields of physics and astronomy is to determine the nature of Dark Matter. It is widely expected that any success in doing so will come about by bringing together and sharing all worldwide available experimental data.&lt;/p&gt;
&lt;h2 id=&quot;harnessing-interdisciplinarity&quot;&gt;Harnessing interdisciplinarity&lt;/h2&gt;
&lt;p&gt;The iDark project aims to combine the worldwide data within the most general models of Dark Matter. Led by Dr Sascha Caron and supported by the Netherlands eScience Center, iDark was launched in 2015 as a platform to bring together expertise in particle physics, physics, astrophysics, eScience and machine learning. Its aim is to test the models, determine the allowed parameter space for dark matter and help focus the effort for experimental searches.&lt;/p&gt;
&lt;p&gt;“The project comprises two main technological components”, says Faruk Diblen, eScience Research Engineer and part of the project team. “On the one hand it focuses on using cutting-edge Artificial Intelligence to classify models for hypothetical dark matter, and on the other it aims to develop an open science platform on which interactive data visualization can be done in a collaborative way.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-7347bcdb.CLQtXzTY_1loWpt.webp&quot; srcset=&quot;&quot;&gt;
iDark builds on research carried out Dr Caron, whose main focus is on physics beyond the Standard Model, especially on the search for candidates for Dark Matter. “Over the past twenty odd years, I have been trying to automate searches for new physics and Dark Matter, which can be done with or without the use of candidate models. My research is based on analyzing large amounts of data, grouping data, learning patterns and searching for anomalies. As such, it is strongly linked to eScience, data science, high-performance computing and machine learning.”&lt;/p&gt;
&lt;h2 id=&quot;spot-the-collaboration&quot;&gt;SPOT the collaboration&lt;/h2&gt;
&lt;p&gt;One of the tools that have so far been developed within the project is SPOT, a platform that allows researchers to share and present their data sets publicly through interactive dashboards.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-d422315b.uuKUUfic_6Ebq8.webp&quot; srcset=&quot;&quot;&gt;
“SPOT came about through the hard work of my fellow engineer, Jisk Attema, who worked on the software in his spare time and realized that it could be used for iDark. While developing SPOT for iDark project, we realized that it can also be used in many other domains in which numerical data is the primary data type. It helps scientists to make visualizations of multi-dimensional data and open science.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“While developing SPOT for iDark project, we realized that it can also be used in many other domains in which numerical data is the primary data type.”&lt;/p&gt;
&lt;p&gt;According to Bob Stienen, PhD researcher at Radboud University and closely involved in iDark, the collaboration between the different groups has provided a major boost to the project. “iDark is structured in three distinct research directions, all of which intersect in their aim to make the interpretation of high-dimensional data easier. Although I worked on one aspect (machine learning), my research benefited immensely from the expertise and resources provided by the Netherlands eScience Center.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Accelerating the search for dark matter&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-35aea07b.DBc5tZDR_2nrIIB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The experts from the eScience Center brought new knowledge on developing web-based data platforms…we wouldn’t have had the ability to work on such large-scale software projects without them.”*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Caron agrees: “The experts from the eScience Center brought new knowledge on developing web-based data platforms. The input provided by Rena and Faruk (eScience Engineers, ed.) was invaluable and only reinforced my view that research depends on successful teamwork and on everyone contributing their own unique skills and expertise. We wouldn’t have had the ability to work on such large-scale software projects without them.”&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://esciencecenter.nl/project/idark&quot;&gt;iDark&lt;/a&gt;
Read more about &lt;a href=&quot;https://www.nikhef.nl/~scaron/&quot;&gt;Sascha Caron&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/accelerating-the-search-for-dark-matter-bcace106.Cuv2Xrpc.jpeg" medium="image"/><author>Netherlands eScience Center</author></item><item><title>Optimizing plasma sources through numerical simulation</title><link>https://blog2.esciencecenter.nl/posts/2019-11-28---optimizing-plasma-sources-through-numerical-simulation</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-11-28---optimizing-plasma-sources-through-numerical-simulation</guid><description>&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;800&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-d4fbc88f.4AutyaV-_hzFtn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;optimizing-plasma-sources-through-numerical-simulation&quot;&gt;Optimizing plasma sources through numerical simulation&lt;/h1&gt;
&lt;p&gt;Cold plasma sources are promising devices for the transformation of carbon dioxide into methane and other value-added chemicals. These sources have numerous other important technological applications and as such are the focus of many projects currently carried out with industrial research partners.**&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-67412b5b.ClMGPqeB_8HiaS.webp&quot; srcset=&quot;&quot;&gt;
From left to right: Wouter Graef, Jan van Dijk, Stefan Verhoeven, Nicolas Renaud, Chris Schoutrop., Adithya VijaykumarAt the Modeling Section of the group Elementary Processes in Gas Discharges at Eindhoven University of Technology, extensive research is being done on gaining a better understanding of cold plasma sources and on using this knowledge to optimize these plasma sources with the help of modelling and numerical simulation. Doing so, however, requires managing and reducing chemical complexity, and the ability to successfully exchange underlying data sets and tools with peers and end-users. The project Passing XSAMS, led by Dr. Jan van Dijk from TU Eindhoven and supported by the Netherlands eScience Center, targets both. Its aim is to develop efficient numerical schemes to simulate the transport fluxes in multi-component mixtures and develop new data exchange formats.&lt;/p&gt;
&lt;h2 id=&quot;magnumpi&quot;&gt;MagnumPI**&lt;/h2&gt;
&lt;p&gt;“The project came at the perfect moment”, says Van Dijk, who is associate professor of Applied Physics. “We were looking for opportunities to fund the work on these themes, which is not always easy because they require a blend of physical, computational mathematics and networking expertise that is difficult to come by. XAMS matched our needs perfectly and has been a true game changer.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-7ee518e9.DHduMLFN_ZbTydO.webp&quot; srcset=&quot;&quot;&gt;
According to Van Dijk, work in all three areas has progressed significantly. Two new iterative matrix solvers have been implemented for the Eigen matrix-vector library and will be made available to the community after further testing and documentation. The mathematics of multi-component mixtures have been clarified significantly and new transport flux schemes are on the way. In addition, new data formats are currently being tested in a code that integrates inter-atomic potentials into cross sections and other quantities of interest for transport simulations. This code, called MagnumPI, will be made available to the community in the near future.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“The collaboration with the eScience Center has been a wonderful experience.” — Jan van Dijk&lt;/p&gt;
&lt;p&gt;Stefan Verhoeven, senior research engineer at the eScience Center, was closely involved in the development of MagnumPI. ‘The tool can calculate different aspects of two particles such as atoms crashing into each other”, says Verhoeven. “We wrote it in C++ and wrapped it into a web application. In addition, we developed the tool with a clear focus on making it compatible with open formats and ensuring it is unit aware.” In addition to MagnumPI, the eScience Center team, which includes Verhoeven and Dr Adithya Vijaykumar, also standardized the input and output formats of the command line, web service and web application using JSON schemas, thereby making it possible to take C++ functions and run them in a web browser without the need for server compute power.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-75eb9831.ByfUxeZp_1n1u07.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;own-language-unique-expertise&quot;&gt;&lt;strong&gt;Own language, unique expertise&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The project has benefitted immensely from the unique expertise each project member brings to the table, says Van Dijk. “The collaboration with the eScience Center has been a wonderful experience. The combination of the eScience knowledge of Adithhya and Stefan in their respective fields of expertise with the domain-specific knowledge on plasmas at TU/e and project partner Plasma Matters B.V. has resulted in progress that until recently I had not even dared to hope for.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“I really believe that our own vocabularies and set of expertise combined nicely to accelerate the rate of progress we made in the project. It has been a great experience.”&lt;/p&gt;
&lt;p&gt;While extremely fruitful, the collaborative effort wasn’t without its own set of challenges, says Verhoeven. “I previously worked in the pharmaceutical industry where a lot of use was made of molecular dynamics. The XAMS project uses some of the same terminology, but also terms that have a completely different meaning. For example, the term ‘species’ has a very clear meaning to most people, but in plasma physics it refers to a type of particle. This domain-specific language took some time getting used to, especially the abbreviations. Luckily, the project partners were extremely patient in explaining their domains and the problems they face. I really believe that our own vocabularies and set of expertise combined nicely to accelerate the rate of progress we made in the project. It has been a great experience.”&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://www.esciencecenter.nl/project/passing-xsams&quot;&gt;Passing XSAMS&lt;/a&gt;
Read more about &lt;a href=&quot;https://www.tue.nl/en/research/researchers/jan-van-dijk/&quot;&gt;Jan van Dijk&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 28 Nov 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;800&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-d4fbc88f.4AutyaV-_hzFtn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;optimizing-plasma-sources-through-numerical-simulation&quot;&gt;Optimizing plasma sources through numerical simulation&lt;/h1&gt;
&lt;p&gt;Cold plasma sources are promising devices for the transformation of carbon dioxide into methane and other value-added chemicals. These sources have numerous other important technological applications and as such are the focus of many projects currently carried out with industrial research partners.**&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-67412b5b.ClMGPqeB_8HiaS.webp&quot; srcset=&quot;&quot;&gt;
From left to right: Wouter Graef, Jan van Dijk, Stefan Verhoeven, Nicolas Renaud, Chris Schoutrop., Adithya VijaykumarAt the Modeling Section of the group Elementary Processes in Gas Discharges at Eindhoven University of Technology, extensive research is being done on gaining a better understanding of cold plasma sources and on using this knowledge to optimize these plasma sources with the help of modelling and numerical simulation. Doing so, however, requires managing and reducing chemical complexity, and the ability to successfully exchange underlying data sets and tools with peers and end-users. The project Passing XSAMS, led by Dr. Jan van Dijk from TU Eindhoven and supported by the Netherlands eScience Center, targets both. Its aim is to develop efficient numerical schemes to simulate the transport fluxes in multi-component mixtures and develop new data exchange formats.&lt;/p&gt;
&lt;h2 id=&quot;magnumpi&quot;&gt;MagnumPI**&lt;/h2&gt;
&lt;p&gt;“The project came at the perfect moment”, says Van Dijk, who is associate professor of Applied Physics. “We were looking for opportunities to fund the work on these themes, which is not always easy because they require a blend of physical, computational mathematics and networking expertise that is difficult to come by. XAMS matched our needs perfectly and has been a true game changer.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-7ee518e9.DHduMLFN_ZbTydO.webp&quot; srcset=&quot;&quot;&gt;
According to Van Dijk, work in all three areas has progressed significantly. Two new iterative matrix solvers have been implemented for the Eigen matrix-vector library and will be made available to the community after further testing and documentation. The mathematics of multi-component mixtures have been clarified significantly and new transport flux schemes are on the way. In addition, new data formats are currently being tested in a code that integrates inter-atomic potentials into cross sections and other quantities of interest for transport simulations. This code, called MagnumPI, will be made available to the community in the near future.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“The collaboration with the eScience Center has been a wonderful experience.” — Jan van Dijk&lt;/p&gt;
&lt;p&gt;Stefan Verhoeven, senior research engineer at the eScience Center, was closely involved in the development of MagnumPI. ‘The tool can calculate different aspects of two particles such as atoms crashing into each other”, says Verhoeven. “We wrote it in C++ and wrapped it into a web application. In addition, we developed the tool with a clear focus on making it compatible with open formats and ensuring it is unit aware.” In addition to MagnumPI, the eScience Center team, which includes Verhoeven and Dr Adithya Vijaykumar, also standardized the input and output formats of the command line, web service and web application using JSON schemas, thereby making it possible to take C++ functions and run them in a web browser without the need for server compute power.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Optimizing plasma sources through numerical simulation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-75eb9831.ByfUxeZp_1n1u07.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;own-language-unique-expertise&quot;&gt;&lt;strong&gt;Own language, unique expertise&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The project has benefitted immensely from the unique expertise each project member brings to the table, says Van Dijk. “The collaboration with the eScience Center has been a wonderful experience. The combination of the eScience knowledge of Adithhya and Stefan in their respective fields of expertise with the domain-specific knowledge on plasmas at TU/e and project partner Plasma Matters B.V. has resulted in progress that until recently I had not even dared to hope for.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;“I really believe that our own vocabularies and set of expertise combined nicely to accelerate the rate of progress we made in the project. It has been a great experience.”&lt;/p&gt;
&lt;p&gt;While extremely fruitful, the collaborative effort wasn’t without its own set of challenges, says Verhoeven. “I previously worked in the pharmaceutical industry where a lot of use was made of molecular dynamics. The XAMS project uses some of the same terminology, but also terms that have a completely different meaning. For example, the term ‘species’ has a very clear meaning to most people, but in plasma physics it refers to a type of particle. This domain-specific language took some time getting used to, especially the abbreviations. Luckily, the project partners were extremely patient in explaining their domains and the problems they face. I really believe that our own vocabularies and set of expertise combined nicely to accelerate the rate of progress we made in the project. It has been a great experience.”&lt;/p&gt;
&lt;p&gt;Read more about &lt;a href=&quot;https://www.esciencecenter.nl/project/passing-xsams&quot;&gt;Passing XSAMS&lt;/a&gt;
Read more about &lt;a href=&quot;https://www.tue.nl/en/research/researchers/jan-van-dijk/&quot;&gt;Jan van Dijk&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/optimizing-plasma-sources-through-numeri-67412b5b.ClMGPqeB.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>eScience trends from ADASS 2019</title><link>https://blog2.esciencecenter.nl/posts/2019-10-21---escience-trends-from-adass-2019</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-10-21---escience-trends-from-adass-2019</guid><description>&lt;p&gt;The 2019 Conference on Astronomical Data Analysis and Software Systems (ADASS, 353 participants) took place in Groningen between 6 and 10 October, 2019. The aim of this annual conference is to bring together scientists and programmers to discuss the trends, developments and challenges in the processing and dissemination of astronomical data. For me, as an eScience Research Engineer at the Netherlands eScience Center, it was particularly interesting because these trends may apply to all domains of science, not only astronomy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_W1CJSpubMdkogPvP6K5f2g-906ce1f5.Bg_wm_KK_Z6dfMO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Increasingly sensitive new telescopes are not enough for astronomical breakthroughs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I attended inspiring talks about data management &lt;a href=&quot;https://www.lsst.org/&quot;&gt;for the Large Synoptic Survey Telescope (LSST&lt;/a&gt;), the &lt;a href=&quot;https://www.euclid-ec.org/&quot;&gt;EUCLID&lt;/a&gt; mission and the &lt;a href=&quot;https://www.cta-observatory.org/&quot;&gt;Cherenkov Telescope Array&lt;/a&gt; (CTA). All of these projects face major challenges beyond their deployment: the collected data have to be stored and processed into science-ready data products; “science-ready data products” became a buzz phrase across the conference. It means that building an even more sensitive telescope will not result in high scientific output if the observations are stored as raw, uncalibrated data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Throwback time, what my Ph.D. research was actually about…..&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1169&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_q7DY353RmUprEG8VdE0znQ-85995019.DZX-_gHy_5BkT2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from André Offringa’s presentation: “Designing radio-astronomical software for delivering science-ready products”&lt;/p&gt;
&lt;p&gt;The discussion about science-ready data products reminded me of what I spent most of my time on during my Ph.D. research: not astronomical interpretation of an observation, but data reduction. So I actually don’t have a Ph.D. in astronomy, but in data reduction! While I spent about five months processing an uncalibrated data set into a well calibrated sky map, only a total of six months were scheduled for actually publishing that observation. This meant that two weeks were left for astronomical analysis and two weeks for writing a paper. That’s insane! This was over ten years ago, but little has changed since then. Imagine how scientific output would increase if astronomers could actually spend their time on astronomy. And likewise for other scientific domains.&lt;/p&gt;
&lt;p&gt;Now, in getting to deliver those science-ready data products, e.g., well calibrated sky maps, we need compute and data transfer infrastructure, data reduction pipelines and support scientists to build, run and maintain those pipelines. Let’s look at the compute and data transfer problem first.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bring the compute to the data or the data to the compute?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1169&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9Y12e1V5GDc07WbZ78shfQ-3a8dcfad.AEYv0_1L_6Yjrh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from presentation by R. Chary (Caltech/IPAC) for the Joint Survey Processing Working Group. The red line indicates the increase of data rates from future telescopes.&lt;/p&gt;
&lt;p&gt;This slide from the presentation of Ranga-Ram Chary (invited speaker) clearly depicts our problem as well as the possible solution. Moore’s law — about the doubling of the number of transistors we can print on integrated circuits every two years-cannot keep up with the increasing data rates from new telescopes: its slope is too shallow. Moreover, Moore’s law &lt;a href=&quot;https://medium.com/@sgblank/the-end-of-more-the-death-of-moores-law-5ddcfd8439dd&quot;&gt;ended&lt;/a&gt; (H.S.). This means that worldwide compute power does not keep pace with the data rates from future telescopes. The slide also shows the solution: bandwidths across the world will increase faster than these data rates and we will be able to process observations by distributing them over many compute clusters across the globe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data reduction pipelines&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1169&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-0P5c8YNlTytlT_YLBtQ1w-3b37f090.CNwRLmWm_VBjO7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from presentation by Christine Banek: Why is the LSST Science Platform Built on Kubernetes?&lt;/p&gt;
&lt;p&gt;Another big trend and irreversible: the use of containers like Docker and Singularity containers. They are lightweight, i.e. their use will have a negligible effect on performance and they help to reproduce scientific results. Kubernetes and Helm are tools that help to manage all these containers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And finally, the people.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Long gone are the days when the most significant progress came from one or a few geniuses working alone or in small isolated teams. Over the last few centuries, all the low hanging fruit has been picked. What remains is much harder to investigate and likely requires hundreds of people. A large fraction of those will be the builders, testers and maintainers of data reduction pipelines, more generally referred to as support scientists. For these people there will be plenty of work in the coming decades. Moreover, in designing any new telescope or spacecraft mission for astronomy, one will have to think beyond data collection; the delivery of science-ready data products will be added to the responsibilities of the observatories conducting these projects.&lt;/p&gt;</description><pubDate>Mon, 21 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The 2019 Conference on Astronomical Data Analysis and Software Systems (ADASS, 353 participants) took place in Groningen between 6 and 10 October, 2019. The aim of this annual conference is to bring together scientists and programmers to discuss the trends, developments and challenges in the processing and dissemination of astronomical data. For me, as an eScience Research Engineer at the Netherlands eScience Center, it was particularly interesting because these trends may apply to all domains of science, not only astronomy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_W1CJSpubMdkogPvP6K5f2g-906ce1f5.Bg_wm_KK_Z6dfMO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Increasingly sensitive new telescopes are not enough for astronomical breakthroughs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I attended inspiring talks about data management &lt;a href=&quot;https://www.lsst.org/&quot;&gt;for the Large Synoptic Survey Telescope (LSST&lt;/a&gt;), the &lt;a href=&quot;https://www.euclid-ec.org/&quot;&gt;EUCLID&lt;/a&gt; mission and the &lt;a href=&quot;https://www.cta-observatory.org/&quot;&gt;Cherenkov Telescope Array&lt;/a&gt; (CTA). All of these projects face major challenges beyond their deployment: the collected data have to be stored and processed into science-ready data products; “science-ready data products” became a buzz phrase across the conference. It means that building an even more sensitive telescope will not result in high scientific output if the observations are stored as raw, uncalibrated data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Throwback time, what my Ph.D. research was actually about…..&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1169&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_q7DY353RmUprEG8VdE0znQ-85995019.DZX-_gHy_5BkT2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from André Offringa’s presentation: “Designing radio-astronomical software for delivering science-ready products”&lt;/p&gt;
&lt;p&gt;The discussion about science-ready data products reminded me of what I spent most of my time on during my Ph.D. research: not astronomical interpretation of an observation, but data reduction. So I actually don’t have a Ph.D. in astronomy, but in data reduction! While I spent about five months processing an uncalibrated data set into a well calibrated sky map, only a total of six months were scheduled for actually publishing that observation. This meant that two weeks were left for astronomical analysis and two weeks for writing a paper. That’s insane! This was over ten years ago, but little has changed since then. Imagine how scientific output would increase if astronomers could actually spend their time on astronomy. And likewise for other scientific domains.&lt;/p&gt;
&lt;p&gt;Now, in getting to deliver those science-ready data products, e.g., well calibrated sky maps, we need compute and data transfer infrastructure, data reduction pipelines and support scientists to build, run and maintain those pipelines. Let’s look at the compute and data transfer problem first.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bring the compute to the data or the data to the compute?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1169&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9Y12e1V5GDc07WbZ78shfQ-3a8dcfad.AEYv0_1L_6Yjrh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from presentation by R. Chary (Caltech/IPAC) for the Joint Survey Processing Working Group. The red line indicates the increase of data rates from future telescopes.&lt;/p&gt;
&lt;p&gt;This slide from the presentation of Ranga-Ram Chary (invited speaker) clearly depicts our problem as well as the possible solution. Moore’s law — about the doubling of the number of transistors we can print on integrated circuits every two years-cannot keep up with the increasing data rates from new telescopes: its slope is too shallow. Moreover, Moore’s law &lt;a href=&quot;https://medium.com/@sgblank/the-end-of-more-the-death-of-moores-law-5ddcfd8439dd&quot;&gt;ended&lt;/a&gt; (H.S.). This means that worldwide compute power does not keep pace with the data rates from future telescopes. The slide also shows the solution: bandwidths across the world will increase faster than these data rates and we will be able to process observations by distributing them over many compute clusters across the globe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Data reduction pipelines&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1169&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-0P5c8YNlTytlT_YLBtQ1w-3b37f090.CNwRLmWm_VBjO7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from presentation by Christine Banek: Why is the LSST Science Platform Built on Kubernetes?&lt;/p&gt;
&lt;p&gt;Another big trend and irreversible: the use of containers like Docker and Singularity containers. They are lightweight, i.e. their use will have a negligible effect on performance and they help to reproduce scientific results. Kubernetes and Helm are tools that help to manage all these containers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And finally, the people.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Long gone are the days when the most significant progress came from one or a few geniuses working alone or in small isolated teams. Over the last few centuries, all the low hanging fruit has been picked. What remains is much harder to investigate and likely requires hundreds of people. A large fraction of those will be the builders, testers and maintainers of data reduction pipelines, more generally referred to as support scientists. For these people there will be plenty of work in the coming decades. Moreover, in designing any new telescope or spacecraft mission for astronomy, one will have to think beyond data collection; the delivery of science-ready data products will be added to the responsibilities of the observatories conducting these projects.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_W1CJSpubMdkogPvP6K5f2g-906ce1f5.Bg_wm_KK.jpeg" medium="image"/><author>Hanno Spreeuw</author></item><item><title>RSEConUK 2019</title><link>https://blog2.esciencecenter.nl/posts/2019-10-18---rseconuk-2019</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-10-18---rseconuk-2019</guid><description>&lt;p&gt;&lt;em&gt;written by&lt;/em&gt; &lt;a href=&quot;https://medium.com/@n.drost&quot;&gt;&lt;em&gt;Niels Drost&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://medium.com/@mkuzak&quot;&gt;&lt;em&gt;Mateusz Kuzak&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://medium.com/@c.martinez&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;451&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Fyw8my4A4JX7tTCDtDoofw-fd1828dd.C0D2Clyy_ZkHbWW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;UK-RSE conference took place from the 17th to 19th of September 2019. This was my second RSE conference of the year, (the &lt;a href=&quot;https://blog.esciencecenter.nl/derse-2019-first-conference-for-research-software-engineers-in-germany-fa568e62ad00&quot;&gt;first one being de-RSE&lt;/a&gt; ) and &lt;a href=&quot;https://nl-rse.org/events/NL-RSE19.html&quot;&gt;nl-rse&lt;/a&gt; is coming up in November. The eScience Center was well represented, with Niels, Mateusz and me. With so many conferences and unavoidable travel in the times of #climateemergency we have decided to travel by train whenever possible #flyless.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;360&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_U0c7WnQvZx6ok6ovaqI2Fg-abd6c953.Py-041qm_okaXs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Niels participated in the &lt;a href=&quot;https://rseconuk2019.sched.com/event/QP6S/rse-worldwide-sharing-across-borders&quot;&gt;RSE worldwide: sharing across the borders session&lt;/a&gt; alongside &lt;a href=&quot;https://twitter.com/neocarlitos/status/1173995445980467202&quot;&gt;RSE representatives from around the globe&lt;/a&gt;. He described the Dutch RSE landscape and important things happening such as our recently published &lt;a href=&quot;https://nl-rse.org/2019/09/17/RaisingResearchSoftware.html&quot;&gt;position paper&lt;/a&gt; and the upcoming nl-rse conference. There was a very good response to this, with a number of people expressing interest in attending our conference.&lt;/p&gt;
&lt;p&gt;Mateusz joined Toni Collis (Chair of Women in High Performance Computing (WHPC)), Catherina Jones and Aiman Shaikh from Science and Technology Facilities Council and James Hetherington (Turing Institute) on the panel &lt;a href=&quot;https://rseconuk2019.sched.com/event/OdJE/1c2-mentoring-and-inclusivity-rse-mentoring-scheme-a-discussion&quot;&gt;Mentoring and Inclusivity — RSE mentoring scheme: a discussion&lt;/a&gt;. The group discussed different mentoring models and how to set up an RSE mentoring scheme.&lt;/p&gt;
&lt;p&gt;One other panel discussion was around the topic very close to our hearts at the eScience Center: &lt;a href=&quot;https://rseconuk2019.sched.com/event/QKqo/2c1-policy-and-culture-software-development-best-practices-why-arent-we-implementing-them&quot;&gt;Policy and Culture — Software development best practices — Why aren’t we implementing them?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From the discussion it was clear that limited amount of time and lack of recognition for time spent on implementing test, good documentation etc. stand in the way. Panellists also agreed that a set of good, minimal practices are often better then overwhelming lists of best practices they are less intimidating and require less time. Best practices approach often leads to no practise at all.&lt;/p&gt;
&lt;p&gt;This also sparked an interesting exchange on Twitter with Ian Bethune commenting:&lt;/p&gt;
&lt;p&gt;What engineers often forget about is that docs, tests, review, etc. ==A== ctually speed up the development and pay off.&lt;/p&gt;
&lt;p&gt;The conference was really well organised, with a great keynote by &lt;a href=&quot;https://rseconuk2019.sched.com/speaker/andy_stanford_clark.1zns8cof&quot;&gt;Andy Stanford-Clark&lt;/a&gt;, a very entertaining one by &lt;a href=&quot;https://rseconuk2019.sched.com/speaker/invited_speaker.1zni68dt&quot;&gt;Ben Goldcare&lt;/a&gt; and a very inspirational post-dinner talk by &lt;a href=&quot;https://rseconuk2019.sched.com/speaker/dr_maggie_aderin_pocock.76qlrjy&quot;&gt;Dr Maggie Aderin-Pocock&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last day of the conference was filled with a variety of exciting hands-on workshops at all levels of expertise, for example: learning how to set-up your own BinderHub instance, using Kubernetes in Google Cloud, building a sustainable team culture or becoming and RSE Superhero with VS Code and Azure Pipelines.&lt;/p&gt;
&lt;p&gt;Here are some of the take-home messages which stuck in my mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One recurring topic was that of career paths for RSEs. This was mentioned several times during the &lt;a href=&quot;https://rseconuk2019.sched.com/event/QSSO/society-of-research-software-engineering-agm&quot;&gt;UK-RSE Trustee flash presentations&lt;/a&gt;, and it resonates with the same message being voiced during &lt;a href=&quot;https://blog.esciencecenter.nl/derse-2019-first-conference-for-research-software-engineers-in-germany-fa568e62ad00&quot;&gt;de-RSE&lt;/a&gt; and with similar discussions taking place in the Netherlands.&lt;/li&gt;
&lt;li&gt;It was mentioned several times that many people feel at home at this conference. It is very inspiring to see the strong feeling of community shared amongst participants.&lt;/li&gt;
&lt;li&gt;It was also mentioned that the &lt;a href=&quot;https://twitter.com/chryswoods/status/1174014379945267201&quot;&gt;RSE community was created as a community of giving&lt;/a&gt;, where participants come to share their knowledge. Again, very inspiring to see such an open culture where helping others is given so much importance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;825&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CyK-DlEHYFptLhZCYvc38w-e3dec488.DQ8U_P8D_Z1WTReH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;824&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_62Ift-P9L06Pupmcn-v-kA-d459cb28.C-zKxBy4_1OS8LN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;824&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Wr9lDE26Eky_I3BqruQVyw-9055e6d3.CRyqMaIl_Z1atLcQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1101&quot; height=&quot;825&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tp3k4enzW5LDqooywahHAA-7ef84d8d._6KMQCRd_Z2cX7Yi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;825&quot; height=&quot;1101&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sVu43I29-zU-In3jOVBHhw-bd74a2a2.BYaqeuTy_Z1bnBtQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</description><pubDate>Fri, 18 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;written by&lt;/em&gt; &lt;a href=&quot;https://medium.com/@n.drost&quot;&gt;&lt;em&gt;Niels Drost&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://medium.com/@mkuzak&quot;&gt;&lt;em&gt;Mateusz Kuzak&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://medium.com/@c.martinez&quot;&gt;&lt;em&gt;Carlos Martinez-Ortiz&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;602&quot; height=&quot;451&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Fyw8my4A4JX7tTCDtDoofw-fd1828dd.C0D2Clyy_ZkHbWW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;UK-RSE conference took place from the 17th to 19th of September 2019. This was my second RSE conference of the year, (the &lt;a href=&quot;https://blog.esciencecenter.nl/derse-2019-first-conference-for-research-software-engineers-in-germany-fa568e62ad00&quot;&gt;first one being de-RSE&lt;/a&gt; ) and &lt;a href=&quot;https://nl-rse.org/events/NL-RSE19.html&quot;&gt;nl-rse&lt;/a&gt; is coming up in November. The eScience Center was well represented, with Niels, Mateusz and me. With so many conferences and unavoidable travel in the times of #climateemergency we have decided to travel by train whenever possible #flyless.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;360&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_U0c7WnQvZx6ok6ovaqI2Fg-abd6c953.Py-041qm_okaXs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Niels participated in the &lt;a href=&quot;https://rseconuk2019.sched.com/event/QP6S/rse-worldwide-sharing-across-borders&quot;&gt;RSE worldwide: sharing across the borders session&lt;/a&gt; alongside &lt;a href=&quot;https://twitter.com/neocarlitos/status/1173995445980467202&quot;&gt;RSE representatives from around the globe&lt;/a&gt;. He described the Dutch RSE landscape and important things happening such as our recently published &lt;a href=&quot;https://nl-rse.org/2019/09/17/RaisingResearchSoftware.html&quot;&gt;position paper&lt;/a&gt; and the upcoming nl-rse conference. There was a very good response to this, with a number of people expressing interest in attending our conference.&lt;/p&gt;
&lt;p&gt;Mateusz joined Toni Collis (Chair of Women in High Performance Computing (WHPC)), Catherina Jones and Aiman Shaikh from Science and Technology Facilities Council and James Hetherington (Turing Institute) on the panel &lt;a href=&quot;https://rseconuk2019.sched.com/event/OdJE/1c2-mentoring-and-inclusivity-rse-mentoring-scheme-a-discussion&quot;&gt;Mentoring and Inclusivity — RSE mentoring scheme: a discussion&lt;/a&gt;. The group discussed different mentoring models and how to set up an RSE mentoring scheme.&lt;/p&gt;
&lt;p&gt;One other panel discussion was around the topic very close to our hearts at the eScience Center: &lt;a href=&quot;https://rseconuk2019.sched.com/event/QKqo/2c1-policy-and-culture-software-development-best-practices-why-arent-we-implementing-them&quot;&gt;Policy and Culture — Software development best practices — Why aren’t we implementing them?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From the discussion it was clear that limited amount of time and lack of recognition for time spent on implementing test, good documentation etc. stand in the way. Panellists also agreed that a set of good, minimal practices are often better then overwhelming lists of best practices they are less intimidating and require less time. Best practices approach often leads to no practise at all.&lt;/p&gt;
&lt;p&gt;This also sparked an interesting exchange on Twitter with Ian Bethune commenting:&lt;/p&gt;
&lt;p&gt;What engineers often forget about is that docs, tests, review, etc. ==A== ctually speed up the development and pay off.&lt;/p&gt;
&lt;p&gt;The conference was really well organised, with a great keynote by &lt;a href=&quot;https://rseconuk2019.sched.com/speaker/andy_stanford_clark.1zns8cof&quot;&gt;Andy Stanford-Clark&lt;/a&gt;, a very entertaining one by &lt;a href=&quot;https://rseconuk2019.sched.com/speaker/invited_speaker.1zni68dt&quot;&gt;Ben Goldcare&lt;/a&gt; and a very inspirational post-dinner talk by &lt;a href=&quot;https://rseconuk2019.sched.com/speaker/dr_maggie_aderin_pocock.76qlrjy&quot;&gt;Dr Maggie Aderin-Pocock&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last day of the conference was filled with a variety of exciting hands-on workshops at all levels of expertise, for example: learning how to set-up your own BinderHub instance, using Kubernetes in Google Cloud, building a sustainable team culture or becoming and RSE Superhero with VS Code and Azure Pipelines.&lt;/p&gt;
&lt;p&gt;Here are some of the take-home messages which stuck in my mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One recurring topic was that of career paths for RSEs. This was mentioned several times during the &lt;a href=&quot;https://rseconuk2019.sched.com/event/QSSO/society-of-research-software-engineering-agm&quot;&gt;UK-RSE Trustee flash presentations&lt;/a&gt;, and it resonates with the same message being voiced during &lt;a href=&quot;https://blog.esciencecenter.nl/derse-2019-first-conference-for-research-software-engineers-in-germany-fa568e62ad00&quot;&gt;de-RSE&lt;/a&gt; and with similar discussions taking place in the Netherlands.&lt;/li&gt;
&lt;li&gt;It was mentioned several times that many people feel at home at this conference. It is very inspiring to see the strong feeling of community shared amongst participants.&lt;/li&gt;
&lt;li&gt;It was also mentioned that the &lt;a href=&quot;https://twitter.com/chryswoods/status/1174014379945267201&quot;&gt;RSE community was created as a community of giving&lt;/a&gt;, where participants come to share their knowledge. Again, very inspiring to see such an open culture where helping others is given so much importance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;825&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CyK-DlEHYFptLhZCYvc38w-e3dec488.DQ8U_P8D_Z1WTReH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;824&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_62Ift-P9L06Pupmcn-v-kA-d459cb28.C-zKxBy4_1OS8LN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;824&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Wr9lDE26Eky_I3BqruQVyw-9055e6d3.CRyqMaIl_Z1atLcQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1101&quot; height=&quot;825&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tp3k4enzW5LDqooywahHAA-7ef84d8d._6KMQCRd_Z2cX7Yi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;825&quot; height=&quot;1101&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sVu43I29-zU-In3jOVBHhw-bd74a2a2.BYaqeuTy_Z1bnBtQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_U0c7WnQvZx6ok6ovaqI2Fg-abd6c953.Py-041qm.png" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>NARCIS connects to the Research Software Directory</title><link>https://blog2.esciencecenter.nl/posts/2019-10-03---narcis-connects-to-the-research-software-directory</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-10-03---narcis-connects-to-the-research-software-directory</guid><description>&lt;h2 id=&quot;software-now-officially-listed-as-a-research-output&quot;&gt;Software now officially listed as a research output&lt;/h2&gt;
&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;The “FAIR Software Route” website will be presented by DANS and eScience Center at the&lt;a href=&quot;https://www.esciencecenter.nl/news/6th-national-escience-symposium-2019-digital-challenges-in-open-science&quot;&gt; eScience Symposium&lt;/a&gt; this November.&lt;/p&gt;
&lt;p&gt;Watch our RSD promotional video!&lt;/p&gt;
&lt;h3 id=&quot;more-information&quot;&gt;More information&lt;/h3&gt;
&lt;p&gt;See also &lt;a href=&quot;https://dans.knaw.nl/en/current/news/new-in-narcis-scientific-software?set_language=en&quot;&gt;New in NARCIS: scientific software&lt;/a&gt;. For more information or questions about this joint project, please contact &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-jason-maassen&quot;&gt;Jason Maassen&lt;/a&gt; from the Netherlands eScience Center or &lt;a href=&quot;https://dans.knaw.nl/en/about/organisation-and-policy/staff/hof-ph-d?set_language=en&quot;&gt;Cees Hof&lt;/a&gt; from DANS.&lt;/p&gt;</description><pubDate>Thu, 03 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;software-now-officially-listed-as-a-research-output&quot;&gt;Software now officially listed as a research output&lt;/h2&gt;
&lt;p&gt;SubscribeRemember me for faster sign in&lt;/p&gt;
&lt;p&gt;The “FAIR Software Route” website will be presented by DANS and eScience Center at the&lt;a href=&quot;https://www.esciencecenter.nl/news/6th-national-escience-symposium-2019-digital-challenges-in-open-science&quot;&gt; eScience Symposium&lt;/a&gt; this November.&lt;/p&gt;
&lt;p&gt;Watch our RSD promotional video!&lt;/p&gt;
&lt;h3 id=&quot;more-information&quot;&gt;More information&lt;/h3&gt;
&lt;p&gt;See also &lt;a href=&quot;https://dans.knaw.nl/en/current/news/new-in-narcis-scientific-software?set_language=en&quot;&gt;New in NARCIS: scientific software&lt;/a&gt;. For more information or questions about this joint project, please contact &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-jason-maassen&quot;&gt;Jason Maassen&lt;/a&gt; from the Netherlands eScience Center or &lt;a href=&quot;https://dans.knaw.nl/en/about/organisation-and-policy/staff/hof-ph-d?set_language=en&quot;&gt;Cees Hof&lt;/a&gt; from DANS.&lt;/p&gt;</content:encoded><author>Carlos Martinez-Ortiz</author></item><item><title>Highlights from the European Conference on Machine Learning 2019</title><link>https://blog2.esciencecenter.nl/posts/2019-09-24---highlights-from-the-european-conference-on-machine-learning-</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-09-24---highlights-from-the-european-conference-on-machine-learning-</guid><description>&lt;h2 id=&quot;ml-highlights-and-trends-as-seen-at-ecml-pkdd-2019-1620-september-würzburg-germany&quot;&gt;ML highlights and trends as seen at ECML-PKDD 2019 (16–20 September, Würzburg, Germany)&lt;/h2&gt;
&lt;p&gt;The conference’s cryptic name is due to the fact that it is a merger of two conferences: the European Conference on Machine Learning (&lt;strong&gt;ECML&lt;/strong&gt;) and the European Conference on Principles and Practice of Knowledge Discovery in Databases (&lt;strong&gt;PKDD)&lt;/strong&gt;. I mostly attended for the machine-learning part, so I will focus in this blog post on the ML aspects of &lt;a href=&quot;https://ecmlpkdd2019.org/&quot;&gt;this one-week conference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s start with my personal highlights…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1119&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7HGhLaTTZyvTt9OsKb4FUQ-f2fd70ee.CQ-qyFVt_ZpL52p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;ECML-PKDD 2019 was in Würzburg, Germany. Pretty city, pretty weather. Perfect to spend a week indoors to do some machine-learning.&lt;/p&gt;
&lt;h2 id=&quot;highlights-my-subjective-choice-obviously&quot;&gt;Highlights (my subjective choice, obviously)&lt;/h2&gt;
&lt;p&gt;Having more than 170 contributed papers is still not a guarantee for finding outstanding advances of the field. Luckily, I came across quite a few very promising contributions at ECMLPKDD 2019. Besides some really interesting real-life use-cases (some mentioned further below), here my personal highlights that really felt like considerable steps forward.&lt;/p&gt;
&lt;p&gt;1 &lt;strong&gt;Deep network training using random learning rates!&lt;/strong&gt;&lt;br&gt;
This is really cool! The authors found a way to largely avoid learning rate optimization altogether. On a wide range of test cases their algorithm (&lt;strong&gt;Alrao&lt;/strong&gt;) performed as good as stochastic gradient descent with optimally tuned learning rate.&lt;br&gt;
Paper: &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/805.pdf&quot;&gt;https://ecmlpkdd2019.org/downloads/paper/805.pdf&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;http://github.com/leonardblier/alrao&quot;&gt;http://github.com/leonardblier/alrao&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;760&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ie45hxTGfxLezlF9utKu6A-4688de77.CXieRFdl_1UwI7K.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fully connected classifier (left) versus Alrao version of the same neural network (right). Neurons in the network are assigned different learning rates and the final classification layer is replaced by a series of classifier units, each using the network output for one specific learning rate. Figure taken from Blier et al. (2019).&lt;/p&gt;
&lt;p&gt;2 &lt;strong&gt;Novel faster and more accurate time series classification methods!&lt;/strong&gt;&lt;br&gt;
In his keynote lecture, &lt;a href=&quot;https://twitter.com/LeDataMiner&quot;&gt;François Petitjean&lt;/a&gt; presented two novel tools. The first is a more classical tree-based approach called &lt;strong&gt;TS-CHIEF,&lt;/strong&gt; which on more than fifty test datasets on average performed as well as the current state-of-the-art method (HIVE-COTE) while training and scaling vastly faster.&lt;br&gt;
Paper: &lt;a href=&quot;https://arxiv.org/abs/1906.10329&quot;&gt;https://arxiv.org/abs/1906.10329&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/dotnet54/TS-CHIEF&quot;&gt;https://github.com/dotnet54/TS-CHIEF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1207&quot; height=&quot;479&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mr22lqNFVDyGemsmrzNf4g-968c4aa6.CfHH5fvz_Z1AAfkW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Inception module for time series classification as proposed by Fawaz et al. (2019). Image taken from their manuscript.&lt;/p&gt;
&lt;p&gt;Then, together with &lt;a href=&quot;https://twitter.com/hassanfawaz93&quot;&gt;Hassan Ismail Fawaz&lt;/a&gt; and others they just published a deep learning approach for time series classification on arXiv. Their network architecture is largely inspired by Inception CNNs known from computer vision. No surprise they termed it &lt;strong&gt;InceptionTime&lt;/strong&gt;. Roughly performs as well as the aforementioned method but both approaches seem to outperform each other on different datasets. Which is cool because that means that they focus on different aspects of the time series. I wonder what happens if you ensemble both, TS-CHIEF and InceptionTime…&lt;br&gt;
Paper: &lt;a href=&quot;https://arxiv.org/pdf/1909.04939.pdf&quot;&gt;https://arxiv.org/pdf/1909.04939.pdf&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/hfawaz/InceptionTime&quot;&gt;https://github.com/hfawaz/InceptionTime&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Related to this, the authors also recently published a very thorough &lt;a href=&quot;https://arxiv.org/abs/1809.04356&quot;&gt;review article on deep learning for time series classificatio&lt;/a&gt; n.&lt;/p&gt;
&lt;p&gt;3 &lt;strong&gt;Faster, tunable t-SNE!&lt;/strong&gt;&lt;br&gt;
I guess few tools are more common to data scientists than t-SNE. It’s used to break down abstract feature vectors (or latent representations) into low dimensional plots (LINK).&lt;br&gt;
Here, the authors not only found a way to get a much faster (python usable) implementation, they also discovered that varying one specific factor in the t-SNE algorithm (that so far was fixed to 1) can be used to fine tune the clustering strength.&lt;br&gt;
Faster t-sne implementation: originally here: &lt;a href=&quot;https://github.com/KlugerLab/pyFIt-SNE&quot;&gt;https://github.com/KlugerLab/pyFIt-SNE&lt;/a&gt;&lt;br&gt;
Alternative version is opentsne: &lt;a href=&quot;https://github.com/pavlin-policar/openTSNE/&quot;&gt;https://github.com/pavlin-policar/openTSNE/&lt;/a&gt;&lt;br&gt;
Paper: &lt;a href=&quot;https://arxiv.org/abs/1902.05804&quot;&gt;https://arxiv.org/abs/1902.05804&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/dkobak/finer-tsne&quot;&gt;https://github.com/dkobak/finer-tsne&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;450&quot; height=&quot;450&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5skE8wLr4MwCcEiLzYDpLQ-960e503d.YWQoN3cN_ZPBGy5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Animation of t-sne of mnist dataset using different tuning parameter alpha. Made by Dimitry Kobak, can be found with adjacent code on: &lt;a href=&quot;https://github.com/dkobak/finer-tsne&quot;&gt;https://github.com/dkobak/finer-tsne&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4 &lt;strong&gt;Novel reinforcement-learning algorithm based on an actor and several (off-policy) critics&lt;/strong&gt;.&lt;br&gt;
They call it BDPI (Bootstrapped Dual Policy Iteration) and it seems that their approach it unusually stable as well as robust to hyperparameter variations, both being huge obstacles in many RL use-cases.&lt;br&gt;
Paper: &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/48.pdf&quot;&gt;https://ecmlpkdd2019.org/downloads/paper/48.pdf&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/vub-ai-lab/bdpi&quot;&gt;https://github.com/vub-ai-lab/bdpi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;5 &lt;strong&gt;Autoencoder with agnostic feature selection&lt;/strong&gt;&lt;br&gt;
Guillaume Doquet and Michèle Sebag presented an &lt;a href=&quot;https://twitter.com/hashtag/autoencoder?src=hashtag_click&quot;&gt;autoencoder&lt;/a&gt; combined with structural regularization for better feature selection (or agnostic feature selection, hence the name &lt;strong&gt;AGNOS&lt;/strong&gt;). It indeed performs pretty well (unfortunately computational cost increase quite a bit).&lt;br&gt;
Paper: &lt;a href=&quot;https://www.ecmlpkdd2019.org/downloads/paper/744.pdf&quot;&gt;https://www.ecmlpkdd2019.org/downloads/paper/744.pdf&lt;/a&gt;&lt;br&gt;
Code not available yet.&lt;/p&gt;
&lt;h2 id=&quot;other-trends-and-common-themes&quot;&gt;Other trends and common themes&lt;/h2&gt;
&lt;h3 id=&quot;probabilistic-models&quot;&gt;Probabilistic models&lt;/h3&gt;
&lt;p&gt;What people in machine-learning mean by probabilistic models is usually models that not only output a single prediction, but also give a distribution or other measure for how certain the model is about its prediction.&lt;/p&gt;
&lt;p&gt;Back in the older times of ML (which in ML means a few years back), most ML practitioners would be happy enough to have a model that performs decently with respect to its output accuracy. To estimate the certainty of those models, it was often common practice (which means it in many cases still is!) to simply look at the model predictions one layer before the final argmax and treat those values as probabilities. But although a softmax layer will indeed give probability-like looking values (they are properly normalized to a sum of 1), they are usually not very reliable uncertainty estimates.&lt;/p&gt;
&lt;p&gt;ECML-PKDD2019 hosted two entire sessions on probabilistic models with a very strong focus on Gaussian processes. There was, for instance, an interesting implementation by &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/116.pdf&quot;&gt;Wistuba and Rawat&lt;/a&gt; using a “Large Margin Gaussian Process” that can be added to the end of a conventional CNN. Or a promising looking deep constitutional Gaussian process method by &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/645.pdf&quot;&gt;Blomqvist et al.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;algorithm-benchmarking-vs-real-world-usability&quot;&gt;Algorithm benchmarking vs. real-world usability&lt;/h3&gt;
&lt;p&gt;This is not exactly a new trend. But you could say it’s a remaining theme. The ML field is no different than most scientific domains in that it is highly driven by the “publish or perish” paradigm. You want to stay in academia? Better publish as much as you can!&lt;/p&gt;
&lt;p&gt;So no surprise that at ECML-PKDD2019 I saw what also can be seen elsewhere: &lt;strong&gt;Most papers coming out in ML represent — at best — incremental improvements over previous work!&lt;/strong&gt; Often that means a slightly better benchmark here, a little faster computation there. That’s fine of course. Only that for people like me that are mostly interested in applying ML tools for a wide range of real world problems, those incremental changes rarely justify going through the hassle. The projects I work on are scientific research projects. For those, I would nearly always favor a more-established, better documented method that gives me a decent accuracy over a newly developed one that might give me slightly better results, but is either more cumbersome to implement, or that requires more expertise to properly tune and understand.&lt;/p&gt;
&lt;h3 id=&quot;resource-efficient-deep-learning-and-ml&quot;&gt;Resource-efficient deep learning (and ML)&lt;/h3&gt;
&lt;p&gt;Often motivated by limited computational resources of devices (IoT, smartphones etc.), sometimes also motivated by energy efficiency/sustainability aspects, efficient machine learning algorithms have gained quite some traction.&lt;/p&gt;
&lt;p&gt;Typical tricks include network pruning (creating sparser models), or lower precision values (e.g. gradients), for instance by going from floats to bitsets.&lt;br&gt;
Another approach is cleverly designed network architectures that allow to drastically cut down training cost for large ensembles of networks. The well-known Inception architecture for CNNs could be seen as such a case. Dimitrios Stamoulis (Carnegie Mellon, USA), for instance presented a &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/880.pdf&quot;&gt;new efficient method for neural architecture search&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Closely related, there was also an entire &lt;a href=&quot;https://greendatamining.github.io/&quot;&gt;workshop on green data mining&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;explainability-interpretability&quot;&gt;Explainability, Interpretability&lt;/h3&gt;
&lt;p&gt;Not unexpectedly, explainable AI or model interpretation came up at many points during the conference. The keynote by Tinne Tuytelaar (KU Leuven, Belgium) on computer vision discussed this to quite some extent. And on the last day there was an entire tutorial/workshop session on the topic → see &lt;a href=&quot;https://kdd.isti.cnr.it/xkdd2019/&quot;&gt;AIMLAI-XKDD website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The slides of the XKDD tutorial part are also all available online: &lt;a href=&quot;https://kdd.isti.cnr.it/xkdd2019/pkdd2019xkdd_tutorial_last.pdf&quot;&gt;https://kdd.isti.cnr.it/xkdd2019/pkdd2019xkdd_tutorial_last.pdf&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-of-ml-all-over-the-place&quot;&gt;Use of ML all over the place&lt;/h3&gt;
&lt;p&gt;Again, no new trend. But it remains great to see, because in the end this is what all of this is about (for me at least). And that’s the use of ML techniques over a wide range of fields and topics.&lt;/p&gt;
&lt;p&gt;Obviously there were many of the usual suspects: analysis or prediction making in finance, e-commerce, power consumption, public transport usage, etc. Closer to my heart though, were the many nice examples of different scientific disciplines using ML to help analyze and interpret their data. I attended a cool &lt;a href=&quot;https://musml2019.weebly.com/&quot;&gt;workshop on machine-learning and music&lt;/a&gt;, looking at neural networks generating human-resembling sheet music or reading ancient hand-written sheets.&lt;br&gt;
I also greatly enjoyed the keynote on “palaeontology as a computational science” by &lt;a href=&quot;https://twitter.com/inzl&quot;&gt;Indrė Žliobaitė,&lt;/a&gt; and saw plenty of interesting cases from life sciences and social sciences.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;931&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_cMmLhzd7StoUuuJDEcIN0A-53e8e21c.8vUYUGYx_ffgzN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;ECML PKDD 2019 group picture supporting Fridays for Future.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;804&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2DCKc1_bq3nR00HrqzAZCw-aaebb568.DGPCq1TG_1opbzE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lively discussions of current techniques in 900 year old wine cellar…&lt;/p&gt;</description><pubDate>Tue, 24 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;ml-highlights-and-trends-as-seen-at-ecml-pkdd-2019-1620-september-würzburg-germany&quot;&gt;ML highlights and trends as seen at ECML-PKDD 2019 (16–20 September, Würzburg, Germany)&lt;/h2&gt;
&lt;p&gt;The conference’s cryptic name is due to the fact that it is a merger of two conferences: the European Conference on Machine Learning (&lt;strong&gt;ECML&lt;/strong&gt;) and the European Conference on Principles and Practice of Knowledge Discovery in Databases (&lt;strong&gt;PKDD)&lt;/strong&gt;. I mostly attended for the machine-learning part, so I will focus in this blog post on the ML aspects of &lt;a href=&quot;https://ecmlpkdd2019.org/&quot;&gt;this one-week conference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let’s start with my personal highlights…&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1119&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7HGhLaTTZyvTt9OsKb4FUQ-f2fd70ee.CQ-qyFVt_ZpL52p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;ECML-PKDD 2019 was in Würzburg, Germany. Pretty city, pretty weather. Perfect to spend a week indoors to do some machine-learning.&lt;/p&gt;
&lt;h2 id=&quot;highlights-my-subjective-choice-obviously&quot;&gt;Highlights (my subjective choice, obviously)&lt;/h2&gt;
&lt;p&gt;Having more than 170 contributed papers is still not a guarantee for finding outstanding advances of the field. Luckily, I came across quite a few very promising contributions at ECMLPKDD 2019. Besides some really interesting real-life use-cases (some mentioned further below), here my personal highlights that really felt like considerable steps forward.&lt;/p&gt;
&lt;p&gt;1 &lt;strong&gt;Deep network training using random learning rates!&lt;/strong&gt;&lt;br&gt;
This is really cool! The authors found a way to largely avoid learning rate optimization altogether. On a wide range of test cases their algorithm (&lt;strong&gt;Alrao&lt;/strong&gt;) performed as good as stochastic gradient descent with optimally tuned learning rate.&lt;br&gt;
Paper: &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/805.pdf&quot;&gt;https://ecmlpkdd2019.org/downloads/paper/805.pdf&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;http://github.com/leonardblier/alrao&quot;&gt;http://github.com/leonardblier/alrao&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;760&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ie45hxTGfxLezlF9utKu6A-4688de77.CXieRFdl_1UwI7K.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Fully connected classifier (left) versus Alrao version of the same neural network (right). Neurons in the network are assigned different learning rates and the final classification layer is replaced by a series of classifier units, each using the network output for one specific learning rate. Figure taken from Blier et al. (2019).&lt;/p&gt;
&lt;p&gt;2 &lt;strong&gt;Novel faster and more accurate time series classification methods!&lt;/strong&gt;&lt;br&gt;
In his keynote lecture, &lt;a href=&quot;https://twitter.com/LeDataMiner&quot;&gt;François Petitjean&lt;/a&gt; presented two novel tools. The first is a more classical tree-based approach called &lt;strong&gt;TS-CHIEF,&lt;/strong&gt; which on more than fifty test datasets on average performed as well as the current state-of-the-art method (HIVE-COTE) while training and scaling vastly faster.&lt;br&gt;
Paper: &lt;a href=&quot;https://arxiv.org/abs/1906.10329&quot;&gt;https://arxiv.org/abs/1906.10329&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/dotnet54/TS-CHIEF&quot;&gt;https://github.com/dotnet54/TS-CHIEF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1207&quot; height=&quot;479&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mr22lqNFVDyGemsmrzNf4g-968c4aa6.CfHH5fvz_Z1AAfkW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Inception module for time series classification as proposed by Fawaz et al. (2019). Image taken from their manuscript.&lt;/p&gt;
&lt;p&gt;Then, together with &lt;a href=&quot;https://twitter.com/hassanfawaz93&quot;&gt;Hassan Ismail Fawaz&lt;/a&gt; and others they just published a deep learning approach for time series classification on arXiv. Their network architecture is largely inspired by Inception CNNs known from computer vision. No surprise they termed it &lt;strong&gt;InceptionTime&lt;/strong&gt;. Roughly performs as well as the aforementioned method but both approaches seem to outperform each other on different datasets. Which is cool because that means that they focus on different aspects of the time series. I wonder what happens if you ensemble both, TS-CHIEF and InceptionTime…&lt;br&gt;
Paper: &lt;a href=&quot;https://arxiv.org/pdf/1909.04939.pdf&quot;&gt;https://arxiv.org/pdf/1909.04939.pdf&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/hfawaz/InceptionTime&quot;&gt;https://github.com/hfawaz/InceptionTime&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Related to this, the authors also recently published a very thorough &lt;a href=&quot;https://arxiv.org/abs/1809.04356&quot;&gt;review article on deep learning for time series classificatio&lt;/a&gt; n.&lt;/p&gt;
&lt;p&gt;3 &lt;strong&gt;Faster, tunable t-SNE!&lt;/strong&gt;&lt;br&gt;
I guess few tools are more common to data scientists than t-SNE. It’s used to break down abstract feature vectors (or latent representations) into low dimensional plots (LINK).&lt;br&gt;
Here, the authors not only found a way to get a much faster (python usable) implementation, they also discovered that varying one specific factor in the t-SNE algorithm (that so far was fixed to 1) can be used to fine tune the clustering strength.&lt;br&gt;
Faster t-sne implementation: originally here: &lt;a href=&quot;https://github.com/KlugerLab/pyFIt-SNE&quot;&gt;https://github.com/KlugerLab/pyFIt-SNE&lt;/a&gt;&lt;br&gt;
Alternative version is opentsne: &lt;a href=&quot;https://github.com/pavlin-policar/openTSNE/&quot;&gt;https://github.com/pavlin-policar/openTSNE/&lt;/a&gt;&lt;br&gt;
Paper: &lt;a href=&quot;https://arxiv.org/abs/1902.05804&quot;&gt;https://arxiv.org/abs/1902.05804&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/dkobak/finer-tsne&quot;&gt;https://github.com/dkobak/finer-tsne&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;450&quot; height=&quot;450&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5skE8wLr4MwCcEiLzYDpLQ-960e503d.YWQoN3cN_ZPBGy5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Animation of t-sne of mnist dataset using different tuning parameter alpha. Made by Dimitry Kobak, can be found with adjacent code on: &lt;a href=&quot;https://github.com/dkobak/finer-tsne&quot;&gt;https://github.com/dkobak/finer-tsne&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4 &lt;strong&gt;Novel reinforcement-learning algorithm based on an actor and several (off-policy) critics&lt;/strong&gt;.&lt;br&gt;
They call it BDPI (Bootstrapped Dual Policy Iteration) and it seems that their approach it unusually stable as well as robust to hyperparameter variations, both being huge obstacles in many RL use-cases.&lt;br&gt;
Paper: &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/48.pdf&quot;&gt;https://ecmlpkdd2019.org/downloads/paper/48.pdf&lt;/a&gt;&lt;br&gt;
Code: &lt;a href=&quot;https://github.com/vub-ai-lab/bdpi&quot;&gt;https://github.com/vub-ai-lab/bdpi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;5 &lt;strong&gt;Autoencoder with agnostic feature selection&lt;/strong&gt;&lt;br&gt;
Guillaume Doquet and Michèle Sebag presented an &lt;a href=&quot;https://twitter.com/hashtag/autoencoder?src=hashtag_click&quot;&gt;autoencoder&lt;/a&gt; combined with structural regularization for better feature selection (or agnostic feature selection, hence the name &lt;strong&gt;AGNOS&lt;/strong&gt;). It indeed performs pretty well (unfortunately computational cost increase quite a bit).&lt;br&gt;
Paper: &lt;a href=&quot;https://www.ecmlpkdd2019.org/downloads/paper/744.pdf&quot;&gt;https://www.ecmlpkdd2019.org/downloads/paper/744.pdf&lt;/a&gt;&lt;br&gt;
Code not available yet.&lt;/p&gt;
&lt;h2 id=&quot;other-trends-and-common-themes&quot;&gt;Other trends and common themes&lt;/h2&gt;
&lt;h3 id=&quot;probabilistic-models&quot;&gt;Probabilistic models&lt;/h3&gt;
&lt;p&gt;What people in machine-learning mean by probabilistic models is usually models that not only output a single prediction, but also give a distribution or other measure for how certain the model is about its prediction.&lt;/p&gt;
&lt;p&gt;Back in the older times of ML (which in ML means a few years back), most ML practitioners would be happy enough to have a model that performs decently with respect to its output accuracy. To estimate the certainty of those models, it was often common practice (which means it in many cases still is!) to simply look at the model predictions one layer before the final argmax and treat those values as probabilities. But although a softmax layer will indeed give probability-like looking values (they are properly normalized to a sum of 1), they are usually not very reliable uncertainty estimates.&lt;/p&gt;
&lt;p&gt;ECML-PKDD2019 hosted two entire sessions on probabilistic models with a very strong focus on Gaussian processes. There was, for instance, an interesting implementation by &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/116.pdf&quot;&gt;Wistuba and Rawat&lt;/a&gt; using a “Large Margin Gaussian Process” that can be added to the end of a conventional CNN. Or a promising looking deep constitutional Gaussian process method by &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/645.pdf&quot;&gt;Blomqvist et al.&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;algorithm-benchmarking-vs-real-world-usability&quot;&gt;Algorithm benchmarking vs. real-world usability&lt;/h3&gt;
&lt;p&gt;This is not exactly a new trend. But you could say it’s a remaining theme. The ML field is no different than most scientific domains in that it is highly driven by the “publish or perish” paradigm. You want to stay in academia? Better publish as much as you can!&lt;/p&gt;
&lt;p&gt;So no surprise that at ECML-PKDD2019 I saw what also can be seen elsewhere: &lt;strong&gt;Most papers coming out in ML represent — at best — incremental improvements over previous work!&lt;/strong&gt; Often that means a slightly better benchmark here, a little faster computation there. That’s fine of course. Only that for people like me that are mostly interested in applying ML tools for a wide range of real world problems, those incremental changes rarely justify going through the hassle. The projects I work on are scientific research projects. For those, I would nearly always favor a more-established, better documented method that gives me a decent accuracy over a newly developed one that might give me slightly better results, but is either more cumbersome to implement, or that requires more expertise to properly tune and understand.&lt;/p&gt;
&lt;h3 id=&quot;resource-efficient-deep-learning-and-ml&quot;&gt;Resource-efficient deep learning (and ML)&lt;/h3&gt;
&lt;p&gt;Often motivated by limited computational resources of devices (IoT, smartphones etc.), sometimes also motivated by energy efficiency/sustainability aspects, efficient machine learning algorithms have gained quite some traction.&lt;/p&gt;
&lt;p&gt;Typical tricks include network pruning (creating sparser models), or lower precision values (e.g. gradients), for instance by going from floats to bitsets.&lt;br&gt;
Another approach is cleverly designed network architectures that allow to drastically cut down training cost for large ensembles of networks. The well-known Inception architecture for CNNs could be seen as such a case. Dimitrios Stamoulis (Carnegie Mellon, USA), for instance presented a &lt;a href=&quot;https://ecmlpkdd2019.org/downloads/paper/880.pdf&quot;&gt;new efficient method for neural architecture search&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Closely related, there was also an entire &lt;a href=&quot;https://greendatamining.github.io/&quot;&gt;workshop on green data mining&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;explainability-interpretability&quot;&gt;Explainability, Interpretability&lt;/h3&gt;
&lt;p&gt;Not unexpectedly, explainable AI or model interpretation came up at many points during the conference. The keynote by Tinne Tuytelaar (KU Leuven, Belgium) on computer vision discussed this to quite some extent. And on the last day there was an entire tutorial/workshop session on the topic → see &lt;a href=&quot;https://kdd.isti.cnr.it/xkdd2019/&quot;&gt;AIMLAI-XKDD website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The slides of the XKDD tutorial part are also all available online: &lt;a href=&quot;https://kdd.isti.cnr.it/xkdd2019/pkdd2019xkdd_tutorial_last.pdf&quot;&gt;https://kdd.isti.cnr.it/xkdd2019/pkdd2019xkdd_tutorial_last.pdf&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;use-of-ml-all-over-the-place&quot;&gt;Use of ML all over the place&lt;/h3&gt;
&lt;p&gt;Again, no new trend. But it remains great to see, because in the end this is what all of this is about (for me at least). And that’s the use of ML techniques over a wide range of fields and topics.&lt;/p&gt;
&lt;p&gt;Obviously there were many of the usual suspects: analysis or prediction making in finance, e-commerce, power consumption, public transport usage, etc. Closer to my heart though, were the many nice examples of different scientific disciplines using ML to help analyze and interpret their data. I attended a cool &lt;a href=&quot;https://musml2019.weebly.com/&quot;&gt;workshop on machine-learning and music&lt;/a&gt;, looking at neural networks generating human-resembling sheet music or reading ancient hand-written sheets.&lt;br&gt;
I also greatly enjoyed the keynote on “palaeontology as a computational science” by &lt;a href=&quot;https://twitter.com/inzl&quot;&gt;Indrė Žliobaitė,&lt;/a&gt; and saw plenty of interesting cases from life sciences and social sciences.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;931&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_cMmLhzd7StoUuuJDEcIN0A-53e8e21c.8vUYUGYx_ffgzN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;ECML PKDD 2019 group picture supporting Fridays for Future.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;804&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2DCKc1_bq3nR00HrqzAZCw-aaebb568.DGPCq1TG_1opbzE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lively discussions of current techniques in 900 year old wine cellar…&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_7HGhLaTTZyvTt9OsKb4FUQ-f2fd70ee.CQ-qyFVt.jpeg" medium="image"/><author>Florian Huber</author></item><item><title>Using deep neural networks to understand molecular interactions</title><link>https://blog2.esciencecenter.nl/posts/2019-07-18---using-deep-neural-networks-to-understand-molecular-interacti</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-07-18---using-deep-neural-networks-to-understand-molecular-interacti</guid><description>&lt;p&gt;&lt;em&gt;Photography: Michiel Wijnbergh |&lt;/em&gt; &lt;a href=&quot;http://www.wijnbergh.nl/&quot;&gt;wijnbergh.nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XLgAxETTVqzLog2sEhsPkw-d061ce2a.Dewrqf0w_Z1Gyi7N.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Lars Ridder, Prof. Alexandre Bonvin, Dr. Nicolas Renaud, Dr. Li Xue, Dr. Sonja Georgievska&lt;/p&gt;
&lt;p&gt;The human body contains trillions of cells. These cells, while all specialised, work in harmony to carry out the basic functions necessary for humans to survive. Such cellular processes are in turn controlled by a huge number of interactions between molecules, many of which we still do not know about or fully understand. Gaining such insight could potentially open the door to the development of new and more effective drug therapies and treatments.&lt;/p&gt;
&lt;p&gt;In 2017 the project DeepRank was started, a collaboration between Alexandre Bonvin, professor of Computational Structural Biology at Utrecht University, his coworker Li Xue, and the Netherlands eScience Center. The aim of the project is to train deep neural networks (dNNs) to learn complex interaction patterns from the huge amount of experimental data in the Protein Data Bank, a valuable source of information not yet fully exploited.&lt;/p&gt;
&lt;h2 id=&quot;reliably-modeling-biomolecular-complexes&quot;&gt;Reliably modeling biomolecular complexes&lt;/h2&gt;
&lt;p&gt;‘Understanding molecular interactions requires studying them in three dimensions’, says Bonvin, whose research group focuses on the development of reliable bioinformatics and computational approaches to predict, model and dissect biomolecular interactions at atomic level. ‘To make this possible, experimental structural biology techniques need to be complemented with computational methods, such as docking, which allows one to model possible complexes of known biomolecular components.’ However, a major challenge in docking is scoring — the identification of correct (near-native) models from a large pool of docked models — due to the biophysical complexity of these interactions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1334&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ik99wSx3Cf5a2ORZRaPDjQ-73fdad02.CCGHXyqL_Z26xawS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OsKix3YA5jQX15FWeE-iGw-1f539080.a1AeQ8xR_Z7jklA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yOn8MNkOqroZo-15PvY1Jw-19e0d69a.BtD3vSZM_1JK3oX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;To overcome this challenge, Bonvin, with support from the eScience Center, uses an innovative strategy in which the problem is treated as a 3D image classification problem. The interfaces of docked models are represented as 3D images and dNNs are trained to classify whether they are near-native or not. It is hoped that the resulting scoring function, DeepRank, will markedly enhance current capabilities to reliably model biomolecular complexes and as a result assist the scientific community in gaining greater insights into macromolecular aspects of life. Bonvin will eventually also implement DeepRank in his HADDOCK modelling platform and freely distribute it through the GitHub and RSD repositories.&lt;/p&gt;
&lt;h2 id=&quot;critical-expertise-in-machine-and-deep-learning&quot;&gt;Critical expertise in machine and deep learning&lt;/h2&gt;
&lt;p&gt;Bonvin is extremely pleased with the intensive collaboration taking place with the eScience Center.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PTmhlhI7NoYVWEbkNonY6w-f948f125.sp5lr0-a_u9kjq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘The eScience research engineers have brought unique expertise in machine and deep learning, and in applying this to the complex models we deal with in this project, while we bring expertise in the research question and the biophysical factors that are important for reliably identifying correct from incorrect solutions. This mix of expertise has really driven new ways of thinking.’&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dFSzUn1eCx7K2zYyOjlrCQ-a235064a.Byh_A--Y_1xhBWw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZX56D4VaQhNQlH1CueZBmw-4875e9ce.33uUr9a6_Z1Vng4L.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Sonja Georgievska, Dr. Nicolas Renaud and Dr. Lars Ridder, the eScience Research Engineers involved in the project, agree.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘Prof. Bonvin and his team are among the top international experts in the field and hugely inspiring to work with. They bring unique expertise that we are trying to complement as best as we can. During the project we developed several tools to process the data, train modular neural networks and analyse the results. We also explored different machine learning methods — 3D CNN, Graph CNN and support vector machines — to classify and score predicted 3D structures of protein complexes. We are now using those tools on a large data set, which can be utilised to train neural networks.’&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KqDL7FBnEBxIO3cZhm46AA-bd44ddfa.B_hNDBxU_18roz3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Li Xue, co-principal investigator of the project and assistant professor at Utrecht University’s department of Chemistry, adds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘The collaboration with the eScience engineers has been very fruitful. All of us bring our own expertise to the table and, as a result, we learn a lot from each other. For example, Sonja Georgievska is an expert on deep learning, Nicolas Renaud has highly efficient programming skills and Lars Ridder is simply impressive for the way he coordinates and steers the team. All of this has really accelerated our level of progress.’&lt;/p&gt;
&lt;/blockquote&gt;</description><pubDate>Thu, 18 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Photography: Michiel Wijnbergh |&lt;/em&gt; &lt;a href=&quot;http://www.wijnbergh.nl/&quot;&gt;wijnbergh.nl&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XLgAxETTVqzLog2sEhsPkw-d061ce2a.Dewrqf0w_Z1Gyi7N.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Lars Ridder, Prof. Alexandre Bonvin, Dr. Nicolas Renaud, Dr. Li Xue, Dr. Sonja Georgievska&lt;/p&gt;
&lt;p&gt;The human body contains trillions of cells. These cells, while all specialised, work in harmony to carry out the basic functions necessary for humans to survive. Such cellular processes are in turn controlled by a huge number of interactions between molecules, many of which we still do not know about or fully understand. Gaining such insight could potentially open the door to the development of new and more effective drug therapies and treatments.&lt;/p&gt;
&lt;p&gt;In 2017 the project DeepRank was started, a collaboration between Alexandre Bonvin, professor of Computational Structural Biology at Utrecht University, his coworker Li Xue, and the Netherlands eScience Center. The aim of the project is to train deep neural networks (dNNs) to learn complex interaction patterns from the huge amount of experimental data in the Protein Data Bank, a valuable source of information not yet fully exploited.&lt;/p&gt;
&lt;h2 id=&quot;reliably-modeling-biomolecular-complexes&quot;&gt;Reliably modeling biomolecular complexes&lt;/h2&gt;
&lt;p&gt;‘Understanding molecular interactions requires studying them in three dimensions’, says Bonvin, whose research group focuses on the development of reliable bioinformatics and computational approaches to predict, model and dissect biomolecular interactions at atomic level. ‘To make this possible, experimental structural biology techniques need to be complemented with computational methods, such as docking, which allows one to model possible complexes of known biomolecular components.’ However, a major challenge in docking is scoring — the identification of correct (near-native) models from a large pool of docked models — due to the biophysical complexity of these interactions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1334&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ik99wSx3Cf5a2ORZRaPDjQ-73fdad02.CCGHXyqL_Z26xawS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OsKix3YA5jQX15FWeE-iGw-1f539080.a1AeQ8xR_Z7jklA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yOn8MNkOqroZo-15PvY1Jw-19e0d69a.BtD3vSZM_1JK3oX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;To overcome this challenge, Bonvin, with support from the eScience Center, uses an innovative strategy in which the problem is treated as a 3D image classification problem. The interfaces of docked models are represented as 3D images and dNNs are trained to classify whether they are near-native or not. It is hoped that the resulting scoring function, DeepRank, will markedly enhance current capabilities to reliably model biomolecular complexes and as a result assist the scientific community in gaining greater insights into macromolecular aspects of life. Bonvin will eventually also implement DeepRank in his HADDOCK modelling platform and freely distribute it through the GitHub and RSD repositories.&lt;/p&gt;
&lt;h2 id=&quot;critical-expertise-in-machine-and-deep-learning&quot;&gt;Critical expertise in machine and deep learning&lt;/h2&gt;
&lt;p&gt;Bonvin is extremely pleased with the intensive collaboration taking place with the eScience Center.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PTmhlhI7NoYVWEbkNonY6w-f948f125.sp5lr0-a_u9kjq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘The eScience research engineers have brought unique expertise in machine and deep learning, and in applying this to the complex models we deal with in this project, while we bring expertise in the research question and the biophysical factors that are important for reliably identifying correct from incorrect solutions. This mix of expertise has really driven new ways of thinking.’&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_dFSzUn1eCx7K2zYyOjlrCQ-a235064a.Byh_A--Y_1xhBWw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZX56D4VaQhNQlH1CueZBmw-4875e9ce.33uUr9a6_Z1Vng4L.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Sonja Georgievska, Dr. Nicolas Renaud and Dr. Lars Ridder, the eScience Research Engineers involved in the project, agree.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘Prof. Bonvin and his team are among the top international experts in the field and hugely inspiring to work with. They bring unique expertise that we are trying to complement as best as we can. During the project we developed several tools to process the data, train modular neural networks and analyse the results. We also explored different machine learning methods — 3D CNN, Graph CNN and support vector machines — to classify and score predicted 3D structures of protein complexes. We are now using those tools on a large data set, which can be utilised to train neural networks.’&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KqDL7FBnEBxIO3cZhm46AA-bd44ddfa.B_hNDBxU_18roz3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Li Xue, co-principal investigator of the project and assistant professor at Utrecht University’s department of Chemistry, adds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;‘The collaboration with the eScience engineers has been very fruitful. All of us bring our own expertise to the table and, as a result, we learn a lot from each other. For example, Sonja Georgievska is an expert on deep learning, Nicolas Renaud has highly efficient programming skills and Lars Ridder is simply impressive for the way he coordinates and steers the team. All of this has really accelerated our level of progress.’&lt;/p&gt;
&lt;/blockquote&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Ik99wSx3Cf5a2ORZRaPDjQ-73fdad02.CCGHXyqL.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>King - Man + Woman = King ?</title><link>https://blog2.esciencecenter.nl/posts/2019-07-15---king-man-woman-king</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-07-15---king-man-woman-king</guid><description>&lt;h2 id=&quot;some-of-the-best-known-examples-used-to-explain-the-power-of-prominent-natural-language-processing-tools-like-word2vec-only-seem-to-work-with-some-cheating&quot;&gt;Some of the best known examples used to explain the power of prominent Natural Language Processing tools (like Word2Vec) only seem to work with some cheating.&lt;/h2&gt;
&lt;p&gt;One of the most important fields for applying modern machine-learning tools is Natural Language Processing, or simply: NLP. It is about using digital tools to analyze, interpret and even generate human (natural) language.&lt;/p&gt;
&lt;p&gt;Arguably the most famous algorithm, known by virtually all people in the NLP field (and even to many people interested in machine-learning but not working on NLP) is &lt;strong&gt;Word2Vec&lt;/strong&gt;. Word2Vec has been implemented in a few ways that makes it very easy to use. And it is frequently taught as an example in many introductory machine-learning/AI or NLP courses.&lt;/p&gt;
&lt;p&gt;One of the main reasons people like it is that it seems very intuitive. Most of all, its fame stems from some striking, intuition-building examples that are often used to demonstrate what Word2Vec is capable of. To explain briefly what Word2Vec does:&lt;/p&gt;
&lt;p&gt;It looks at large amounts of text and counts which words frequently co-occur with others. Based on those co-occurrences, Word2Vec finds abstract representations for every word, so called &lt;strong&gt;word embeddings&lt;/strong&gt;. This are low-dimensional vectors (think of a list of 200 or 300 numbers). Once you have those word vectors, you can do nearly-magical math with words! If you take the vectors for King, Man, Woman, you can calculate King - Man + Woman and then you’ll get the vector for: Queen!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2166&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WZsoh-HYxhXEEf5Q_gsQsw-dc557f8b.qKHizdzM_17YKI2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I can really recommend playing with word vectors! It’s fun and you can find plenty of pre-trained networks, so you can get started right away. Try this word vector calculator. If you then feel like doing some training on cocktail books yourself, I highly recommend “Liquid Intelligence” by Dave Arnold (in word embeddings that would probably be: cocktails — fuzz + linear_algebra). Cartoon by Florian Huber, licensed under CC BY 4.0. (which means: feel free to share or re-use it, if you don’t mind my limited drawing skills).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wow. King - Man + Woman = Queen!&lt;/strong&gt;&lt;br&gt;
That is magic. The algorithm hence learned what the words &lt;em&gt;mean&lt;/em&gt;. It kind of &lt;em&gt;understands&lt;/em&gt; them. At least that’s how it seems…&lt;br&gt;
The problem is, that reducing Word2Vec to this one paramount example has been a huge mistake in my opinion. To me (and I believe many others as well) this has been very misleading.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;225&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vRUQP7Yno5--CKJ2vYXahg-84aae3cd.B_qaU8Jl_2XBbz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Just to be clear:&lt;/strong&gt; there is nothing wrong with the algorithm itself! It is conceptually very interesting and works very well for a lot of cases. Done right, it can give a decent representation of word similarity or meaning. But the &lt;em&gt;“King - Man + Woman = Queen”&lt;/em&gt; example by faroverstates what the algorithm actually is capable of.&lt;/p&gt;
&lt;p&gt;Here are some reasons why I think we should stop using that classical example to introduce Word2Vec:&lt;/p&gt;
&lt;p&gt;1 It turns out that for the example to work in the first place, you have to include some &lt;strong&gt;‘cheating’&lt;/strong&gt;. The actual result would namely be King - Man + Woman = King. So, the resulting vector would be more similar to King than to Queen. The widely known example only works because the implementation of the algorithm will exclude the original vector from the possible results! That means the word vector for &lt;strong&gt;King - Man + Woman&lt;/strong&gt; is closest to the word vector for King. Second comes Queen, which is what the routine will then pick. Quite disappointing, isn’t it?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;283&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FoPjjRbKP2gkyGxAqvMzCg-945b7e28.BBzJvZRs_Z2cbwWl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In many courses and tutorials I’ve seen, this issue was not mentioned. I hence believe it is still not common knowledge. It was actually only in one of the better online NLP courses that I finally learned about this disappointing &lt;em&gt;‘trick’&lt;/em&gt; (&lt;a href=&quot;https://www.coursera.org/lecture/language-processing/word-analogies-without-magic-king-man-woman-queen-lpSIA&quot;&gt;HSE course on NLP, worth a visit!&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Recently, three researchers from the University of Groningen tested many of the given examples from some of the key publications on Word2Vec. While some examples indeed worked as intended, a frustratingly high number of the given examples really only worked when using the little ‘trick’ of not allowing the query word itself (see also: &lt;a href=&quot;https://arxiv.org/abs/1905.09866&quot;&gt;[Nissim 2019&lt;/a&gt;]).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1110&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tFmq8FUI8SzxKKqo_kgmpQ-46f90cca.CR4UwMxo_2dBQ9u.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Table taken from Nissim et al. (2019): &lt;a href=&quot;https://arxiv.org/abs/1905.09866&quot;&gt;https://arxiv.org/abs/1905.09866&lt;/a&gt;. The authors tested a list of analogy examples from key articles using Word2Vec. They did a query of the type C is to B as A is to X. “Index” denotes the position the reported answer (“Reported”) was actually found (very often NOT “1”!). In addition the 1st and 2nd answer given by the algorithm is displayed in the two right columns.&lt;/p&gt;
&lt;p&gt;2 Unfortunately, things get worse.&lt;br&gt;
Finley et al. [2017] did a more thorough analysis of analogies other than Male-Female/King-Queen/Man-Woman. They evaluated a wide range of syntactic and semantic analogies and found that such calculations based on word embeddings (i.e. word vectors) do perform well for some types of analogies, but really poor for others. In the category ‘lexical semantics’ those algorithms seem to perform particularly badly…. with one very notable outlier: male-female analogies! So, in a way those examples typically given in lectures or tutorials rather represent an exception than the rule (see also &lt;a href=&quot;https://www.aclweb.org/anthology/S17-1001&quot;&gt;[Finley 2017]&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;3When it comes to going beyond this one shiny example and comparing different methods for producing word-embeddings, people usually compare the methods accuracy across a large corpus of texts. Even here, things seem to be more complex than often told. Some interesting studies (see [Levy et al., 2016]) clearly demonstrate that we need to be really careful when comparing different algorithms. And that includes Word2Vec.&lt;/p&gt;
&lt;p&gt;Quite often the “new” method is optimized towards a test dataset to perform well. Then it is compared to the “old” methods, which is fine. Only that those were much less optimized for the respective datasets. When done properly the outcome often is much less convincing, and in many cases reveals that there is very little difference between old methods (done right) and new methods (see also &lt;a href=&quot;https://www.aclweb.org/anthology/Q15-1016&quot;&gt;[Levy 2016]&lt;/a&gt;, &lt;a href=&quot;https://papers.nips.cc/paper/5477-neural-word-embedding-as-implicit-matrix-factorization.pdf&quot;&gt;[Levy 2014]&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;All of this tells me two things:&lt;/p&gt;
&lt;p&gt;Be careful when comparing methods using benchmarks on one or few particular datasets. That holds true far beyond this Word2Vec example!&lt;/p&gt;
&lt;p&gt;And stop reducing Word2Vec to the &lt;em&gt;“King - Man + Woman = Queen”&lt;/em&gt; example. It creates unrealistically high expectations. Well… and it’s actually not even working without cheating.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A very good free online course on NLP is done by the HSE in Moscow and can be found on Coursera. This was clearly one of the better NLP courses I’ve seen, and it also puts Word2Vec very clearly into perspective.&lt;br&gt;
→ &lt;a href=&quot;https://www.coursera.org/learn/language-processing&quot;&gt;Link to HSE/Coursera NLP course&lt;/a&gt;.&lt;br&gt;
→ &lt;a href=&quot;https://www.coursera.org/lecture/language-processing/word-analogies-without-magic-king-man-woman-queen-lpSIA&quot;&gt;Link to video from that course on King-man-woman-queen example&lt;/a&gt;.&lt;br&gt;
→ &lt;a href=&quot;https://github.com/hse-aml/natural-language-processing&quot;&gt;Link to their GitHub repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Like to play with some word embeddings? There is a lot of pre-trained, ready-to-use stuff out there. &lt;a href=&quot;http://vectors.nlpl.eu/explore/embeddings/en/calculator/&quot;&gt;Try for instance this &lt;strong&gt;semantic calculator&lt;/strong&gt;&lt;/a&gt;. You can choose between different models trained on Google News, English Wikipedia and others. Fun to play with, and good to get a first glimpse of what it can and cannot do.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/1905.09866&quot;&gt;&lt;strong&gt;Nissim, van Noord, van der Goot (2019)&lt;/strong&gt;: Fair is Better than Sensational:&lt;br&gt;
Man is to Doctor as Woman is to Doctor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aclweb.org/anthology/Q15-1016&quot;&gt;&lt;strong&gt;Levy, Goldberg, Dagan (2016)&lt;/strong&gt;: Improving Distributional Similarity&lt;br&gt;
with Lessons Learned from Word Embeddings.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://papers.nips.cc/paper/5477-neural-word-embedding-as-implicit-matrix-factorization.pdf&quot;&gt;&lt;strong&gt;Levy and Goldberg (2014)&lt;/strong&gt;: Neural Word Embedding&lt;br&gt;
as Implicit Matrix Factorization.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aclweb.org/anthology/S17-1001&quot;&gt;&lt;strong&gt;Finley, Farmer, Pakhomov (2017)&lt;/strong&gt;: What Analogies Reveal about Word Vectors and their Compositionality.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a side note: In this blog post I mainly write about Word2Vec (or very related algorithms). But given the severity of the issues listed above I also expect that the same problem could be found for many other popular word embeddings as well. It certainly seems worth testing.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to&lt;/em&gt; &lt;em&gt;, and&lt;/em&gt; &lt;em&gt;for helpful discussions and comments.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Mon, 15 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;some-of-the-best-known-examples-used-to-explain-the-power-of-prominent-natural-language-processing-tools-like-word2vec-only-seem-to-work-with-some-cheating&quot;&gt;Some of the best known examples used to explain the power of prominent Natural Language Processing tools (like Word2Vec) only seem to work with some cheating.&lt;/h2&gt;
&lt;p&gt;One of the most important fields for applying modern machine-learning tools is Natural Language Processing, or simply: NLP. It is about using digital tools to analyze, interpret and even generate human (natural) language.&lt;/p&gt;
&lt;p&gt;Arguably the most famous algorithm, known by virtually all people in the NLP field (and even to many people interested in machine-learning but not working on NLP) is &lt;strong&gt;Word2Vec&lt;/strong&gt;. Word2Vec has been implemented in a few ways that makes it very easy to use. And it is frequently taught as an example in many introductory machine-learning/AI or NLP courses.&lt;/p&gt;
&lt;p&gt;One of the main reasons people like it is that it seems very intuitive. Most of all, its fame stems from some striking, intuition-building examples that are often used to demonstrate what Word2Vec is capable of. To explain briefly what Word2Vec does:&lt;/p&gt;
&lt;p&gt;It looks at large amounts of text and counts which words frequently co-occur with others. Based on those co-occurrences, Word2Vec finds abstract representations for every word, so called &lt;strong&gt;word embeddings&lt;/strong&gt;. This are low-dimensional vectors (think of a list of 200 or 300 numbers). Once you have those word vectors, you can do nearly-magical math with words! If you take the vectors for King, Man, Woman, you can calculate King - Man + Woman and then you’ll get the vector for: Queen!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2166&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WZsoh-HYxhXEEf5Q_gsQsw-dc557f8b.qKHizdzM_17YKI2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I can really recommend playing with word vectors! It’s fun and you can find plenty of pre-trained networks, so you can get started right away. Try this word vector calculator. If you then feel like doing some training on cocktail books yourself, I highly recommend “Liquid Intelligence” by Dave Arnold (in word embeddings that would probably be: cocktails — fuzz + linear_algebra). Cartoon by Florian Huber, licensed under CC BY 4.0. (which means: feel free to share or re-use it, if you don’t mind my limited drawing skills).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wow. King - Man + Woman = Queen!&lt;/strong&gt;&lt;br&gt;
That is magic. The algorithm hence learned what the words &lt;em&gt;mean&lt;/em&gt;. It kind of &lt;em&gt;understands&lt;/em&gt; them. At least that’s how it seems…&lt;br&gt;
The problem is, that reducing Word2Vec to this one paramount example has been a huge mistake in my opinion. To me (and I believe many others as well) this has been very misleading.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;225&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vRUQP7Yno5--CKJ2vYXahg-84aae3cd.B_qaU8Jl_2XBbz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Just to be clear:&lt;/strong&gt; there is nothing wrong with the algorithm itself! It is conceptually very interesting and works very well for a lot of cases. Done right, it can give a decent representation of word similarity or meaning. But the &lt;em&gt;“King - Man + Woman = Queen”&lt;/em&gt; example by faroverstates what the algorithm actually is capable of.&lt;/p&gt;
&lt;p&gt;Here are some reasons why I think we should stop using that classical example to introduce Word2Vec:&lt;/p&gt;
&lt;p&gt;1 It turns out that for the example to work in the first place, you have to include some &lt;strong&gt;‘cheating’&lt;/strong&gt;. The actual result would namely be King - Man + Woman = King. So, the resulting vector would be more similar to King than to Queen. The widely known example only works because the implementation of the algorithm will exclude the original vector from the possible results! That means the word vector for &lt;strong&gt;King - Man + Woman&lt;/strong&gt; is closest to the word vector for King. Second comes Queen, which is what the routine will then pick. Quite disappointing, isn’t it?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;283&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FoPjjRbKP2gkyGxAqvMzCg-945b7e28.BBzJvZRs_Z2cbwWl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In many courses and tutorials I’ve seen, this issue was not mentioned. I hence believe it is still not common knowledge. It was actually only in one of the better online NLP courses that I finally learned about this disappointing &lt;em&gt;‘trick’&lt;/em&gt; (&lt;a href=&quot;https://www.coursera.org/lecture/language-processing/word-analogies-without-magic-king-man-woman-queen-lpSIA&quot;&gt;HSE course on NLP, worth a visit!&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Recently, three researchers from the University of Groningen tested many of the given examples from some of the key publications on Word2Vec. While some examples indeed worked as intended, a frustratingly high number of the given examples really only worked when using the little ‘trick’ of not allowing the query word itself (see also: &lt;a href=&quot;https://arxiv.org/abs/1905.09866&quot;&gt;[Nissim 2019&lt;/a&gt;]).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1110&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tFmq8FUI8SzxKKqo_kgmpQ-46f90cca.CR4UwMxo_2dBQ9u.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Table taken from Nissim et al. (2019): &lt;a href=&quot;https://arxiv.org/abs/1905.09866&quot;&gt;https://arxiv.org/abs/1905.09866&lt;/a&gt;. The authors tested a list of analogy examples from key articles using Word2Vec. They did a query of the type C is to B as A is to X. “Index” denotes the position the reported answer (“Reported”) was actually found (very often NOT “1”!). In addition the 1st and 2nd answer given by the algorithm is displayed in the two right columns.&lt;/p&gt;
&lt;p&gt;2 Unfortunately, things get worse.&lt;br&gt;
Finley et al. [2017] did a more thorough analysis of analogies other than Male-Female/King-Queen/Man-Woman. They evaluated a wide range of syntactic and semantic analogies and found that such calculations based on word embeddings (i.e. word vectors) do perform well for some types of analogies, but really poor for others. In the category ‘lexical semantics’ those algorithms seem to perform particularly badly…. with one very notable outlier: male-female analogies! So, in a way those examples typically given in lectures or tutorials rather represent an exception than the rule (see also &lt;a href=&quot;https://www.aclweb.org/anthology/S17-1001&quot;&gt;[Finley 2017]&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;3When it comes to going beyond this one shiny example and comparing different methods for producing word-embeddings, people usually compare the methods accuracy across a large corpus of texts. Even here, things seem to be more complex than often told. Some interesting studies (see [Levy et al., 2016]) clearly demonstrate that we need to be really careful when comparing different algorithms. And that includes Word2Vec.&lt;/p&gt;
&lt;p&gt;Quite often the “new” method is optimized towards a test dataset to perform well. Then it is compared to the “old” methods, which is fine. Only that those were much less optimized for the respective datasets. When done properly the outcome often is much less convincing, and in many cases reveals that there is very little difference between old methods (done right) and new methods (see also &lt;a href=&quot;https://www.aclweb.org/anthology/Q15-1016&quot;&gt;[Levy 2016]&lt;/a&gt;, &lt;a href=&quot;https://papers.nips.cc/paper/5477-neural-word-embedding-as-implicit-matrix-factorization.pdf&quot;&gt;[Levy 2014]&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;All of this tells me two things:&lt;/p&gt;
&lt;p&gt;Be careful when comparing methods using benchmarks on one or few particular datasets. That holds true far beyond this Word2Vec example!&lt;/p&gt;
&lt;p&gt;And stop reducing Word2Vec to the &lt;em&gt;“King - Man + Woman = Queen”&lt;/em&gt; example. It creates unrealistically high expectations. Well… and it’s actually not even working without cheating.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A very good free online course on NLP is done by the HSE in Moscow and can be found on Coursera. This was clearly one of the better NLP courses I’ve seen, and it also puts Word2Vec very clearly into perspective.&lt;br&gt;
→ &lt;a href=&quot;https://www.coursera.org/learn/language-processing&quot;&gt;Link to HSE/Coursera NLP course&lt;/a&gt;.&lt;br&gt;
→ &lt;a href=&quot;https://www.coursera.org/lecture/language-processing/word-analogies-without-magic-king-man-woman-queen-lpSIA&quot;&gt;Link to video from that course on King-man-woman-queen example&lt;/a&gt;.&lt;br&gt;
→ &lt;a href=&quot;https://github.com/hse-aml/natural-language-processing&quot;&gt;Link to their GitHub repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Like to play with some word embeddings? There is a lot of pre-trained, ready-to-use stuff out there. &lt;a href=&quot;http://vectors.nlpl.eu/explore/embeddings/en/calculator/&quot;&gt;Try for instance this &lt;strong&gt;semantic calculator&lt;/strong&gt;&lt;/a&gt;. You can choose between different models trained on Google News, English Wikipedia and others. Fun to play with, and good to get a first glimpse of what it can and cannot do.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/1905.09866&quot;&gt;&lt;strong&gt;Nissim, van Noord, van der Goot (2019)&lt;/strong&gt;: Fair is Better than Sensational:&lt;br&gt;
Man is to Doctor as Woman is to Doctor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aclweb.org/anthology/Q15-1016&quot;&gt;&lt;strong&gt;Levy, Goldberg, Dagan (2016)&lt;/strong&gt;: Improving Distributional Similarity&lt;br&gt;
with Lessons Learned from Word Embeddings.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://papers.nips.cc/paper/5477-neural-word-embedding-as-implicit-matrix-factorization.pdf&quot;&gt;&lt;strong&gt;Levy and Goldberg (2014)&lt;/strong&gt;: Neural Word Embedding&lt;br&gt;
as Implicit Matrix Factorization.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.aclweb.org/anthology/S17-1001&quot;&gt;&lt;strong&gt;Finley, Farmer, Pakhomov (2017)&lt;/strong&gt;: What Analogies Reveal about Word Vectors and their Compositionality.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a side note: In this blog post I mainly write about Word2Vec (or very related algorithms). But given the severity of the issues listed above I also expect that the same problem could be found for many other popular word embeddings as well. It certainly seems worth testing.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to&lt;/em&gt; &lt;em&gt;, and&lt;/em&gt; &lt;em&gt;for helpful discussions and comments.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_WZsoh-HYxhXEEf5Q_gsQsw-dc557f8b.qKHizdzM.png" medium="image"/><author>Florian Huber</author></item><item><title>why all you’ll ever need is markdown</title><link>https://blog2.esciencecenter.nl/posts/2019-07-02---why-all-youll-ever-need-is-markdown</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-07-02---why-all-youll-ever-need-is-markdown</guid><description>&lt;h2 id=&quot;an-introduction-to-pandoc&quot;&gt;an introduction to Pandoc&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4240&quot; height=&quot;2384&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4G2GgU10iJkPldd1-e299d9db.BLs2j-O3_aQkOr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Daniel McCullough on Unsplash&lt;/p&gt;
&lt;p&gt;Markdown is widely used for writing up documents. It is supported by many blog engines, GitHub readme, you name it. There are many varieties, dialects and extensions to Markdown. The standard is described on the &lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Daring Fireball website&lt;/a&gt;. One place where many flavours of Markdown meet is in &lt;a href=&quot;https://pandoc.org/&quot;&gt;Pandoc&lt;/a&gt;. Pandoc can convert Markdown to many different formats like HTML, LaTeX, PDF (through LaTeX), RTF, DOC, EPUB and even back to Markdown of a different flavour. There are some little known features (or extensions) of Markdown that make it very versatile and suitable for any rich text content, especially if you use Pandoc.&lt;/p&gt;
&lt;p&gt;The take-away message is: you will never again have to write a document in LaTeX or HTML directly, not for writing notes, reports or papers, no power-point for presentations, no awkward wysiwig editor for web content (I’m talking to you Medium!); just use Markdown.&lt;/p&gt;
&lt;p&gt;You might ask “But Johan, how do I then …?”, shush! The answer is always going to be: &lt;strong&gt;Pandoc&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;primer&quot;&gt;Primer&lt;/h2&gt;
&lt;p&gt;Markdown is a way of writing up rich content (i.e. text, document hierarchy, images, lists, quotes, etc.) in plain text using a human readable format. The format is aimed to mimic in plain text the formatted result:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Level&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Header&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==============&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Lorem&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ipsum dolor sit amet, consectetur adipiscing elit, sed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;eiusmod tempor incididunt ut labore et dolore magna aliqua&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Level&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Header&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--------------Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;nisi ut aliquip ex ea commodo consequat&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Another&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; item&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;##&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Also&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Level&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HeaderDuis&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; aute irure dolor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; reprehenderit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; voluptate velit esse cillum dolore eu fugiat nulla pariatur&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; quote&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Excepteur&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sint occaecat cupidatat non proident, sunt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; culpa qui officia deserunt mollit anim id est laborum&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can read &lt;a href=&quot;https://daringfireball.net/projects/markdown/syntax&quot;&gt;Daring Fireball&lt;/a&gt; for more syntax. The basics of Markdown are highly intuitive, but in many instances standard Markdown does not suffice: there is no support for equations, citation management, cross references or numbered figures. However, Pandoc supports many extensions and flavours of Markdown that have evolved over the years. Markdown feels a bit like a natural language. This has lead to some &lt;a href=&quot;https://www.ericholscher.com/blog/2016/mar/15/dont-use-markdown-for-technical-docs/&quot;&gt;critique on the use of Markdown in technical documents&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will highlight some extensions, all clearly documented and supported by Pandoc, that transform Markdown into a versatile and extendable format, suitable for even the most technical and demanding documents, yet easy to use when no such demands arise.&lt;/p&gt;
&lt;h3 id=&quot;flavours-and-extensions&quot;&gt;Flavours and extensions&lt;/h3&gt;
&lt;p&gt;There are many extensions to Markdown, some of which are more widely used than others. One of the most influencial flavour of Markdown is the superset by Github, its major addition being that of delimited code blocks.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`javascript&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;var factorial &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; factorial(n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;—&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;attributes&quot;&gt;Attributes&lt;/h3&gt;
&lt;p&gt;Nothing good ever comes from PHP, except for PHP Markdown, which adds attributes to Markdown.&lt;/p&gt;
&lt;p&gt;Any element in a Markdown document can be adorned with (CSS style) attributes by appending them in curly braces: &lt;code&gt;{#id .class .class key=value}&lt;/code&gt;. For example,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;## The proof {#proof .section color=red}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;when converted to HTML looks like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h2 id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;proof&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;section&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; proof&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or to LaTeX&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hypertarget{proof}{%&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;\subsection{The proof}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;label{proof}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the case of LaTeX, the &lt;code&gt;color&lt;/code&gt; attribute as well as the class is ignored, because Pandoc (by default) doesn’t know what to do with it. The &lt;code&gt;#proof&lt;/code&gt; id attached to this header can be used further on in the document to make cross-references.&lt;/p&gt;
&lt;p&gt;The attribute syntax also applies to code blocks: a line starting with &lt;code&gt;```python&lt;/code&gt; is equivalent to &lt;code&gt;``` {.python}&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;div-elements&quot;&gt;DIV elements&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;&amp;#x3C;div&gt;&lt;/code&gt; element can be added using three (or more) colons.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {.warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;This&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is a warning&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be used to write down any non-standard element. So how is this rendered? If your output format is HTML, change the style sheet. For generating LaTeX however we need to do a bit more work. This is where Pandoc comes in. Pandoc has support for filtering elements and creating relevant output, but we’ll get back to that.&lt;/p&gt;
&lt;h3 id=&quot;yaml-metadata&quot;&gt;YAML metadata&lt;/h3&gt;
&lt;p&gt;Information that is usually contained in a HTML &lt;code&gt;&amp;#x3C;header&gt;&lt;/code&gt; region can be included in the YAML metadata block. This is a block delimited by hyphens at the top of the document.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; theorem on right angled triangles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Pythagoras&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Samos&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;date&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2019&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;07&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;02&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is also the place where you can configure options for Pandoc and its filters.&lt;/p&gt;
&lt;h3 id=&quot;citations&quot;&gt;Citations&lt;/h3&gt;
&lt;p&gt;Citations are managed using the &lt;code&gt;pandoc-citeproc&lt;/code&gt; plugin. For those who have worked with BibTeX (or another bibliography database) before, you include the bibliography by adding a line to the YAML header block. Say you have stored your references in &lt;code&gt;ref.bib&lt;/code&gt;, and want to create a dedicated section called “References” to list the citations:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bibliography&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;reference&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;section&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; References&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are many ways to cite papers, the syntax for which is &lt;a href=&quot;https://pandoc.org/MANUAL.html#citations&quot;&gt;documented in the Pandoc manual.&lt;/a&gt; Basic citation looks like &lt;code&gt;[@Hidding2014]&lt;/code&gt;, where &lt;code&gt;Hidding2014&lt;/code&gt; is an entry in the bibliography. Several editors (VSCode and Emacs) even support autocompletion on the included bibliography.&lt;/p&gt;
&lt;h3 id=&quot;equations&quot;&gt;Equations&lt;/h3&gt;
&lt;p&gt;Equations can be entered using the famous LaTeX DSL for equations. Use single &lt;code&gt;$&lt;/code&gt; characters to delimit an inline equation and double &lt;code&gt;$$&lt;/code&gt; to delimit a full width equation.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Given&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a right angled triangle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sides &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and hypotenuse &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, we may state that,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.$$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When converting to a LaTeX based output this will work trivially. For HTML it is probably best to use MathJax, enabled in Pandoc with the &lt;code&gt;--mathjax&lt;/code&gt; and &lt;code&gt;--standalone&lt;/code&gt; flags.&lt;/p&gt;
&lt;p&gt;I promised to show you how Markdown can be extended with arbitrary functionality using Pandoc. It is inevitable that I will get a bit more technical here, but the rewards are high.&lt;/p&gt;
&lt;h2 id=&quot;pandoc-basics&quot;&gt;Pandoc basics&lt;/h2&gt;
&lt;p&gt;Pandoc reads and writes documents of many formats. It does so by converting to and from a native intermediate representation.&lt;/p&gt;
&lt;p&gt;We’ll create a document named &lt;code&gt;last-theorem.md&lt;/code&gt; and enter the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Last&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; theorem&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; P.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; de &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fermat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---For integer values of $a$, $b$, $c$ and $n &gt; 2$, the equation$$a^n + b^n = c^n,$$has no solution. I have a truly remarkable proof for this.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see how Pandoc reads a document by running&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t native &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will give (slightly edited for readability)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Pandoc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Meta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {unMeta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fromList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   [(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MetaInlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;P.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;de&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fermat&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   ,(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MetaInlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])]})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;that,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;integer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;values&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “of”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;the&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;equation&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DisplayMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;has&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;solution&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;have&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;truly&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elegant&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;proof&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;this,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;but&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;not&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;the&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;place&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;give&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;it&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, this is &lt;a href=&quot;https://haskell.org/&quot;&gt;Haskell&lt;/a&gt; syntax. It just means what you think it means. Using native output in Pandoc will be very useful if you start developing your own filters. For now it just serves to illustrates how Pandoc works. If you’re not a hacker, you’ll never have to look at this again 🤓👍.&lt;/p&gt;
&lt;p&gt;Let’s create a PDF from this mathematics wizardry.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t latex &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pdf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Resulting in a nice PDF rendering:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1167&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_D5CzmUE-GndA7H9_l0vAFQ-59a5604a.k0T8OjTD_Talat.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typeset paper on a famous theorem&lt;/p&gt;
&lt;h3 id=&quot;pandoc-filters&quot;&gt;Pandoc filters&lt;/h3&gt;
&lt;p&gt;There is a big problem with the above example. The equation is not numbered! Pandoc filters let you change the intermediate representation. Let’s try the &lt;code&gt;pandoc-eqnos&lt;/code&gt; filter. This filter is written in Python (using &lt;code&gt;pypandoc&lt;/code&gt;); any language that can read the intermediate JSON representation works.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pip install &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--user pandoc-eqnos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ll need to change the &lt;code&gt;last-theorem.md&lt;/code&gt; document a bit. To get an equation numbered, add an id to the equation.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {#eq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fermat}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also add a sentence to the end.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; prove &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inexistence &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a solution for &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Equation&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; @&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;eq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fermat had eluded mathematicians for centuries&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now to invoke the equation numbering filter, add the &lt;code&gt;--filter pandoc-eqnos&lt;/code&gt; argument to the command line.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t latex &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--filter pandoc-eqnos -o last-theorem.pdf -s last-theorem.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;336&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kt-38FBpJoz_V1RdJj9odQ-ff7349e8.G50ZgR2r_MR1qL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typeset paper on a famous theorem with numbered equations&lt;/p&gt;
&lt;p&gt;Pandoc command lines can grow out of hand rather quickly. It is advisable to manage your Pandoc settings in a Bash script or Make file, whatever you prefer.&lt;/p&gt;
&lt;h3 id=&quot;lua-filters&quot;&gt;Lua filters&lt;/h3&gt;
&lt;p&gt;Pandoc has built-in support for filters written in Lua. Filters written in Lua are generally faster than those written in Python or other external languages. Lua filters forego documents being passed to an external program via JSON, but rather work directly on the abstract syntax tree as it is represented in Pandoc itself.&lt;/p&gt;
&lt;p&gt;Let’s add a feature. Add the following to our budding math paper:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {.warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Modular&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; forms and elliptic curves ahead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To parse this, Pandoc needs the extension &lt;code&gt;fenced_divs&lt;/code&gt; enabled.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fenced_divs &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--filter pandoc-eqnos -t native -s last-theorem.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the end of the output will be the expression:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;warning&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Modular&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;forms&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elliptic&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;curves&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ahead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we generate HTML from this example, we can add the proper CSS to the &lt;code&gt;.warning&lt;/code&gt; class to change the looks of the warning. However, in the generated PDF there’s no change. Let’s make a filter that creates a nice coloured box in the LaTeX output. We define a filter that runs on all &lt;code&gt;Div&lt;/code&gt; elements in the file &lt;code&gt;warning-div.lua&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;classes[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;warning&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- insert element in front&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;insert(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      pandoc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RawBlock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;latex&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;begin{warning}&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- insert element at the back&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;insert(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      pandoc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RawBlock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;latex&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;end{warning}&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  return el&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The filter checks if the &lt;code&gt;div&lt;/code&gt; has class &lt;code&gt;warning&lt;/code&gt;, if so, it adds a LaTeX &lt;code&gt;RawBlock&lt;/code&gt; at the start and end of the &lt;code&gt;div&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Running Pandoc with &lt;code&gt;--lua-filter=warning-div.lua&lt;/code&gt; now converts the &lt;code&gt;div&lt;/code&gt; element to a LaTeX string&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;begin{warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Modular&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; forms and elliptic curves ahead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;end{warning}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not standard LaTeX, so we’ll need to define a macro in &lt;code&gt;warning.tex&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usepackage{tcolorbox}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;newenvironment{warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {\begin{tcolorbox}[colbacktitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;white,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                       title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Warning&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,coltitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;black,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                       fonttitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bfseries]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {\end{tcolorbox}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can run Pandoc again to generate the PDF. The &lt;code&gt;-H&lt;/code&gt; option can be used to include files into the generated output.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fenced_divs &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--filter pandoc-eqnos --lua-filter warning-div.lua -H warning.tex -t latex -o last-theorem.pdf -s last-theorem.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did I mention Pandoc command lines tend to grow out of hand?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;331&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4FIsZuEJ8O4AzlMpB3ARGw-616efe43.BtCnKQ3q_2vSCt1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typeset paper on a famous theorem with numbered equations and a warning&lt;/p&gt;
&lt;h2 id=&quot;skies-and-limits&quot;&gt;Skies and limits&lt;/h2&gt;
&lt;p&gt;Granted, to unlock the full power of Markdown for the web, you’ll need to know some HTML and CSS, and to tweak PDF output to your impossibly high standards you need to grok LaTeX. All the more reason to create an ecosystem of scripts, themes and tutorials to ease the learning curve. Also, code editors should offer better support for more varieties of markdown. I don’t mean cluttering up the editing experience with more distracting tool-tips, snippets etc. Just this: correct and efficient highlighting and proper outline support.&lt;/p&gt;
&lt;p&gt;This was just a teaser of what is possible with Pandoc. Did I mention creating slide shows with &lt;code&gt;reveal.js&lt;/code&gt;? Or how about doing some literate programming with &lt;code&gt;entangled&lt;/code&gt; [(see my previous post on that)?]( The documentation of Pandoc is excellent, so just go ahead and write all your content in Markdown!&lt;/p&gt;</description><pubDate>Tue, 02 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;an-introduction-to-pandoc&quot;&gt;an introduction to Pandoc&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4240&quot; height=&quot;2384&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_4G2GgU10iJkPldd1-e299d9db.BLs2j-O3_aQkOr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Daniel McCullough on Unsplash&lt;/p&gt;
&lt;p&gt;Markdown is widely used for writing up documents. It is supported by many blog engines, GitHub readme, you name it. There are many varieties, dialects and extensions to Markdown. The standard is described on the &lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Daring Fireball website&lt;/a&gt;. One place where many flavours of Markdown meet is in &lt;a href=&quot;https://pandoc.org/&quot;&gt;Pandoc&lt;/a&gt;. Pandoc can convert Markdown to many different formats like HTML, LaTeX, PDF (through LaTeX), RTF, DOC, EPUB and even back to Markdown of a different flavour. There are some little known features (or extensions) of Markdown that make it very versatile and suitable for any rich text content, especially if you use Pandoc.&lt;/p&gt;
&lt;p&gt;The take-away message is: you will never again have to write a document in LaTeX or HTML directly, not for writing notes, reports or papers, no power-point for presentations, no awkward wysiwig editor for web content (I’m talking to you Medium!); just use Markdown.&lt;/p&gt;
&lt;p&gt;You might ask “But Johan, how do I then …?”, shush! The answer is always going to be: &lt;strong&gt;Pandoc&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;primer&quot;&gt;Primer&lt;/h2&gt;
&lt;p&gt;Markdown is a way of writing up rich content (i.e. text, document hierarchy, images, lists, quotes, etc.) in plain text using a human readable format. The format is aimed to mimic in plain text the formatted result:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Level&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Header&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==============&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Lorem&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ipsum dolor sit amet, consectetur adipiscing elit, sed &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;eiusmod tempor incididunt ut labore et dolore magna aliqua&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Level&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Header&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--------------Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;nisi ut aliquip ex ea commodo consequat&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; list item&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Another&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; item&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;##&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Also&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Level&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; HeaderDuis&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; aute irure dolor &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; reprehenderit &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; voluptate velit esse cillum dolore eu fugiat nulla pariatur&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; quote&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Excepteur&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sint occaecat cupidatat non proident, sunt &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; culpa qui officia deserunt mollit anim id est laborum&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can read &lt;a href=&quot;https://daringfireball.net/projects/markdown/syntax&quot;&gt;Daring Fireball&lt;/a&gt; for more syntax. The basics of Markdown are highly intuitive, but in many instances standard Markdown does not suffice: there is no support for equations, citation management, cross references or numbered figures. However, Pandoc supports many extensions and flavours of Markdown that have evolved over the years. Markdown feels a bit like a natural language. This has lead to some &lt;a href=&quot;https://www.ericholscher.com/blog/2016/mar/15/dont-use-markdown-for-technical-docs/&quot;&gt;critique on the use of Markdown in technical documents&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I will highlight some extensions, all clearly documented and supported by Pandoc, that transform Markdown into a versatile and extendable format, suitable for even the most technical and demanding documents, yet easy to use when no such demands arise.&lt;/p&gt;
&lt;h3 id=&quot;flavours-and-extensions&quot;&gt;Flavours and extensions&lt;/h3&gt;
&lt;p&gt;There are many extensions to Markdown, some of which are more widely used than others. One of the most influencial flavour of Markdown is the superset by Github, its major addition being that of delimited code blocks.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`javascript&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;var factorial &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; factorial(n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;—&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;attributes&quot;&gt;Attributes&lt;/h3&gt;
&lt;p&gt;Nothing good ever comes from PHP, except for PHP Markdown, which adds attributes to Markdown.&lt;/p&gt;
&lt;p&gt;Any element in a Markdown document can be adorned with (CSS style) attributes by appending them in curly braces: &lt;code&gt;{#id .class .class key=value}&lt;/code&gt;. For example,&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;## The proof {#proof .section color=red}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;when converted to HTML looks like&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h2 id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;proof&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;section&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; color&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;red&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; proof&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;h2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or to LaTeX&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hypertarget{proof}{%&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;\subsection{The proof}&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;label{proof}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the case of LaTeX, the &lt;code&gt;color&lt;/code&gt; attribute as well as the class is ignored, because Pandoc (by default) doesn’t know what to do with it. The &lt;code&gt;#proof&lt;/code&gt; id attached to this header can be used further on in the document to make cross-references.&lt;/p&gt;
&lt;p&gt;The attribute syntax also applies to code blocks: a line starting with &lt;code&gt;```python&lt;/code&gt; is equivalent to &lt;code&gt;``` {.python}&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;div-elements&quot;&gt;DIV elements&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;&amp;#x3C;div&gt;&lt;/code&gt; element can be added using three (or more) colons.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {.warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;This&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is a warning&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be used to write down any non-standard element. So how is this rendered? If your output format is HTML, change the style sheet. For generating LaTeX however we need to do a bit more work. This is where Pandoc comes in. Pandoc has support for filtering elements and creating relevant output, but we’ll get back to that.&lt;/p&gt;
&lt;h3 id=&quot;yaml-metadata&quot;&gt;YAML metadata&lt;/h3&gt;
&lt;p&gt;Information that is usually contained in a HTML &lt;code&gt;&amp;#x3C;header&gt;&lt;/code&gt; region can be included in the YAML metadata block. This is a block delimited by hyphens at the top of the document.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; A&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; theorem on right angled triangles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Pythagoras&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Samos&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;date&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2019&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;07&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;02&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is also the place where you can configure options for Pandoc and its filters.&lt;/p&gt;
&lt;h3 id=&quot;citations&quot;&gt;Citations&lt;/h3&gt;
&lt;p&gt;Citations are managed using the &lt;code&gt;pandoc-citeproc&lt;/code&gt; plugin. For those who have worked with BibTeX (or another bibliography database) before, you include the bibliography by adding a line to the YAML header block. Say you have stored your references in &lt;code&gt;ref.bib&lt;/code&gt;, and want to create a dedicated section called “References” to list the citations:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bibliography&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ref&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;reference&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;section&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; References&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are many ways to cite papers, the syntax for which is &lt;a href=&quot;https://pandoc.org/MANUAL.html#citations&quot;&gt;documented in the Pandoc manual.&lt;/a&gt; Basic citation looks like &lt;code&gt;[@Hidding2014]&lt;/code&gt;, where &lt;code&gt;Hidding2014&lt;/code&gt; is an entry in the bibliography. Several editors (VSCode and Emacs) even support autocompletion on the included bibliography.&lt;/p&gt;
&lt;h3 id=&quot;equations&quot;&gt;Equations&lt;/h3&gt;
&lt;p&gt;Equations can be entered using the famous LaTeX DSL for equations. Use single &lt;code&gt;$&lt;/code&gt; characters to delimit an inline equation and double &lt;code&gt;$$&lt;/code&gt; to delimit a full width equation.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Given&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a right angled triangle &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sides &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; and hypotenuse &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, we may state that,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.$$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When converting to a LaTeX based output this will work trivially. For HTML it is probably best to use MathJax, enabled in Pandoc with the &lt;code&gt;--mathjax&lt;/code&gt; and &lt;code&gt;--standalone&lt;/code&gt; flags.&lt;/p&gt;
&lt;p&gt;I promised to show you how Markdown can be extended with arbitrary functionality using Pandoc. It is inevitable that I will get a bit more technical here, but the rewards are high.&lt;/p&gt;
&lt;h2 id=&quot;pandoc-basics&quot;&gt;Pandoc basics&lt;/h2&gt;
&lt;p&gt;Pandoc reads and writes documents of many formats. It does so by converting to and from a native intermediate representation.&lt;/p&gt;
&lt;p&gt;We’ll create a document named &lt;code&gt;last-theorem.md&lt;/code&gt; and enter the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Last&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; theorem&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; P.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; de &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fermat&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;---For integer values of $a$, $b$, $c$ and $n &gt; 2$, the equation$$a^n + b^n = c^n,$$has no solution. I have a truly remarkable proof for this.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see how Pandoc reads a document by running&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t native &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will give (slightly edited for readability)&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Pandoc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Meta&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {unMeta &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; fromList&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   [(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;author&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MetaInlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;P.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;de&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Fermat&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;   ,(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;MetaInlines&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])]})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;state&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;that,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;integer&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;values&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “of”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; InlineMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;the&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;equation&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; DisplayMath&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;has&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;no&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;solution&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;I&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;have&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;truly&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elegant&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;proof&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;this,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;but&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;not&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;the&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;place&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;give&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;it&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes, this is &lt;a href=&quot;https://haskell.org/&quot;&gt;Haskell&lt;/a&gt; syntax. It just means what you think it means. Using native output in Pandoc will be very useful if you start developing your own filters. For now it just serves to illustrates how Pandoc works. If you’re not a hacker, you’ll never have to look at this again 🤓👍.&lt;/p&gt;
&lt;p&gt;Let’s create a PDF from this mathematics wizardry.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t latex &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;o last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pdf &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;s last&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;theorem&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Resulting in a nice PDF rendering:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1167&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_D5CzmUE-GndA7H9_l0vAFQ-59a5604a.k0T8OjTD_Talat.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typeset paper on a famous theorem&lt;/p&gt;
&lt;h3 id=&quot;pandoc-filters&quot;&gt;Pandoc filters&lt;/h3&gt;
&lt;p&gt;There is a big problem with the above example. The equation is not numbered! Pandoc filters let you change the intermediate representation. Let’s try the &lt;code&gt;pandoc-eqnos&lt;/code&gt; filter. This filter is written in Python (using &lt;code&gt;pypandoc&lt;/code&gt;); any language that can read the intermediate JSON representation works.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pip install &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--user pandoc-eqnos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We’ll need to change the &lt;code&gt;last-theorem.md&lt;/code&gt; document a bit. To get an equation numbered, add an id to the equation.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; b&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;^&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n,&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {#eq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fermat}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also add a sentence to the end.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; prove &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; inexistence &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; a solution for &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Equation&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; @&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;eq&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fermat had eluded mathematicians for centuries&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now to invoke the equation numbering filter, add the &lt;code&gt;--filter pandoc-eqnos&lt;/code&gt; argument to the command line.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;t latex &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--filter pandoc-eqnos -o last-theorem.pdf -s last-theorem.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;336&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kt-38FBpJoz_V1RdJj9odQ-ff7349e8.G50ZgR2r_MR1qL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typeset paper on a famous theorem with numbered equations&lt;/p&gt;
&lt;p&gt;Pandoc command lines can grow out of hand rather quickly. It is advisable to manage your Pandoc settings in a Bash script or Make file, whatever you prefer.&lt;/p&gt;
&lt;h3 id=&quot;lua-filters&quot;&gt;Lua filters&lt;/h3&gt;
&lt;p&gt;Pandoc has built-in support for filters written in Lua. Filters written in Lua are generally faster than those written in Python or other external languages. Lua filters forego documents being passed to an external program via JSON, but rather work directly on the abstract syntax tree as it is represented in Pandoc itself.&lt;/p&gt;
&lt;p&gt;Let’s add a feature. Add the following to our budding math paper:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {.warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Modular&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; forms and elliptic curves ahead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:::&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To parse this, Pandoc needs the extension &lt;code&gt;fenced_divs&lt;/code&gt; enabled.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fenced_divs &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--filter pandoc-eqnos -t native -s last-theorem.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the end of the output will be the expression:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,[&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;warning&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;[]&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Para&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Modular&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;forms&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;elliptic&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;curves&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Space&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Str&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;ahead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we generate HTML from this example, we can add the proper CSS to the &lt;code&gt;.warning&lt;/code&gt; class to change the looks of the warning. However, in the generated PDF there’s no change. Let’s make a filter that creates a nice coloured box in the LaTeX output. We define a filter that runs on all &lt;code&gt;Div&lt;/code&gt; elements in the file &lt;code&gt;warning-div.lua&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;function &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Div&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(el)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;classes[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;warning&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- insert element in front&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;insert(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      pandoc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RawBlock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;latex&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;begin{warning}&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;    -- insert element at the back&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    table&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;insert(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      el&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;content,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      pandoc&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;RawBlock&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;latex&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;end{warning}&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  return el&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The filter checks if the &lt;code&gt;div&lt;/code&gt; has class &lt;code&gt;warning&lt;/code&gt;, if so, it adds a LaTeX &lt;code&gt;RawBlock&lt;/code&gt; at the start and end of the &lt;code&gt;div&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Running Pandoc with &lt;code&gt;--lua-filter=warning-div.lua&lt;/code&gt; now converts the &lt;code&gt;div&lt;/code&gt; element to a LaTeX string&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;begin{warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Modular&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; forms and elliptic curves ahead&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;end{warning}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not standard LaTeX, so we’ll need to define a macro in &lt;code&gt;warning.tex&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;usepackage{tcolorbox}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;newenvironment{warning}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {\begin{tcolorbox}[colbacktitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;white,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                       title&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Warning&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,coltitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;black,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;                       fonttitle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;bfseries]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {\end{tcolorbox}}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can run Pandoc again to generate the PDF. The &lt;code&gt;-H&lt;/code&gt; option can be used to include files into the generated output.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pandoc &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f markdown&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;yaml_metadata_block&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fenced_divs &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--filter pandoc-eqnos --lua-filter warning-div.lua -H warning.tex -t latex -o last-theorem.pdf -s last-theorem.md&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did I mention Pandoc command lines tend to grow out of hand?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;331&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4FIsZuEJ8O4AzlMpB3ARGw-616efe43.BtCnKQ3q_2vSCt1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typeset paper on a famous theorem with numbered equations and a warning&lt;/p&gt;
&lt;h2 id=&quot;skies-and-limits&quot;&gt;Skies and limits&lt;/h2&gt;
&lt;p&gt;Granted, to unlock the full power of Markdown for the web, you’ll need to know some HTML and CSS, and to tweak PDF output to your impossibly high standards you need to grok LaTeX. All the more reason to create an ecosystem of scripts, themes and tutorials to ease the learning curve. Also, code editors should offer better support for more varieties of markdown. I don’t mean cluttering up the editing experience with more distracting tool-tips, snippets etc. Just this: correct and efficient highlighting and proper outline support.&lt;/p&gt;
&lt;p&gt;This was just a teaser of what is possible with Pandoc. Did I mention creating slide shows with &lt;code&gt;reveal.js&lt;/code&gt;? Or how about doing some literate programming with &lt;code&gt;entangled&lt;/code&gt; [(see my previous post on that)?]( The documentation of Pandoc is excellent, so just go ahead and write all your content in Markdown!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_D5CzmUE-GndA7H9_l0vAFQ-59a5604a.k0T8OjTD.png" medium="image"/><author>Johan Hidding</author></item><item><title>derse 2019 first conference for research software engineers in germany</title><link>https://blog2.esciencecenter.nl/posts/2019-06-24---derse-2019-first-conference-for-research-software-engineers-in-germany</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-06-24---derse-2019-first-conference-for-research-software-engineers-in-germany</guid><description>&lt;p&gt;written by&lt;/p&gt;
&lt;p&gt;[Carlos Martinez-Ortiz]&lt;/p&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;p&gt;[Florian Huber]&lt;/p&gt;
&lt;h2 id=&quot;facts&quot;&gt;Facts&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What:&lt;/strong&gt; &lt;a href=&quot;https://www.de-rse.org/en/conf2019/&quot;&gt;First Conference for Research Software Engineers&lt;/a&gt; (RSE) in Germany&lt;br&gt;
&lt;strong&gt;When:&lt;/strong&gt; 4-6 June 2019&lt;br&gt;
&lt;strong&gt;Where:&lt;/strong&gt; Albert Einstein Science Park in Potsdam&lt;/p&gt;
&lt;h2 id=&quot;but-wait-what-is-a-rse-anyway&quot;&gt;But wait… what is a RSE anyway?&lt;/h2&gt;
&lt;p&gt;Like many other areas of society, the field of scientific research currently sees a quickly growing influence of new digital technologies and new IT concepts. Not surprisingly, this results in an ever-increasing need for people to tackle the increasing digitalization of research.&lt;/p&gt;
&lt;p&gt;In the past, people in many different positions within the academic landscape would take care of developing digital tools such as research software. Typically this included many PhD students and postdocs, hence positions with deviating job profiles and non-permanent contracts.&lt;/p&gt;
&lt;p&gt;In view of the rising need for digital expertise and the missing adequate positions and job descriptions within most academic systems, an initiative to establish a dedicated profession of the Research Software Engineer (&lt;strong&gt;RSE&lt;/strong&gt;) was started.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;997&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v-AmdN95tAiNrpO9EMc86g-a52b179e.vFyDQZ3a_Z1k7X0w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;deRSE19 aerial group photo (CC-BY Antonia Cozacu, Jan Philipp Dietrich, de-RSE e.V.)&lt;/p&gt;
&lt;p&gt;This initiative started in the UK with the &lt;a href=&quot;https://rse.ac.uk/&quot;&gt;UK Research Software Engineer Association&lt;/a&gt; (see also &lt;a href=&quot;https://www.software.ac.uk/blog/2016-08-17-not-so-brief-history-research-software-engineers-0&quot;&gt;the not-so-brief history of RSEs&lt;/a&gt;). Several countries followed and founded RSE organizations including the Netherlands (&lt;a href=&quot;http://nl-rse.org/&quot;&gt;NL-RSE&lt;/a&gt;) and Germany (&lt;a href=&quot;http://nl-rse.org/&quot;&gt;deRSE&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;https://twitter.com/alysbrett&quot;&gt;Alys Brett&lt;/a&gt; pointed out during her keynote, RSEs sit somewhere in between a researcher and a software engineer. The term RSE is still somewhat vague as it covers a broad spectrum of expertise and activities; there are no universal job specification or career paths defined for RSEs, &lt;a href=&quot;https://www.kdl.kcl.ac.uk/blog/rse-career-development/&quot;&gt;although some initiatives are emerging&lt;/a&gt;. Many people may be a RSE without realizing it!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;609&quot; height=&quot;457&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_LHILpQZNZqtPdkhb-ba62923b.BJXJbJQW_1vHDGs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from the presenation of Alys Brett pointing at the position of RSEs in between Software Engineering and Research.&lt;/p&gt;
&lt;p&gt;If we think of RSEs as individuals which combine (in different proportions) software engineering skills &amp;#x26; scientific research skills then it indeed covers a very broad range. This means the RSE community is in itself very diverse, which has the advantage of diversity of knowledge and expertise. However, the downside of this diversity is that it is difficult to put a RSE in a box and clearly identify who is a RSE.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;577&quot; height=&quot;458&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_J3KDe8ySfpOxzb3Z-f2a967e1.ChoDsMrU_1kay8V.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;rse-demographics&quot;&gt;RSE demographics&lt;/h2&gt;
&lt;p&gt;So, is this just a small group of people? Not really — since 2016, an &lt;a href=&quot;https://github.com/softwaresaved/international-survey/tree/master/analysis/2018&quot;&gt;international survey&lt;/a&gt; is conducted, asking individuals questions regarding their education, field of expertise, technical skills and demographic information. During the conference, &lt;a href=&quot;https://twitter.com/StephanJanosch&quot;&gt;Stephan Janosch&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/mrtnhmtz&quot;&gt;Martin Hammitzsch&lt;/a&gt; used this survey to give an impression of how the RSE landscape looks like in Germany. A similar analysis was conducted at &lt;a href=&quot;https://www.dlr.de/dlr/en/&quot;&gt;DLR&lt;/a&gt;, although some people at DLR do not identify as RSEs but as researchers which do software (&lt;a href=&quot;https://derse19.uni-jena.de/derse19/talk/MQCZ3N/&quot;&gt;see talk abstract&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;588&quot; height=&quot;524&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_m9ogy5N0x0CX1h7C-1e9b6ee0.Ds7iNjGh_2llADh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In general, the RSE landscape looks very similar to the current situation in the Netherlands. It still is a long way to go to establish the role of RSEs within the academic landscape. One indicator is the large fraction of non-permanent contracts among RSEs (see bar plots below). Another one is that actual job titles in Germany still show the lack of dedicated positions related to research software engineering (see word clouds below).&lt;/p&gt;
&lt;p&gt;It at first seems as if RSEs in the Netherlands can already rely a better job situation (more permanent positions) and better fitting job titles. However, bare in mind that the number of respondents in Germany was higher than in the Netherlands: 333 vs 54 which may induce some bias in the statistics. The numbers also heavily depend on who considers herself/himself a RSE. Hence who is actually responding to the survey. In the Netherlands we believe that a large number of participants working at the eScience Center dominate the statistics.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;856&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0n9pVvWQSfDUDrwJdSDrEw-a894b7e2.Dnduvjnt_1Yphr5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Plots from (or based on) a 2018 RSE survey. A larger fraction of RSEs in the Netherlands holds a permanent position (bar plots on the left. Permanent RSE employment: 57% vs 25% in Germany). And RSE-related job titles are still not common in the German academic setting (Job title wordclouds on the right. Top right: Netherlands. Bottom right: Germany). Both aspects will hopefully change through the actions of the RSE initiative. Also be aware that statistics for the Netherlands were fairly low for the survey and are likely to be dominated by people from the Netherlands eScience Center.&lt;/p&gt;
&lt;h2 id=&quot;what-will-the-future-bring-for-rses&quot;&gt;What will the future bring for RSE’s&lt;/h2&gt;
&lt;p&gt;We don’t know — undoubtedly research software will continue to play an important part in science and with it the role of RSEs will become more prominent.&lt;/p&gt;
&lt;p&gt;What we do know for sure is that deRSE was a fantastic conference and a great success! And it reminded us that would be very beneficial for the RSE community in the Netherlands to have another local RSE conference (we had a &lt;a href=&quot;http://nl-rse.org/2018/06/29/first-meetup.html&quot;&gt;first meet-up last year&lt;/a&gt;) where RSEs from different institutions can come together and share their experiences and thoughts. &lt;a href=&quot;http://nl-rse.org/pages/join.html&quot;&gt;Join the NL-RSE mailing list&lt;/a&gt; for updates on upcoming RSE events in the Netherlands.&lt;/p&gt;
&lt;h2 id=&quot;some-impressions-from-the-conference&quot;&gt;Some impressions from the conference&lt;/h2&gt;
&lt;p&gt;Over the three days of the conference we saw a lot of interesting presentations, posters, attended workshops and discussion sessions. Clearly too much to do all contributions justice. Here we just picked a few highlights that stuck with us and were not mentioned above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The secret behind the growth of RSE Groups in the UK (see &lt;a href=&quot;https://www.software.ac.uk/blog/2018-04-11-secret-behind-growth-rse-groups-uk&quot;&gt;their blog post&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/AndreasZeller&quot;&gt;Andreas Zeller&lt;/a&gt; gave a great entertaining keynote lecture on Sustainable Research Software. His suggestion was to use literate programming as well as prototyping.&lt;br&gt;
&lt;em&gt;Literate programming+ Prototyping =&lt;/em&gt; &lt;em&gt;&lt;strong&gt;Literate prototyping&lt;/strong&gt;&lt;/em&gt; *= Notebooks&lt;br&gt;
*(see also the [recent post on literate programming]( by
[Johan Hidding]
)&lt;/li&gt;
&lt;li&gt;There were about 40 posters and most of them were very briefly (1 minute) pitched in a special lightening session. This made it very clear how broad the audience was in terms of backgrounds and scientific research fields.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wfJTIrrkE3tX3ppF-2892970d.xAQYworH_Z1xrusa.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Presenters of brief poster pitches during the lightening session.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/konradfoerstner&quot;&gt;Konrad Förstner&lt;/a&gt; did &lt;a href=&quot;http://www.openscienceradio.org/2019/06/12/osr171-voices-from-de-rse-conference-2019-en/&quot;&gt;a Podcast&lt;/a&gt; during the conference and collected impressions from many of the participants (which again shows how diverse the field is!).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/alexhillphd&quot;&gt;Alex Hill&lt;/a&gt; was making a strong case for doing more reviews in her talk&lt;br&gt;
(she also wrote a &lt;a href=&quot;http://www.alexandra-hill.com/2018/06/25/the-art-of-giving-and-receiving-code-reviews/&quot;&gt;blog post on the same topic&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;final-notes&quot;&gt;Final notes&lt;/h2&gt;
&lt;p&gt;Many of the presentations were recorded and will soon be made available. Best to check out updates on their &lt;a href=&quot;https://twitter.com/RSE_de&quot;&gt;twitter channel&lt;/a&gt; or the &lt;a href=&quot;https://www.de-rse.org/en/conf2019/index.html&quot;&gt;conference website&lt;/a&gt;.&lt;br&gt;
Attending this conference was a lot of fun, so thanks for organizing and see you next time!&lt;/p&gt;
&lt;p&gt;Any comments, suggestions, or questions?&lt;br&gt;
Get in touch!&lt;/p&gt;
&lt;p&gt;[Carlos Martinez-Ortiz]&lt;/p&gt;
&lt;p&gt;| &lt;a href=&quot;https://twitter.com/neocarlitos&quot;&gt;Carlos on twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[Florian Huber]&lt;/p&gt;
&lt;p&gt;| &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;Florian on twitter&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 24 Jun 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;written by&lt;/p&gt;
&lt;p&gt;[Carlos Martinez-Ortiz]&lt;/p&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;p&gt;[Florian Huber]&lt;/p&gt;
&lt;h2 id=&quot;facts&quot;&gt;Facts&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What:&lt;/strong&gt; &lt;a href=&quot;https://www.de-rse.org/en/conf2019/&quot;&gt;First Conference for Research Software Engineers&lt;/a&gt; (RSE) in Germany&lt;br&gt;
&lt;strong&gt;When:&lt;/strong&gt; 4-6 June 2019&lt;br&gt;
&lt;strong&gt;Where:&lt;/strong&gt; Albert Einstein Science Park in Potsdam&lt;/p&gt;
&lt;h2 id=&quot;but-wait-what-is-a-rse-anyway&quot;&gt;But wait… what is a RSE anyway?&lt;/h2&gt;
&lt;p&gt;Like many other areas of society, the field of scientific research currently sees a quickly growing influence of new digital technologies and new IT concepts. Not surprisingly, this results in an ever-increasing need for people to tackle the increasing digitalization of research.&lt;/p&gt;
&lt;p&gt;In the past, people in many different positions within the academic landscape would take care of developing digital tools such as research software. Typically this included many PhD students and postdocs, hence positions with deviating job profiles and non-permanent contracts.&lt;/p&gt;
&lt;p&gt;In view of the rising need for digital expertise and the missing adequate positions and job descriptions within most academic systems, an initiative to establish a dedicated profession of the Research Software Engineer (&lt;strong&gt;RSE&lt;/strong&gt;) was started.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;997&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v-AmdN95tAiNrpO9EMc86g-a52b179e.vFyDQZ3a_Z1k7X0w.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;deRSE19 aerial group photo (CC-BY Antonia Cozacu, Jan Philipp Dietrich, de-RSE e.V.)&lt;/p&gt;
&lt;p&gt;This initiative started in the UK with the &lt;a href=&quot;https://rse.ac.uk/&quot;&gt;UK Research Software Engineer Association&lt;/a&gt; (see also &lt;a href=&quot;https://www.software.ac.uk/blog/2016-08-17-not-so-brief-history-research-software-engineers-0&quot;&gt;the not-so-brief history of RSEs&lt;/a&gt;). Several countries followed and founded RSE organizations including the Netherlands (&lt;a href=&quot;http://nl-rse.org/&quot;&gt;NL-RSE&lt;/a&gt;) and Germany (&lt;a href=&quot;http://nl-rse.org/&quot;&gt;deRSE&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;https://twitter.com/alysbrett&quot;&gt;Alys Brett&lt;/a&gt; pointed out during her keynote, RSEs sit somewhere in between a researcher and a software engineer. The term RSE is still somewhat vague as it covers a broad spectrum of expertise and activities; there are no universal job specification or career paths defined for RSEs, &lt;a href=&quot;https://www.kdl.kcl.ac.uk/blog/rse-career-development/&quot;&gt;although some initiatives are emerging&lt;/a&gt;. Many people may be a RSE without realizing it!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;609&quot; height=&quot;457&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_LHILpQZNZqtPdkhb-ba62923b.BJXJbJQW_1vHDGs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Slide from the presenation of Alys Brett pointing at the position of RSEs in between Software Engineering and Research.&lt;/p&gt;
&lt;p&gt;If we think of RSEs as individuals which combine (in different proportions) software engineering skills &amp;#x26; scientific research skills then it indeed covers a very broad range. This means the RSE community is in itself very diverse, which has the advantage of diversity of knowledge and expertise. However, the downside of this diversity is that it is difficult to put a RSE in a box and clearly identify who is a RSE.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;577&quot; height=&quot;458&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_J3KDe8ySfpOxzb3Z-f2a967e1.ChoDsMrU_1kay8V.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;rse-demographics&quot;&gt;RSE demographics&lt;/h2&gt;
&lt;p&gt;So, is this just a small group of people? Not really — since 2016, an &lt;a href=&quot;https://github.com/softwaresaved/international-survey/tree/master/analysis/2018&quot;&gt;international survey&lt;/a&gt; is conducted, asking individuals questions regarding their education, field of expertise, technical skills and demographic information. During the conference, &lt;a href=&quot;https://twitter.com/StephanJanosch&quot;&gt;Stephan Janosch&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/mrtnhmtz&quot;&gt;Martin Hammitzsch&lt;/a&gt; used this survey to give an impression of how the RSE landscape looks like in Germany. A similar analysis was conducted at &lt;a href=&quot;https://www.dlr.de/dlr/en/&quot;&gt;DLR&lt;/a&gt;, although some people at DLR do not identify as RSEs but as researchers which do software (&lt;a href=&quot;https://derse19.uni-jena.de/derse19/talk/MQCZ3N/&quot;&gt;see talk abstract&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;588&quot; height=&quot;524&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_m9ogy5N0x0CX1h7C-1e9b6ee0.Ds7iNjGh_2llADh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In general, the RSE landscape looks very similar to the current situation in the Netherlands. It still is a long way to go to establish the role of RSEs within the academic landscape. One indicator is the large fraction of non-permanent contracts among RSEs (see bar plots below). Another one is that actual job titles in Germany still show the lack of dedicated positions related to research software engineering (see word clouds below).&lt;/p&gt;
&lt;p&gt;It at first seems as if RSEs in the Netherlands can already rely a better job situation (more permanent positions) and better fitting job titles. However, bare in mind that the number of respondents in Germany was higher than in the Netherlands: 333 vs 54 which may induce some bias in the statistics. The numbers also heavily depend on who considers herself/himself a RSE. Hence who is actually responding to the survey. In the Netherlands we believe that a large number of participants working at the eScience Center dominate the statistics.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;856&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0n9pVvWQSfDUDrwJdSDrEw-a894b7e2.Dnduvjnt_1Yphr5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Plots from (or based on) a 2018 RSE survey. A larger fraction of RSEs in the Netherlands holds a permanent position (bar plots on the left. Permanent RSE employment: 57% vs 25% in Germany). And RSE-related job titles are still not common in the German academic setting (Job title wordclouds on the right. Top right: Netherlands. Bottom right: Germany). Both aspects will hopefully change through the actions of the RSE initiative. Also be aware that statistics for the Netherlands were fairly low for the survey and are likely to be dominated by people from the Netherlands eScience Center.&lt;/p&gt;
&lt;h2 id=&quot;what-will-the-future-bring-for-rses&quot;&gt;What will the future bring for RSE’s&lt;/h2&gt;
&lt;p&gt;We don’t know — undoubtedly research software will continue to play an important part in science and with it the role of RSEs will become more prominent.&lt;/p&gt;
&lt;p&gt;What we do know for sure is that deRSE was a fantastic conference and a great success! And it reminded us that would be very beneficial for the RSE community in the Netherlands to have another local RSE conference (we had a &lt;a href=&quot;http://nl-rse.org/2018/06/29/first-meetup.html&quot;&gt;first meet-up last year&lt;/a&gt;) where RSEs from different institutions can come together and share their experiences and thoughts. &lt;a href=&quot;http://nl-rse.org/pages/join.html&quot;&gt;Join the NL-RSE mailing list&lt;/a&gt; for updates on upcoming RSE events in the Netherlands.&lt;/p&gt;
&lt;h2 id=&quot;some-impressions-from-the-conference&quot;&gt;Some impressions from the conference&lt;/h2&gt;
&lt;p&gt;Over the three days of the conference we saw a lot of interesting presentations, posters, attended workshops and discussion sessions. Clearly too much to do all contributions justice. Here we just picked a few highlights that stuck with us and were not mentioned above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The secret behind the growth of RSE Groups in the UK (see &lt;a href=&quot;https://www.software.ac.uk/blog/2018-04-11-secret-behind-growth-rse-groups-uk&quot;&gt;their blog post&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/AndreasZeller&quot;&gt;Andreas Zeller&lt;/a&gt; gave a great entertaining keynote lecture on Sustainable Research Software. His suggestion was to use literate programming as well as prototyping.&lt;br&gt;
&lt;em&gt;Literate programming+ Prototyping =&lt;/em&gt; &lt;em&gt;&lt;strong&gt;Literate prototyping&lt;/strong&gt;&lt;/em&gt; *= Notebooks&lt;br&gt;
*(see also the [recent post on literate programming]( by
[Johan Hidding]
)&lt;/li&gt;
&lt;li&gt;There were about 40 posters and most of them were very briefly (1 minute) pitched in a special lightening session. This made it very clear how broad the audience was in terms of backgrounds and scientific research fields.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wfJTIrrkE3tX3ppF-2892970d.xAQYworH_Z1xrusa.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Presenters of brief poster pitches during the lightening session.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/konradfoerstner&quot;&gt;Konrad Förstner&lt;/a&gt; did &lt;a href=&quot;http://www.openscienceradio.org/2019/06/12/osr171-voices-from-de-rse-conference-2019-en/&quot;&gt;a Podcast&lt;/a&gt; during the conference and collected impressions from many of the participants (which again shows how diverse the field is!).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/alexhillphd&quot;&gt;Alex Hill&lt;/a&gt; was making a strong case for doing more reviews in her talk&lt;br&gt;
(she also wrote a &lt;a href=&quot;http://www.alexandra-hill.com/2018/06/25/the-art-of-giving-and-receiving-code-reviews/&quot;&gt;blog post on the same topic&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;final-notes&quot;&gt;Final notes&lt;/h2&gt;
&lt;p&gt;Many of the presentations were recorded and will soon be made available. Best to check out updates on their &lt;a href=&quot;https://twitter.com/RSE_de&quot;&gt;twitter channel&lt;/a&gt; or the &lt;a href=&quot;https://www.de-rse.org/en/conf2019/index.html&quot;&gt;conference website&lt;/a&gt;.&lt;br&gt;
Attending this conference was a lot of fun, so thanks for organizing and see you next time!&lt;/p&gt;
&lt;p&gt;Any comments, suggestions, or questions?&lt;br&gt;
Get in touch!&lt;/p&gt;
&lt;p&gt;[Carlos Martinez-Ortiz]&lt;/p&gt;
&lt;p&gt;| &lt;a href=&quot;https://twitter.com/neocarlitos&quot;&gt;Carlos on twitter&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[Florian Huber]&lt;/p&gt;
&lt;p&gt;| &lt;a href=&quot;https://twitter.com/me_datapoint&quot;&gt;Florian on twitter&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_v-AmdN95tAiNrpO9EMc86g-a52b179e.vFyDQZ3a.jpeg" medium="image"/><author>Florian Huber</author></item><item><title>turning a panda into a cat!</title><link>https://blog2.esciencecenter.nl/posts/2019-06-20---turning-a-panda-into-a-cat</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-06-20---turning-a-panda-into-a-cat</guid><description>&lt;h2 id=&quot;why-adversarial-examples-are-not-scarybut-are-most-likely-useful&quot;&gt;Why adversarial examples are not scary…but are most likely useful&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1867&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xr8cAurNp61q6Vfe-7789a74b.BJNIeX3Y_ZRVwAc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Is it a bird? Is it a plane?” A child who never saw Superman might mistake him for a bird or a plane. On the other hand, who knows what a time traveler from the ’70s would see in this picture. Photo by 贝莉儿 NG on Unsplash&lt;/p&gt;
&lt;p&gt;If you’ve had anything to do with deep learning recently, you’ve heard of them: &lt;em&gt;adversarial examples&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The nightmare of deep neural networks. Every skeptic’s favorite example.&lt;/p&gt;
&lt;p&gt;Adversarial examples are one way of showing the limitations of neural networks when someone asks “is this how human vision works”?.&lt;/p&gt;
&lt;p&gt;In a nutshell, it is possible to change a few carefully chosen pixels in a picture of a panda, such that a network that was trained to distinguish pandas from cats will classify the &lt;em&gt;picture&lt;/em&gt; of the panda as a &lt;em&gt;picture&lt;/em&gt; of a cat. (Pandas are so cute, therefore they are used [a lot]( in the data science world.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1594&quot; height=&quot;686&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_l0s5ZoLgVp2tIIMr-d558db4b.BUvat9Vv_Z1kJg0b.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this example, the panda is confused for a gibbon, but cats are cuter than gibbons, so I use cats in the text&lt;/p&gt;
&lt;p&gt;Now, note how I emphasized the word &lt;em&gt;picture&lt;/em&gt; above. Why? Because &lt;em&gt;that&lt;/em&gt; is what we give to the network as input: a picture, a matrix of pixels.&lt;/p&gt;
&lt;p&gt;It learns &lt;em&gt;patterns&lt;/em&gt; that appear frequently in the matrices of pixels (i.e. pictures) that represent a panda. A &lt;em&gt;combination&lt;/em&gt; of patterns represents a category, like pandas (well, actually a &lt;em&gt;hierarchical&lt;/em&gt; &lt;em&gt;nonlinear&lt;/em&gt; combination of patterns, but those are details).&lt;/p&gt;
&lt;p&gt;If none of the pictures of pandas used for training contained ‘weird’ pixels, the network will not learn that pictures may come with weird pixels. (Just think of all the funny mistakes that your children were making when learning various things at age 3… well, funny to &lt;em&gt;you&lt;/em&gt;, not to them!)&lt;/p&gt;
&lt;p&gt;That said, if at prediction time you give a picture with weird pixels, the network might give &lt;em&gt;anything&lt;/em&gt; for an answer — because it has to give one. And if you have two categories and you chose the pixels to alter carefully (it is very easy actually), voila — it will predict that your panda is a cat.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_eyLwwz_4InVWo3Of-30eeda49.C6ZRlpaq_Z1CuJAJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“I better watch the road and not those weird pixels” - a well-trained biker. Photo by Nikita Ignatev on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Truth is in the eye of the beholder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Wait a minute. We asked the network if it saw a picture of a panda, not an actual panda. Did the network say it was an actual picture of a panda? No. Correct answer. Why? Because we did not give it an &lt;em&gt;actual&lt;/em&gt; picture of a panda. It was a &lt;em&gt;digitally manipulated&lt;/em&gt; picture. Fake. A human will &lt;em&gt;not&lt;/em&gt; recognize that that was not an actual picture of a panda. But the network said “No” and in a sign of a protest it answered “ A cat!”. (The last is a joke, obviously.)&lt;/p&gt;
&lt;p&gt;So, garbage in, garbage out.&lt;/p&gt;
&lt;p&gt;Why is this not scary? Actually, why do people think it is scary? Supposedly, in computer vision, one might use carefully digitally manipulated image to fool the network. True. But if you are using computer vision (thus automated) instead of human vision, and if I am a hacker, then I can fool you in much easier ways. If I want to use your smartphone that uses facial recognition to unlock itself, I don’t have to digitally alter an image of me so that the network thinks it is you. I will show the network an actual image of you.&lt;/p&gt;
&lt;p&gt;Ok. But what about the changed &lt;em&gt;reality&lt;/em&gt; rather than changed pictures? Namely, another favorite example is the altered stop sign at a crossroad that might trick a self-driving car into going straight and crashing, while a human driver would still recognize the sign.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2488&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_EZweu8W1Iv2CyL4f-8a057f5e.CcUttdbs_2g7Q1p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A ‘stop’ sign for a human driver, a ‘go ahead’ sign for a self-driving car. Photo by Luke van Zyl on Unsplash&lt;/p&gt;
&lt;p&gt;It is actually not difficult to realize that a vandal who wants to crash a self-driving car (?!) can do it in a much easier way, than by carefully spraying the stop sign using deep learning. &lt;a href=&quot;https://medium.com/@catherio/unsolved-research-problems-vs-real-world-threat-models-e270e256bc9e&quot;&gt;Here&lt;/a&gt; is a post that elaborates on this.&lt;/p&gt;
&lt;p&gt;So, we saw that everyone’s favorite security examples are not really a threat.&lt;/p&gt;
&lt;p&gt;Why are adversarial examples useful? Because they improve the knowledge that we have on deep learning. By being aware of its current limitations, researchers can make the neural networks even ‘smarter’ and maybe one day they will actually imitate human vision if that’s what we aim for.&lt;/p&gt;
&lt;p&gt;Until that day, I am so eager to hear of a &lt;em&gt;real&lt;/em&gt; threat that adversarial examples might pose.&lt;/p&gt;
&lt;p&gt;(Bonus: &lt;a href=&quot;https://www.ted.com/talks/donald_hoffman_do_we_see_reality_as_it_is?language=en#t-1108775&quot;&gt;Do &lt;strong&gt;we&lt;/strong&gt; see reality as it is?&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Florian Huber, Berend Weel, Felipe Zapata, Kim Holthaus, Johan Rheeder, Patrick Bos, and Zvezdan Protic for the useful suggestions.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 20 Jun 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;why-adversarial-examples-are-not-scarybut-are-most-likely-useful&quot;&gt;Why adversarial examples are not scary…but are most likely useful&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1867&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_xr8cAurNp61q6Vfe-7789a74b.BJNIeX3Y_ZRVwAc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Is it a bird? Is it a plane?” A child who never saw Superman might mistake him for a bird or a plane. On the other hand, who knows what a time traveler from the ’70s would see in this picture. Photo by 贝莉儿 NG on Unsplash&lt;/p&gt;
&lt;p&gt;If you’ve had anything to do with deep learning recently, you’ve heard of them: &lt;em&gt;adversarial examples&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The nightmare of deep neural networks. Every skeptic’s favorite example.&lt;/p&gt;
&lt;p&gt;Adversarial examples are one way of showing the limitations of neural networks when someone asks “is this how human vision works”?.&lt;/p&gt;
&lt;p&gt;In a nutshell, it is possible to change a few carefully chosen pixels in a picture of a panda, such that a network that was trained to distinguish pandas from cats will classify the &lt;em&gt;picture&lt;/em&gt; of the panda as a &lt;em&gt;picture&lt;/em&gt; of a cat. (Pandas are so cute, therefore they are used [a lot]( in the data science world.)&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1594&quot; height=&quot;686&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_l0s5ZoLgVp2tIIMr-d558db4b.BUvat9Vv_Z1kJg0b.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this example, the panda is confused for a gibbon, but cats are cuter than gibbons, so I use cats in the text&lt;/p&gt;
&lt;p&gt;Now, note how I emphasized the word &lt;em&gt;picture&lt;/em&gt; above. Why? Because &lt;em&gt;that&lt;/em&gt; is what we give to the network as input: a picture, a matrix of pixels.&lt;/p&gt;
&lt;p&gt;It learns &lt;em&gt;patterns&lt;/em&gt; that appear frequently in the matrices of pixels (i.e. pictures) that represent a panda. A &lt;em&gt;combination&lt;/em&gt; of patterns represents a category, like pandas (well, actually a &lt;em&gt;hierarchical&lt;/em&gt; &lt;em&gt;nonlinear&lt;/em&gt; combination of patterns, but those are details).&lt;/p&gt;
&lt;p&gt;If none of the pictures of pandas used for training contained ‘weird’ pixels, the network will not learn that pictures may come with weird pixels. (Just think of all the funny mistakes that your children were making when learning various things at age 3… well, funny to &lt;em&gt;you&lt;/em&gt;, not to them!)&lt;/p&gt;
&lt;p&gt;That said, if at prediction time you give a picture with weird pixels, the network might give &lt;em&gt;anything&lt;/em&gt; for an answer — because it has to give one. And if you have two categories and you chose the pixels to alter carefully (it is very easy actually), voila — it will predict that your panda is a cat.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_eyLwwz_4InVWo3Of-30eeda49.C6ZRlpaq_Z1CuJAJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“I better watch the road and not those weird pixels” - a well-trained biker. Photo by Nikita Ignatev on Unsplash&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Truth is in the eye of the beholder&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Wait a minute. We asked the network if it saw a picture of a panda, not an actual panda. Did the network say it was an actual picture of a panda? No. Correct answer. Why? Because we did not give it an &lt;em&gt;actual&lt;/em&gt; picture of a panda. It was a &lt;em&gt;digitally manipulated&lt;/em&gt; picture. Fake. A human will &lt;em&gt;not&lt;/em&gt; recognize that that was not an actual picture of a panda. But the network said “No” and in a sign of a protest it answered “ A cat!”. (The last is a joke, obviously.)&lt;/p&gt;
&lt;p&gt;So, garbage in, garbage out.&lt;/p&gt;
&lt;p&gt;Why is this not scary? Actually, why do people think it is scary? Supposedly, in computer vision, one might use carefully digitally manipulated image to fool the network. True. But if you are using computer vision (thus automated) instead of human vision, and if I am a hacker, then I can fool you in much easier ways. If I want to use your smartphone that uses facial recognition to unlock itself, I don’t have to digitally alter an image of me so that the network thinks it is you. I will show the network an actual image of you.&lt;/p&gt;
&lt;p&gt;Ok. But what about the changed &lt;em&gt;reality&lt;/em&gt; rather than changed pictures? Namely, another favorite example is the altered stop sign at a crossroad that might trick a self-driving car into going straight and crashing, while a human driver would still recognize the sign.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2488&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_EZweu8W1Iv2CyL4f-8a057f5e.CcUttdbs_2g7Q1p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A ‘stop’ sign for a human driver, a ‘go ahead’ sign for a self-driving car. Photo by Luke van Zyl on Unsplash&lt;/p&gt;
&lt;p&gt;It is actually not difficult to realize that a vandal who wants to crash a self-driving car (?!) can do it in a much easier way, than by carefully spraying the stop sign using deep learning. &lt;a href=&quot;https://medium.com/@catherio/unsolved-research-problems-vs-real-world-threat-models-e270e256bc9e&quot;&gt;Here&lt;/a&gt; is a post that elaborates on this.&lt;/p&gt;
&lt;p&gt;So, we saw that everyone’s favorite security examples are not really a threat.&lt;/p&gt;
&lt;p&gt;Why are adversarial examples useful? Because they improve the knowledge that we have on deep learning. By being aware of its current limitations, researchers can make the neural networks even ‘smarter’ and maybe one day they will actually imitate human vision if that’s what we aim for.&lt;/p&gt;
&lt;p&gt;Until that day, I am so eager to hear of a &lt;em&gt;real&lt;/em&gt; threat that adversarial examples might pose.&lt;/p&gt;
&lt;p&gt;(Bonus: &lt;a href=&quot;https://www.ted.com/talks/donald_hoffman_do_we_see_reality_as_it_is?language=en#t-1108775&quot;&gt;Do &lt;strong&gt;we&lt;/strong&gt; see reality as it is?&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Florian Huber, Berend Weel, Felipe Zapata, Kim Holthaus, Johan Rheeder, Patrick Bos, and Zvezdan Protic for the useful suggestions.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_l0s5ZoLgVp2tIIMr-d558db4b.BUvat9Vv.webp" medium="image"/><author>Sonja Georgievska</author></item><item><title>big questions — small data.</title><link>https://blog2.esciencecenter.nl/posts/2019-06-14---big-questions-small-data</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-06-14---big-questions-small-data</guid><description>&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; our mission is to &lt;strong&gt;“digitally enhance science”&lt;/strong&gt;.&lt;br&gt;
How to do this other than by the biggest tech-superpowers of our time:&lt;br&gt;
super-computing, big-data, and of course: deep learning!&lt;br&gt;
But are these technologies suitable or even necessary for every scientific problem?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1750&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_kuv6purwbawIwU37-22aa1350.CnbCuf6__Z1z03FN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Actual scientific research is often a lot less shiny. Actually, we also tend to work with smaller touch screens… Photo by Josh Hild on Unsplash&lt;/p&gt;
&lt;p&gt;Our world, our universe, we ourselves are incredibly complex systems.&lt;br&gt;
And as no surprise this also means that the way we try to understand all of this is incredibly complex as well. And research technologies, paradigms, and philosophies are as diverse as one can imagine.&lt;/p&gt;
&lt;p&gt;In this post I want to argue that it is all about finding or developing the &lt;strong&gt;right techniques for the right problem&lt;/strong&gt;. For some that could indeed be buzzword-superpowers. But for most people in scientific research it is probably something less buzz-wordy…&lt;/p&gt;
&lt;h2 id=&quot;hey-researcher-how-much-data-have-you-got&quot;&gt;Hey Researcher! How much data have you got?&lt;/h2&gt;
&lt;p&gt;Seems like it’s all about &lt;em&gt;&lt;strong&gt;big data&lt;/strong&gt;&lt;/em&gt; nowadays… well not exactly.&lt;br&gt;
I’m coming from a physics and life-science background. More importantly, I spent a big part of my own research being an experimentalist. That means you start forming a hypothesis, think of an experiment to test it, and then you spend some months, some years, or even some decades on doing those experiments.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Rq9Nd5b7Em4_sCoB-c783816e.DsCkK2D5_Z1F9gvF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A modern library is a good metaphor. For some tasks you want to train a very deep neural network on all books in it (e.g. to gain deeper insides such as that a king that is female would be a queen, a very famous but misleading example from the field of natural language processing ). For other research questions it will be about finding the ONE right book that contains the answer (a specific biographical note, a mathematical proof, a previously overlooked footnote …). Photo by Sara Kurfeß on Unsplash&lt;/p&gt;
&lt;p&gt;And there is quite a number of research fields where people work on experiments that are very hard to carry out AND that produce very little data. One datapoint at a time. I will always remember what a former colleague of mine said when she quit after her first year of postdoc:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It took me one year to get one datapoint! I think I don’t need to spend another year to get a second one.” (anonymous postdoc)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you might guess, she left science and was indeed fairly frustrated by how little data she got. It’s important to note that she was very skilled, so it wasn’t her ‘fault’ that she collected the data so slowly. She was simply unlucky to work on an experiment that turned out to be a combination of difficult steps glued together. This meant that getting &lt;em&gt;&lt;strong&gt;one&lt;/strong&gt;&lt;/em&gt; successful experimental run, where everything worked out fine, was simply very unlikely.&lt;/p&gt;
&lt;p&gt;What type (and amount) of data you need strongly depends on the research question and hypothesis that you want to address. To prove that not all swans are white, you only need one black swan. If you want to prove that birds shit onto your car more often than onto the car of your neighbor, you need to have proper statistics. And that means: many more datapoints!&lt;/p&gt;
&lt;p&gt;Now speaking for life sciences only, the spectrum of possible scenarios is huge. For some types of experiments you can be happy if you gather &lt;strong&gt;5 or 10&lt;/strong&gt; datapoints. For others you can hope to run &lt;strong&gt;10s or 100s&lt;/strong&gt; of similar experiments (and hence also learn about the intrinsic randomness and noise of the data). Think of typical medical studies with 10s or 100s of patients or animals. &lt;strong&gt;Not exactly BIG data!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But sure, there are also cases where life science questions are tackled with much larger amounts of data. Large genetics studies, population wide screenings, automated, or semi-automated types of experiments.&lt;/p&gt;
&lt;h2 id=&quot;big-small-tiny-and-what-about-complex&quot;&gt;Big? Small? Tiny? And what about complex?&lt;/h2&gt;
&lt;p&gt;With the over-use of the term ‘big data’ it seems as if everything would be about whether your data is too small, or big enough. In reality, things are a lot more complicated. Not only do people not agree on how big is really BIG. There is also much more depth to the problem. Data can be more or less noisy, more or less ‘rich’, more or less ‘complex’.&lt;/p&gt;
&lt;p&gt;You can have the age, name, and location of millions of people. That would maybe be big data, but not very complex. Or you could have high-resolution MRI scans from 20 patients, which would maybe not be considered big in the number of datapoints (every patient is one), but each collected sample is very complex and potentially contains a lot information (another way to classify big data are the &lt;a href=&quot;https://www.ibmbigdatahub.com/infographic/four-vs-big-data&quot;&gt;Four V’s&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;how-to-make-most-of-your-data&quot;&gt;How to make most of your data?&lt;/h2&gt;
&lt;p&gt;In the tech world with the ongoing rise of deep learning techniques, it seems there is only one proper answer. DO DEEP LEARNING.&lt;/p&gt;
&lt;p&gt;If you live in the machine-learning tutorial world you could even get the impression that people will laugh at you if you turn towards ‘old school’ machine-learning techniques. Deep learning is smarter, better, faster, and of course: much fancier and cooler!&lt;/p&gt;
&lt;p&gt;To make things simple: Deep learning can be the ultimate super power if you have a clearly defined question and near-to-unlimited data. It works like a charm for the google-type of things in the world. And &lt;strong&gt;IT CAN&lt;/strong&gt; also work for smaller datasets as well. But in those cases it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Will not always work!&lt;/li&gt;
&lt;li&gt;Will quite often not be the best solution.&lt;/li&gt;
&lt;li&gt;Will need much more custom-tailoring.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In industry (and increasingly in the academic world as well) there is currently a strong tendency to dump ‘old-fashioned’ machine-learning and statistical tools to move on to deep learning models. Their main advantage is that they are very strong in finding the right way to treat complex data ‘themselves’. That means, we as researchers do not have to add complex rules, models, or hypotheses onto the input data. Seems great. But it really won’t work for many scientific use cases. If it is about rare events, or smaller datasets, or more complex types of questions (say, more complex than a simple classification task), deep learning models often perform very poorly.&lt;/p&gt;
&lt;p&gt;And, surprise!&lt;br&gt;
In many such cases, very boring old-school methods like more traditional machine-learning techniques (support vector machines, random forests etc.) or even more old-fashioned: classical statistical tools, can do a much better job.&lt;/p&gt;
&lt;p&gt;I am not trying to argue that there is no use for deep learning in academic research. There is, plenty even. But it is not the ultimate weapon. I’m sure it will do an unbelievable job for some cases (and an OK job for some others). But researchers need to be well-aware of its possibilities and limitations to use it for the right data, and the right research questions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;853&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_D2uZDKsjjb_kaqPX_x_zJw-1d63c8f5.Bl3gaBER_HuWkz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Many examples from archeology illustrate nicely that it is often about extracting as much as possible from one or few samples. While modern machine-learning tools will have potential use for some of the tasks involved, it is clearly not feasible to simply run current cutting-edge NLP models on a few fragments of ancient writings. Depicted here: Oxyrhynchus papyrus (P.Oxy. I 29) showing fragment of Euclid’s Elements. See wikipedia.&lt;/p&gt;
&lt;h2 id=&quot;final-note-make-tiny-data-count&quot;&gt;Final note: Make tiny data count.&lt;/h2&gt;
&lt;p&gt;The ideal industry use-case: plenty of data, plenty of compute power, simple classification task… is very far from most current and future scientific problems of interest. For research it will be key to put more effort into developing statistically sound models that can do great things, with little data.&lt;/p&gt;
&lt;p&gt;Often this means custom-tailoring different techniques to fit the respective research question and available data. In most cases researchers will have very little use for the newest, cutting-edge 100-layer deep neural network architecture. They won’t have enough data to train it. And researchers have other needs than industry use cases. They will be happy to sacrifice a few percentage points in model accuracy for the gain of a much simpler and more intuitive algorithm or model architecture (see [blog post on explainability]( So, typically simplicity beats benchmarking.&lt;/p&gt;
&lt;p&gt;Instead of simply reusing the latest benchmark winning networks, successful application of machine-learning and deep learning in research projects is more like this: Take a simpler, but still a little bit fancy-looking deep learning model for a sub-task, combine it with some ‘old-school’ machine-learning tools (say support vector machines or Bayesian network), and in the end use some good old basic statistics stuff from the 19th century.&lt;/p&gt;
&lt;p&gt;Maybe a little less shiny and fancy, but that is often how we can make best use of &lt;strong&gt;tiny data to be able to answer big questions&lt;/strong&gt;.&lt;/p&gt;</description><pubDate>Fri, 14 Jun 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; our mission is to &lt;strong&gt;“digitally enhance science”&lt;/strong&gt;.&lt;br&gt;
How to do this other than by the biggest tech-superpowers of our time:&lt;br&gt;
super-computing, big-data, and of course: deep learning!&lt;br&gt;
But are these technologies suitable or even necessary for every scientific problem?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1750&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_kuv6purwbawIwU37-22aa1350.CnbCuf6__Z1z03FN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Actual scientific research is often a lot less shiny. Actually, we also tend to work with smaller touch screens… Photo by Josh Hild on Unsplash&lt;/p&gt;
&lt;p&gt;Our world, our universe, we ourselves are incredibly complex systems.&lt;br&gt;
And as no surprise this also means that the way we try to understand all of this is incredibly complex as well. And research technologies, paradigms, and philosophies are as diverse as one can imagine.&lt;/p&gt;
&lt;p&gt;In this post I want to argue that it is all about finding or developing the &lt;strong&gt;right techniques for the right problem&lt;/strong&gt;. For some that could indeed be buzzword-superpowers. But for most people in scientific research it is probably something less buzz-wordy…&lt;/p&gt;
&lt;h2 id=&quot;hey-researcher-how-much-data-have-you-got&quot;&gt;Hey Researcher! How much data have you got?&lt;/h2&gt;
&lt;p&gt;Seems like it’s all about &lt;em&gt;&lt;strong&gt;big data&lt;/strong&gt;&lt;/em&gt; nowadays… well not exactly.&lt;br&gt;
I’m coming from a physics and life-science background. More importantly, I spent a big part of my own research being an experimentalist. That means you start forming a hypothesis, think of an experiment to test it, and then you spend some months, some years, or even some decades on doing those experiments.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Rq9Nd5b7Em4_sCoB-c783816e.DsCkK2D5_Z1F9gvF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A modern library is a good metaphor. For some tasks you want to train a very deep neural network on all books in it (e.g. to gain deeper insides such as that a king that is female would be a queen, a very famous but misleading example from the field of natural language processing ). For other research questions it will be about finding the ONE right book that contains the answer (a specific biographical note, a mathematical proof, a previously overlooked footnote …). Photo by Sara Kurfeß on Unsplash&lt;/p&gt;
&lt;p&gt;And there is quite a number of research fields where people work on experiments that are very hard to carry out AND that produce very little data. One datapoint at a time. I will always remember what a former colleague of mine said when she quit after her first year of postdoc:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It took me one year to get one datapoint! I think I don’t need to spend another year to get a second one.” (anonymous postdoc)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you might guess, she left science and was indeed fairly frustrated by how little data she got. It’s important to note that she was very skilled, so it wasn’t her ‘fault’ that she collected the data so slowly. She was simply unlucky to work on an experiment that turned out to be a combination of difficult steps glued together. This meant that getting &lt;em&gt;&lt;strong&gt;one&lt;/strong&gt;&lt;/em&gt; successful experimental run, where everything worked out fine, was simply very unlikely.&lt;/p&gt;
&lt;p&gt;What type (and amount) of data you need strongly depends on the research question and hypothesis that you want to address. To prove that not all swans are white, you only need one black swan. If you want to prove that birds shit onto your car more often than onto the car of your neighbor, you need to have proper statistics. And that means: many more datapoints!&lt;/p&gt;
&lt;p&gt;Now speaking for life sciences only, the spectrum of possible scenarios is huge. For some types of experiments you can be happy if you gather &lt;strong&gt;5 or 10&lt;/strong&gt; datapoints. For others you can hope to run &lt;strong&gt;10s or 100s&lt;/strong&gt; of similar experiments (and hence also learn about the intrinsic randomness and noise of the data). Think of typical medical studies with 10s or 100s of patients or animals. &lt;strong&gt;Not exactly BIG data!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But sure, there are also cases where life science questions are tackled with much larger amounts of data. Large genetics studies, population wide screenings, automated, or semi-automated types of experiments.&lt;/p&gt;
&lt;h2 id=&quot;big-small-tiny-and-what-about-complex&quot;&gt;Big? Small? Tiny? And what about complex?&lt;/h2&gt;
&lt;p&gt;With the over-use of the term ‘big data’ it seems as if everything would be about whether your data is too small, or big enough. In reality, things are a lot more complicated. Not only do people not agree on how big is really BIG. There is also much more depth to the problem. Data can be more or less noisy, more or less ‘rich’, more or less ‘complex’.&lt;/p&gt;
&lt;p&gt;You can have the age, name, and location of millions of people. That would maybe be big data, but not very complex. Or you could have high-resolution MRI scans from 20 patients, which would maybe not be considered big in the number of datapoints (every patient is one), but each collected sample is very complex and potentially contains a lot information (another way to classify big data are the &lt;a href=&quot;https://www.ibmbigdatahub.com/infographic/four-vs-big-data&quot;&gt;Four V’s&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;how-to-make-most-of-your-data&quot;&gt;How to make most of your data?&lt;/h2&gt;
&lt;p&gt;In the tech world with the ongoing rise of deep learning techniques, it seems there is only one proper answer. DO DEEP LEARNING.&lt;/p&gt;
&lt;p&gt;If you live in the machine-learning tutorial world you could even get the impression that people will laugh at you if you turn towards ‘old school’ machine-learning techniques. Deep learning is smarter, better, faster, and of course: much fancier and cooler!&lt;/p&gt;
&lt;p&gt;To make things simple: Deep learning can be the ultimate super power if you have a clearly defined question and near-to-unlimited data. It works like a charm for the google-type of things in the world. And &lt;strong&gt;IT CAN&lt;/strong&gt; also work for smaller datasets as well. But in those cases it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Will not always work!&lt;/li&gt;
&lt;li&gt;Will quite often not be the best solution.&lt;/li&gt;
&lt;li&gt;Will need much more custom-tailoring.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In industry (and increasingly in the academic world as well) there is currently a strong tendency to dump ‘old-fashioned’ machine-learning and statistical tools to move on to deep learning models. Their main advantage is that they are very strong in finding the right way to treat complex data ‘themselves’. That means, we as researchers do not have to add complex rules, models, or hypotheses onto the input data. Seems great. But it really won’t work for many scientific use cases. If it is about rare events, or smaller datasets, or more complex types of questions (say, more complex than a simple classification task), deep learning models often perform very poorly.&lt;/p&gt;
&lt;p&gt;And, surprise!&lt;br&gt;
In many such cases, very boring old-school methods like more traditional machine-learning techniques (support vector machines, random forests etc.) or even more old-fashioned: classical statistical tools, can do a much better job.&lt;/p&gt;
&lt;p&gt;I am not trying to argue that there is no use for deep learning in academic research. There is, plenty even. But it is not the ultimate weapon. I’m sure it will do an unbelievable job for some cases (and an OK job for some others). But researchers need to be well-aware of its possibilities and limitations to use it for the right data, and the right research questions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;853&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_D2uZDKsjjb_kaqPX_x_zJw-1d63c8f5.Bl3gaBER_HuWkz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Many examples from archeology illustrate nicely that it is often about extracting as much as possible from one or few samples. While modern machine-learning tools will have potential use for some of the tasks involved, it is clearly not feasible to simply run current cutting-edge NLP models on a few fragments of ancient writings. Depicted here: Oxyrhynchus papyrus (P.Oxy. I 29) showing fragment of Euclid’s Elements. See wikipedia.&lt;/p&gt;
&lt;h2 id=&quot;final-note-make-tiny-data-count&quot;&gt;Final note: Make tiny data count.&lt;/h2&gt;
&lt;p&gt;The ideal industry use-case: plenty of data, plenty of compute power, simple classification task… is very far from most current and future scientific problems of interest. For research it will be key to put more effort into developing statistically sound models that can do great things, with little data.&lt;/p&gt;
&lt;p&gt;Often this means custom-tailoring different techniques to fit the respective research question and available data. In most cases researchers will have very little use for the newest, cutting-edge 100-layer deep neural network architecture. They won’t have enough data to train it. And researchers have other needs than industry use cases. They will be happy to sacrifice a few percentage points in model accuracy for the gain of a much simpler and more intuitive algorithm or model architecture (see [blog post on explainability]( So, typically simplicity beats benchmarking.&lt;/p&gt;
&lt;p&gt;Instead of simply reusing the latest benchmark winning networks, successful application of machine-learning and deep learning in research projects is more like this: Take a simpler, but still a little bit fancy-looking deep learning model for a sub-task, combine it with some ‘old-school’ machine-learning tools (say support vector machines or Bayesian network), and in the end use some good old basic statistics stuff from the 19th century.&lt;/p&gt;
&lt;p&gt;Maybe a little less shiny and fancy, but that is often how we can make best use of &lt;strong&gt;tiny data to be able to answer big questions&lt;/strong&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_kuv6purwbawIwU37-22aa1350.CnbCuf6_.webp" medium="image"/><author>Florian Huber</author></item><item><title>explainable ai exit or infinite loop</title><link>https://blog2.esciencecenter.nl/posts/2019-06-12---explainable-ai-exit-or-infinite-loop</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-06-12---explainable-ai-exit-or-infinite-loop</guid><description>&lt;blockquote&gt;
&lt;p&gt;Let us simplify before we try to explain&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;958&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_SJOGsixtTuXLuT7p-0bbdb076.D4Mrq2WB_1ATH4s.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Franck V. on Unsplash&lt;/p&gt;
&lt;p&gt;Before we start, let’s make it clear: by AI here I mean computational statistics, and by explainable — well, I don’t really know what I mean by that. This is because of a lack of a standard definition, just like there is no definition of (human) intelligence on which everyone agrees.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The black box that gives the magic numbers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wgh71PgpNMU7tonx-d189acd0.EzAetqYZ_ZbFND3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Farhan Siddicq on Unsplash&lt;/p&gt;
&lt;p&gt;Explainable AI as a concept is as &lt;a href=&quot;https://en.wikipedia.org/wiki/Explainable_artificial_intelligence&quot;&gt;old&lt;/a&gt; as the field of AI. However, only recently it gained a lot of interest from researchers. The interest, of course, came due to the enormous boom that the technology called deep learning (DL) has made in public life. But also due to the way DL works. Namely, in the past, machine learning practitioners used to craft intuitively explainable features that represented the problem and the data. However, nowadays, it seems that all one needs is a lot of data, a GPU computing cluster, and time, for the deep neural network to come up with the magical numbers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Magic makes you feel out of control&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;930&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Mbz9uhZnei5ol2lm-6d9b045e.nTG4fwKQ_Z2hQTF5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by FuYong Hua on Unsplash&lt;/p&gt;
&lt;p&gt;This is where the frustrations start for those that need to implement a trained network into practice. They are puzzled about how this technology solves the problem. Will they have any control over it when the conditions or the data change &lt;a href=&quot;https://openai.com/blog/adversarial-example-research/&quot;&gt;slightly&lt;/a&gt;, will the performances stay the same? Will they have to deal with &lt;a href=&quot;https://en.wikipedia.org/wiki/Right_to_explanation&quot;&gt;lawsuits&lt;/a&gt; because the network made ridiculous mistakes in critical decisions?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We need to be able to explain how it works&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Clearly, there is a lot of demand for explainable AI, no matter what exactly it is. Any ray of light in the complete darkness is better than no light at all. This arguably sparkled a whole new field called explainable AI. Which is good: with so much research going on, something useful must come out of it…. Right?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Taking the high-speed train, but in which direction?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;935&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_dZCufW48zn80OKDf-d7ad172e.B7yatR6B_1dr5Q6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Free To Use Sounds on Unsplash&lt;/p&gt;
&lt;p&gt;So, we try to craft models that explain how DL techniques work. But are we heading in the right direction? Aren’t things actually happening too fast? Namely, DL is taking precedence in practice so fast, that there was even no time so far &lt;a href=&quot;https://sites.google.com/site/deeplearningtheory/&quot;&gt;to develop a theoretical framework&lt;/a&gt; that captures its power and limitations. Nevertheless, we want it already to explain itself?!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Once upon a time, there used to be &lt;em&gt;Occam’s razor&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“All other things being equal, the simplest solution is the best” — a simple explanation of Occam’s razor&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I studied computer science a while ago, but I believe that the main principles in designing a model/algorithm are still valid today: make your models simple and avoid too many parameters in your models. Something like Occam’s razor.&lt;/p&gt;
&lt;p&gt;Translated to the DL world, this would mean: do not use more complex networks than you actually need for your problem. Otherwise, you are in the wild, and slight changes in the data distribution can lead to a ‘disaster’. Or, if not, then at least, the ‘explanation’ is lost in the abundance of &lt;a href=&quot;https://arxiv.org/abs/1803.03635&quot;&gt;redundant&lt;/a&gt; parameters.&lt;/p&gt;
&lt;p&gt;However, at this moment rarely we consider optimizing the models. There is a simple reason: DL networks are so successful at solving particular problems, black box or not, that almost all attention of the research community goes into the front end, that is, application (and explainability therein).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Without law, there is no crime&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In this situation, when we try to explain AI, we might be fixing cracks while making new ones. Namely, at the moment we have to rely on heuristics for explaining the DL results.&lt;/p&gt;
&lt;p&gt;This means that eventually, we will need to define metrics to be able to compare the different heuristics, or &lt;em&gt;explainability models&lt;/em&gt;, that have been proposed. &lt;a href=&quot;https://en.wikipedia.org/wiki/No_free_lunch_theorem&quot;&gt;As it is usually the case&lt;/a&gt;, for every particular problem and dataset, and for every metric, a different model will outperform the rest. Then one will have to choose between different explainability models for her problem/data at hand. Then she will be asked to explain how she chose that particular model, “how can we trust it”? Then we will need to develop models that ‘explain’ the explainability models. And there we go forever and ever in an infinite loop…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ctrl+Alt+Del&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(OK, I am exaggerating here;), but please bear with me, I am just trying to make a point … Did I make it, by the way?)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Acknowledgments&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Carlos Martinez Ortiz, Janneke van der Zwaan, Maarten van Meersbergen&lt;/em&gt;**,** &lt;em&gt;Florian Huber, Patrick Bos, Tom Bakker, and Zvezdan Protic for proof-reading and for the useful comments.&lt;/em&gt;&lt;/p&gt;</description><pubDate>Wed, 12 Jun 2019 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Let us simplify before we try to explain&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;958&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_SJOGsixtTuXLuT7p-0bbdb076.D4Mrq2WB_1ATH4s.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Franck V. on Unsplash&lt;/p&gt;
&lt;p&gt;Before we start, let’s make it clear: by AI here I mean computational statistics, and by explainable — well, I don’t really know what I mean by that. This is because of a lack of a standard definition, just like there is no definition of (human) intelligence on which everyone agrees.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The black box that gives the magic numbers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wgh71PgpNMU7tonx-d189acd0.EzAetqYZ_ZbFND3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Farhan Siddicq on Unsplash&lt;/p&gt;
&lt;p&gt;Explainable AI as a concept is as &lt;a href=&quot;https://en.wikipedia.org/wiki/Explainable_artificial_intelligence&quot;&gt;old&lt;/a&gt; as the field of AI. However, only recently it gained a lot of interest from researchers. The interest, of course, came due to the enormous boom that the technology called deep learning (DL) has made in public life. But also due to the way DL works. Namely, in the past, machine learning practitioners used to craft intuitively explainable features that represented the problem and the data. However, nowadays, it seems that all one needs is a lot of data, a GPU computing cluster, and time, for the deep neural network to come up with the magical numbers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Magic makes you feel out of control&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;930&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Mbz9uhZnei5ol2lm-6d9b045e.nTG4fwKQ_Z2hQTF5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by FuYong Hua on Unsplash&lt;/p&gt;
&lt;p&gt;This is where the frustrations start for those that need to implement a trained network into practice. They are puzzled about how this technology solves the problem. Will they have any control over it when the conditions or the data change &lt;a href=&quot;https://openai.com/blog/adversarial-example-research/&quot;&gt;slightly&lt;/a&gt;, will the performances stay the same? Will they have to deal with &lt;a href=&quot;https://en.wikipedia.org/wiki/Right_to_explanation&quot;&gt;lawsuits&lt;/a&gt; because the network made ridiculous mistakes in critical decisions?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We need to be able to explain how it works&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Clearly, there is a lot of demand for explainable AI, no matter what exactly it is. Any ray of light in the complete darkness is better than no light at all. This arguably sparkled a whole new field called explainable AI. Which is good: with so much research going on, something useful must come out of it…. Right?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Taking the high-speed train, but in which direction?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;935&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_dZCufW48zn80OKDf-d7ad172e.B7yatR6B_1dr5Q6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Free To Use Sounds on Unsplash&lt;/p&gt;
&lt;p&gt;So, we try to craft models that explain how DL techniques work. But are we heading in the right direction? Aren’t things actually happening too fast? Namely, DL is taking precedence in practice so fast, that there was even no time so far &lt;a href=&quot;https://sites.google.com/site/deeplearningtheory/&quot;&gt;to develop a theoretical framework&lt;/a&gt; that captures its power and limitations. Nevertheless, we want it already to explain itself?!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Once upon a time, there used to be &lt;em&gt;Occam’s razor&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“All other things being equal, the simplest solution is the best” — a simple explanation of Occam’s razor&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I studied computer science a while ago, but I believe that the main principles in designing a model/algorithm are still valid today: make your models simple and avoid too many parameters in your models. Something like Occam’s razor.&lt;/p&gt;
&lt;p&gt;Translated to the DL world, this would mean: do not use more complex networks than you actually need for your problem. Otherwise, you are in the wild, and slight changes in the data distribution can lead to a ‘disaster’. Or, if not, then at least, the ‘explanation’ is lost in the abundance of &lt;a href=&quot;https://arxiv.org/abs/1803.03635&quot;&gt;redundant&lt;/a&gt; parameters.&lt;/p&gt;
&lt;p&gt;However, at this moment rarely we consider optimizing the models. There is a simple reason: DL networks are so successful at solving particular problems, black box or not, that almost all attention of the research community goes into the front end, that is, application (and explainability therein).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Without law, there is no crime&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In this situation, when we try to explain AI, we might be fixing cracks while making new ones. Namely, at the moment we have to rely on heuristics for explaining the DL results.&lt;/p&gt;
&lt;p&gt;This means that eventually, we will need to define metrics to be able to compare the different heuristics, or &lt;em&gt;explainability models&lt;/em&gt;, that have been proposed. &lt;a href=&quot;https://en.wikipedia.org/wiki/No_free_lunch_theorem&quot;&gt;As it is usually the case&lt;/a&gt;, for every particular problem and dataset, and for every metric, a different model will outperform the rest. Then one will have to choose between different explainability models for her problem/data at hand. Then she will be asked to explain how she chose that particular model, “how can we trust it”? Then we will need to develop models that ‘explain’ the explainability models. And there we go forever and ever in an infinite loop…&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ctrl+Alt+Del&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(OK, I am exaggerating here;), but please bear with me, I am just trying to make a point … Did I make it, by the way?)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Acknowledgments&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Carlos Martinez Ortiz, Janneke van der Zwaan, Maarten van Meersbergen&lt;/em&gt;**,** &lt;em&gt;Florian Huber, Patrick Bos, Tom Bakker, and Zvezdan Protic for proof-reading and for the useful comments.&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_wgh71PgpNMU7tonx-d189acd0.EzAetqYZ.webp" medium="image"/><author>Sonja Georgievska</author></item><item><title>breaking the barrier fluid simulations parallel-in-time.</title><link>https://blog2.esciencecenter.nl/posts/2019-06-03---breaking-the-barrier-fluid-simulations-parallel-in-time</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-06-03---breaking-the-barrier-fluid-simulations-parallel-in-time</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_kgHps8C6sIPJ87U5-21014e83.Cf2esTW4_Z1sLsff.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Parallel flows — Photo by Sergey Pesterev on Unsplash&lt;/p&gt;
&lt;p&gt;These days computers are growing faster only by adding more cores and increasing parallelism of the programs. As an example, suppose we are computing the turbulent flow around an airfoil. This is a problem that is very intensive to compute so we’d want to parallelise it.&lt;/p&gt;
&lt;h3 id=&quot;parallel-in-space-and-scaling-of-overhead&quot;&gt;Parallel-in-space, and scaling of overhead&lt;/h3&gt;
&lt;p&gt;The traditional approach is to divide the volume of our simulation into different domains, and give each domain to a different processor. After each time-step the changes in each domain need to be communicated between the processors. This adds overhead to the computation. Each time we split the volumes in half we can potentially double the speed in which we get our answer, but this is mitigated by the fact that we also increase the amount of communication needed between the compute nodes.&lt;/p&gt;
&lt;p&gt;This principle of balancing processing power versus communication overhead is a universal one. There always seems to be a barrier to how many processors we can use for solving a problem. The question is then, &lt;em&gt;how can we break this barrier&lt;/em&gt;, how can we parallelise our computation even further? This is the point where we go parallel-in-time.&lt;/p&gt;
&lt;h3 id=&quot;parallel-in-time-but-how&quot;&gt;Parallel-in-time, but how?&lt;/h3&gt;
&lt;p&gt;At first the notion of parallel-in-time integration often is counter intuitive. The problem of simulation a fluid (and many other computations like it) is inherently sequential. &lt;strong&gt;The change in a state of a physical system always depends on the current state of the system.&lt;/strong&gt; How then, do we compute the future in parallel with the past?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Ex_5x8X3ahx9H8tr-93129325.BK4ZxPDR_Z1FXd11.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One state follows the other — Photo by Kumiko SHIMIZU on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;parareal&quot;&gt;Parareal&lt;/h2&gt;
&lt;p&gt;A simple method that, in theory, gives decent speed-ups is &lt;a href=&quot;https://en.wikipedia.org/wiki/Parareal&quot;&gt;Parareal&lt;/a&gt;. It was invented in 2001 by &lt;a href=&quot;https://doi.org/10.1016%2FS0764-4442%2800%2901793-6&quot;&gt;Lions, Maday &amp;#x26; Turinici&lt;/a&gt;. The introduction of Parareal was largely what got the current surge in parallel-in-time methods started, since it is the first algorithm that showed enough promise to give a real speed up. Also, it is relatively simple to explain.&lt;/p&gt;
&lt;h3 id=&quot;coarse--fine&quot;&gt;Coarse &amp;#x26; Fine&lt;/h3&gt;
&lt;p&gt;Parareal works by defining a c &lt;em&gt;oarse&lt;/em&gt; and a &lt;em&gt;fine&lt;/em&gt; algorithm. The coarse algorithm should be cheap to compute, possibly a low order integration, on a coarse grid, possibly also with reduced model complexity and with a large time-step. The &lt;em&gt;fine&lt;/em&gt; integrator on the other hand, is the expensive algorithm often computed on a finer grid, with all necessary physics included.&lt;/p&gt;
&lt;p&gt;The first step of Parareal is to get an initial guess for the evolution of the system by taking the result of just the coarse integrator. We use this initial guess to start the fine integrator at each time-step simultaneously. Since we already have an initial guess for each time-step (on the coarse grid), we can perform the fine integration in parallel.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_MIbMvMtZ8iDrIh39-41b44295.BTaAkWhy_1V4HUO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Coarse building with fine grid — Photo by Lance Anderson on Unsplash&lt;/p&gt;
&lt;p&gt;At the end of this step each of the fine integrators will be slightly off, because they started from a wrong first estimate. We can try to correct the results of the fine integrators. Several iterations of fine integration followed by correction will be needed.&lt;/p&gt;
&lt;p&gt;The quality of the Parareal algorithm depends heavily on the accuracy of the coarse integrator.&lt;/p&gt;
&lt;p&gt;We only get a speed-up if the algorithm converges in fewer iterations than our number of time-steps. Also note that while we get our answer faster, we need to do a lot more work to get it.&lt;/p&gt;
&lt;h3 id=&quot;the-bay-of-fundy&quot;&gt;The Bay of Fundy&lt;/h3&gt;
&lt;p&gt;An example of a successful application of Parareal in hydrodynamics was presented by &lt;a href=&quot;http://doi.org/10.1016/j.jocs.2016.12.006&quot;&gt;Eghbal, Gerber &amp;#x26; Aubanel (2016) [doi:10.1016/j.jocs.2016.12.006]&lt;/a&gt;. They implemented Parareal on top of an existing (proprietary, sad enough) GPU hydro code with the aim of modelling hydro turbine tidal power generation in the Bay of Fundy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;674&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CTqna61llKW59pGAbDslWg-6cd020ac.Du_6NsKj_ZgGXgR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(left) Simulation of tidal flow in Bay of Fundy (right) Gantt chart of Parareal, the number in each box signifies the time-step that is worked on. Processor 0 performs the coarse integration and orchestrates the other processors. (from Eghbal et al 2016)&lt;/p&gt;
&lt;p&gt;The Gantt chart on the right shows the work being done by 10 processors. Eghbal et al. divided the work in multiple time ‘windows’, two of which are shown here. In each window we see that Parareal converged in 5 iterations. To save data transfer in the correction step, each processor works on successive time-steps. This way only the data of the coarse integrator has to be propagated between processors.&lt;/p&gt;
&lt;h3 id=&quot;difficulties&quot;&gt;Difficulties&lt;/h3&gt;
&lt;p&gt;One area where Parareal is reported to go wrong is with oscillating systems. The coarse integrator usually gives a result that is out-of-phase with the real solution. Attempts have been made to do phase-correction on top of Parareal, but this is still very much a topic of research.&lt;/p&gt;
&lt;h3 id=&quot;beyond-parareal&quot;&gt;Beyond Parareal&lt;/h3&gt;
&lt;p&gt;There are many more methods for parallel-in-time integration. One example is &lt;em&gt;Multigrid Reduction in Time&lt;/em&gt; or MGRIT. MGRIT can be seen as a generalisation of Parareal. It has more flexibility in the ways to correct the results from the fine integrator, and can be used in conjunction with multi-grid method in space. An implementation of MGRIT is available in the XBraid package.&lt;/p&gt;
&lt;h2 id=&quot;fair-warning&quot;&gt;Fair warning&lt;/h2&gt;
&lt;p&gt;There are reports of significant speed-ups with parallel-in-time methods but this comes with a warning. There is a big investment into tuning the system. A lot of work goes into making current parallel-in-time methods perform faster than sequential methods. In the case of Parareal, this means finding a good model for the coarse integration.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_G1X_X13MDVRAqNAz-5afe64df.CLAr7JmW_2mMiAq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Effects of overheating — Photo by Bjørn Tore Økland on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;stay-green&quot;&gt;Stay green&lt;/h3&gt;
&lt;p&gt;To recap, our question was: How do we compute past and future in parallel? The answer: by wasting a lot of computational power. In these days of ecological responsibility and green computing, wasting valuable processor cycles seems like a bad idea. Even if you succeed in getting a speed-up, you still need to convince your local super computing facility why you need all this.&lt;/p&gt;
&lt;p&gt;We may find however, that in some cases there is no other way forward. As the number of cores on a machine keep increasing, we need to be more creative in utilizing the computational power we’re given.&lt;/p&gt;
&lt;h3 id=&quot;further-reading&quot;&gt;Further reading&lt;/h3&gt;
&lt;p&gt;The field of parallel-in-time methods is still young. At &lt;a href=&quot;http://www.parallel-in-time.org/&quot;&gt;&lt;em&gt;http://www.parallel-in-time.org&lt;/em&gt;&lt;/a&gt; there is a collection of scientific papers and computer codes. A good review on available methods is &lt;a href=&quot;https://www.youtube.com/watch?v=dn5vqN8ezuE&quot;&gt;“50 years of parallel-in-time” by Martin Gander&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Mon, 03 Jun 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_kgHps8C6sIPJ87U5-21014e83.Cf2esTW4_Z1sLsff.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Parallel flows — Photo by Sergey Pesterev on Unsplash&lt;/p&gt;
&lt;p&gt;These days computers are growing faster only by adding more cores and increasing parallelism of the programs. As an example, suppose we are computing the turbulent flow around an airfoil. This is a problem that is very intensive to compute so we’d want to parallelise it.&lt;/p&gt;
&lt;h3 id=&quot;parallel-in-space-and-scaling-of-overhead&quot;&gt;Parallel-in-space, and scaling of overhead&lt;/h3&gt;
&lt;p&gt;The traditional approach is to divide the volume of our simulation into different domains, and give each domain to a different processor. After each time-step the changes in each domain need to be communicated between the processors. This adds overhead to the computation. Each time we split the volumes in half we can potentially double the speed in which we get our answer, but this is mitigated by the fact that we also increase the amount of communication needed between the compute nodes.&lt;/p&gt;
&lt;p&gt;This principle of balancing processing power versus communication overhead is a universal one. There always seems to be a barrier to how many processors we can use for solving a problem. The question is then, &lt;em&gt;how can we break this barrier&lt;/em&gt;, how can we parallelise our computation even further? This is the point where we go parallel-in-time.&lt;/p&gt;
&lt;h3 id=&quot;parallel-in-time-but-how&quot;&gt;Parallel-in-time, but how?&lt;/h3&gt;
&lt;p&gt;At first the notion of parallel-in-time integration often is counter intuitive. The problem of simulation a fluid (and many other computations like it) is inherently sequential. &lt;strong&gt;The change in a state of a physical system always depends on the current state of the system.&lt;/strong&gt; How then, do we compute the future in parallel with the past?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Ex_5x8X3ahx9H8tr-93129325.BK4ZxPDR_Z1FXd11.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;One state follows the other — Photo by Kumiko SHIMIZU on Unsplash&lt;/p&gt;
&lt;h2 id=&quot;parareal&quot;&gt;Parareal&lt;/h2&gt;
&lt;p&gt;A simple method that, in theory, gives decent speed-ups is &lt;a href=&quot;https://en.wikipedia.org/wiki/Parareal&quot;&gt;Parareal&lt;/a&gt;. It was invented in 2001 by &lt;a href=&quot;https://doi.org/10.1016%2FS0764-4442%2800%2901793-6&quot;&gt;Lions, Maday &amp;#x26; Turinici&lt;/a&gt;. The introduction of Parareal was largely what got the current surge in parallel-in-time methods started, since it is the first algorithm that showed enough promise to give a real speed up. Also, it is relatively simple to explain.&lt;/p&gt;
&lt;h3 id=&quot;coarse--fine&quot;&gt;Coarse &amp;#x26; Fine&lt;/h3&gt;
&lt;p&gt;Parareal works by defining a c &lt;em&gt;oarse&lt;/em&gt; and a &lt;em&gt;fine&lt;/em&gt; algorithm. The coarse algorithm should be cheap to compute, possibly a low order integration, on a coarse grid, possibly also with reduced model complexity and with a large time-step. The &lt;em&gt;fine&lt;/em&gt; integrator on the other hand, is the expensive algorithm often computed on a finer grid, with all necessary physics included.&lt;/p&gt;
&lt;p&gt;The first step of Parareal is to get an initial guess for the evolution of the system by taking the result of just the coarse integrator. We use this initial guess to start the fine integrator at each time-step simultaneously. Since we already have an initial guess for each time-step (on the coarse grid), we can perform the fine integration in parallel.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_MIbMvMtZ8iDrIh39-41b44295.BTaAkWhy_1V4HUO.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Coarse building with fine grid — Photo by Lance Anderson on Unsplash&lt;/p&gt;
&lt;p&gt;At the end of this step each of the fine integrators will be slightly off, because they started from a wrong first estimate. We can try to correct the results of the fine integrators. Several iterations of fine integration followed by correction will be needed.&lt;/p&gt;
&lt;p&gt;The quality of the Parareal algorithm depends heavily on the accuracy of the coarse integrator.&lt;/p&gt;
&lt;p&gt;We only get a speed-up if the algorithm converges in fewer iterations than our number of time-steps. Also note that while we get our answer faster, we need to do a lot more work to get it.&lt;/p&gt;
&lt;h3 id=&quot;the-bay-of-fundy&quot;&gt;The Bay of Fundy&lt;/h3&gt;
&lt;p&gt;An example of a successful application of Parareal in hydrodynamics was presented by &lt;a href=&quot;http://doi.org/10.1016/j.jocs.2016.12.006&quot;&gt;Eghbal, Gerber &amp;#x26; Aubanel (2016) [doi:10.1016/j.jocs.2016.12.006]&lt;/a&gt;. They implemented Parareal on top of an existing (proprietary, sad enough) GPU hydro code with the aim of modelling hydro turbine tidal power generation in the Bay of Fundy.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;674&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CTqna61llKW59pGAbDslWg-6cd020ac.Du_6NsKj_ZgGXgR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;(left) Simulation of tidal flow in Bay of Fundy (right) Gantt chart of Parareal, the number in each box signifies the time-step that is worked on. Processor 0 performs the coarse integration and orchestrates the other processors. (from Eghbal et al 2016)&lt;/p&gt;
&lt;p&gt;The Gantt chart on the right shows the work being done by 10 processors. Eghbal et al. divided the work in multiple time ‘windows’, two of which are shown here. In each window we see that Parareal converged in 5 iterations. To save data transfer in the correction step, each processor works on successive time-steps. This way only the data of the coarse integrator has to be propagated between processors.&lt;/p&gt;
&lt;h3 id=&quot;difficulties&quot;&gt;Difficulties&lt;/h3&gt;
&lt;p&gt;One area where Parareal is reported to go wrong is with oscillating systems. The coarse integrator usually gives a result that is out-of-phase with the real solution. Attempts have been made to do phase-correction on top of Parareal, but this is still very much a topic of research.&lt;/p&gt;
&lt;h3 id=&quot;beyond-parareal&quot;&gt;Beyond Parareal&lt;/h3&gt;
&lt;p&gt;There are many more methods for parallel-in-time integration. One example is &lt;em&gt;Multigrid Reduction in Time&lt;/em&gt; or MGRIT. MGRIT can be seen as a generalisation of Parareal. It has more flexibility in the ways to correct the results from the fine integrator, and can be used in conjunction with multi-grid method in space. An implementation of MGRIT is available in the XBraid package.&lt;/p&gt;
&lt;h2 id=&quot;fair-warning&quot;&gt;Fair warning&lt;/h2&gt;
&lt;p&gt;There are reports of significant speed-ups with parallel-in-time methods but this comes with a warning. There is a big investment into tuning the system. A lot of work goes into making current parallel-in-time methods perform faster than sequential methods. In the case of Parareal, this means finding a good model for the coarse integration.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_G1X_X13MDVRAqNAz-5afe64df.CLAr7JmW_2mMiAq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Effects of overheating — Photo by Bjørn Tore Økland on Unsplash&lt;/p&gt;
&lt;h3 id=&quot;stay-green&quot;&gt;Stay green&lt;/h3&gt;
&lt;p&gt;To recap, our question was: How do we compute past and future in parallel? The answer: by wasting a lot of computational power. In these days of ecological responsibility and green computing, wasting valuable processor cycles seems like a bad idea. Even if you succeed in getting a speed-up, you still need to convince your local super computing facility why you need all this.&lt;/p&gt;
&lt;p&gt;We may find however, that in some cases there is no other way forward. As the number of cores on a machine keep increasing, we need to be more creative in utilizing the computational power we’re given.&lt;/p&gt;
&lt;h3 id=&quot;further-reading&quot;&gt;Further reading&lt;/h3&gt;
&lt;p&gt;The field of parallel-in-time methods is still young. At &lt;a href=&quot;http://www.parallel-in-time.org/&quot;&gt;&lt;em&gt;http://www.parallel-in-time.org&lt;/em&gt;&lt;/a&gt; there is a collection of scientific papers and computer codes. A good review on available methods is &lt;a href=&quot;https://www.youtube.com/watch?v=dn5vqN8ezuE&quot;&gt;“50 years of parallel-in-time” by Martin Gander&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_Ex_5x8X3ahx9H8tr-93129325.BK4ZxPDR.webp" medium="image"/><author>Johan Hidding</author></item><item><title>some thoughts about developing software for scientific applications</title><link>https://blog2.esciencecenter.nl/posts/2019-05-29---some-thoughts-about-developing-software-for-scientific-applications</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-05-29---some-thoughts-about-developing-software-for-scientific-applications</guid><description>&lt;blockquote&gt;
&lt;p&gt;…The children would remember for the rest of their lives the august solemnity with which their father, devastated by his prolonged vigil and by the wraith of his imagination, revealed his discovery to them:&lt;/p&gt;
&lt;p&gt;-‘The world is round, like an orange.’&lt;/p&gt;
&lt;p&gt;― &lt;strong&gt;Gabriel Garcí­a Márquez, One Hundred Years of Solitude&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_stxtWjVMWisEjKv8-b9b5049c.CGBdkv-8_1xlI93.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Benjamin Davies on Unsplash&lt;/p&gt;
&lt;p&gt;Recently, I have been reading a wonderful book called: &lt;a href=&quot;https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow&quot;&gt;&lt;em&gt;Thinking, fast and slow&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt; In that book, David Kahneman brilliantly guides us through the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dual_process_theory&quot;&gt;two system model&lt;/a&gt; representing the thought process: a fast system in charge of the automatic behavior and a slow one taking analytical decisions. Mr. Kahneman insistently warns us, in his very clever humor, about the lazy slow system and the biased decision-making of the fast system. In this post I will borrow these ideas to share my experience about designing and implementing scientific software.&lt;/p&gt;
&lt;p&gt;Also, in contrast to my [previous blog]( post in which I briefly introduced some guidelines to deal with legacy code, in this one I would like to embark with you on a new journey to the promised land full of nothingness where we can start (almost) from scratch!&lt;/p&gt;
&lt;h3 id=&quot;the-world-is-round-like-an-orange&quot;&gt;The world is round, like an orange!&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“Our comforting conviction that the world makes sense rests on a secure foundation: our almost unlimited ability to ignore our ignorance.”&lt;br&gt;
― Daniel Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;932&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_82ZMt6M1u2kNP0Lf-2869ab36.cObdflL4_Z1ll0Sy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NASA on Unsplash&lt;/p&gt;
&lt;p&gt;Lets start from the beginning: planet earth. One given day on earth, &lt;em&gt;José Arcadio Buendía&lt;/em&gt;, one of the main characters of o &lt;a href=&quot;https://en.wikipedia.org/wiki/One_Hundred_Years_of_Solitude&quot;&gt;ne hundred years of solitude&lt;/a&gt;, discovered after many months of effort and pain that the earth is round! Which is great, apart from the fact that the Greeks knew it a couple of millennia before.&lt;/p&gt;
&lt;p&gt;Scientific software developing is full of &lt;em&gt;José&lt;/em&gt; Arcadios, they wake up early on the morning and spend febrile days playing with mathematical model in the shape of quick and dirty script that are going to be hopefully clean and polish on the future. Of course, as the famous software engineer &lt;a href=&quot;https://blog.cleancoder.com/&quot;&gt;Robert Martin&lt;/a&gt; brilliantly explains in his &lt;a href=&quot;https://www.pearson.com/us/higher-education/program/Martin-Clean-Code-A-Handbook-of-Agile-Software-Craftsmanship/PGM63937.html&quot;&gt;clean code book&lt;/a&gt;, the code never gets clean and it becomes yet another spaghetti monster.&lt;/p&gt;
&lt;p&gt;So, what can you do to create flexible and functional software for scientific applications? There are many great books about software architecture like &lt;a href=&quot;https://learning.oreilly.com/library/view/clean-architecture-a/9780134494272/&quot;&gt;clean architecture&lt;/a&gt; and &lt;a href=&quot;https://www.oreilly.com/library/view/the-pragmatic-programmer/020161622X/&quot;&gt;the pragmatic programmer&lt;/a&gt;. However, when developing software for scientific applications, we usually do not have a set of well defined specifications, instead we just have hunches and vague ideas of what may or may not work.&lt;/p&gt;
&lt;p&gt;Since we lack a concrete plan, our mind continuously plays tricks on us, making us to believe that we possess both unlimited time and resources. Professional software architects are quite conscious about this &lt;a href=&quot;https://en.wikipedia.org/wiki/Planning_fallacy&quot;&gt;planning fallacy&lt;/a&gt; and have years of experience and painful mistakes to remind them about those biases. But scientific software is usually the toil of a &lt;a href=&quot;https://arxiv.org/abs/1904.09954&quot;&gt;single or few heroes&lt;/a&gt; who work day and night to create software, crunch data and analyze results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The question is then how can we make a concrete plan for implementing half-proven ideas&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What I have found is that the unknowns of the projects can be treated as black boxes that can be encapsulated in a flexible framework. This framework, allows to replace one black box by another with an small amount of effort.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this blog I would like to introduce a simple guideline about best practices for designing scientific software, without entering in any religious battles about whether &lt;a href=&quot;https://en.wikipedia.org/wiki/Agile_software_development&quot;&gt;Agile&lt;/a&gt; methodologies like &lt;a href=&quot;https://en.wikipedia.org/wiki/Scrum_(software_development)&quot;&gt;Scrum&lt;/a&gt; are suitable for scientific software development.&lt;/p&gt;
&lt;h3 id=&quot;make-a-clear-plan-and-discuss-it-with-others&quot;&gt;Make a clear plan and discuss it with others&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“many people are overconfident, prone to place too much faith in their intuitions.”&lt;/p&gt;
&lt;p&gt;― Daniel Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A whiteboard or a piece of paper is a great place to start designing software. Discuss over a cup of coffee with your colleagues what is the functionality that you are expecting from the software. Make a scheme representing the functionality as boxes and the relation between the functions as edges, do not enter on the details of the algorithms for the moment being. Then ask yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are the components of you design orthogonal? This means that you can replace one component by another without having to change all the other components.&lt;/li&gt;
&lt;li&gt;Is there some information that is duplicate or can be derived from a higher abstraction level?
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_vh8bBvgToPFAyBLk-b840d649.DOgE6tM2_1kEKCo.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Photo by Kaleidico on Unsplash&lt;/p&gt;
&lt;p&gt;Once you have a draft about the functionality and its dependencies, look up for the parts of the system that are independent from the current unknowns of the project. Those independent parts constitute the backbone of your framework and should be flexible enough to allow to plugin other components.&lt;/p&gt;
&lt;p&gt;The development of a modular and flexible software may seem costly, but the invested time will be amortized on the future when you would need to replace a part of the system without having to restart from scratch. And believe me, that is always going to happen!&lt;/p&gt;
&lt;p&gt;If the previous design rings a bell, have a look at the &lt;a href=&quot;https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch03.html&quot;&gt;microkernel architecture&lt;/a&gt;!&lt;/p&gt;
&lt;h3 id=&quot;test-driven-development&quot;&gt;Test Driven Development&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“We are prone to overestimate how much we understand about the world and to underestimate the role of chance in events.”&lt;/p&gt;
&lt;p&gt;―David Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_G2kcC7G4TFHygK9s-679679d1.DSsvtmDW_2rnSvu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by SpaceX on Unsplash&lt;/p&gt;
&lt;p&gt;You may think that since you are navigating uncharted seas, you need to play with the models before testing the code. But, if your goal is to prove an hypothesis based on some data or algorithm, should you not been testing the code that represents the hypothesis since the beginning?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;Test Driven Development&lt;/a&gt; is completely ignored or at best frown upon in scientific software development, but the nature of this software development methodology is deeply rooted on the scientific method. You need to first identity the properties that your system should have and then you progressively build your system around a set of tests that check for the expected functionality.&lt;/p&gt;
&lt;h3 id=&quot;avoid-social-embarrassment-use-the-standard-libraries&quot;&gt;Avoid social embarrassment: use the standard libraries&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“true experts know the limits of their knowledge”&lt;/p&gt;
&lt;p&gt;―David Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Duplication and re-implementation of well known algorithms should be avoided, correctness is more important than performance. Remember that the main goals of a scientific library is first reproducibility and then performance. A flexible, well-tested and well-documented library can always be improved in the future.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;https://en.wikiquote.org/wiki/Donald_Knuth&quot;&gt;Donald Knuth&lt;/a&gt; famously said: “Premature optimization is the root of all evil”. You first goal should be a functional and well tested library, once you have something that works as expected, you can start profiling and optimizing.&lt;/p&gt;
&lt;h3 id=&quot;finally&quot;&gt;Finally&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1051&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wbN9foCe_njdkMbr-24583a61.Co8bTKgK_1k8R0I.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Aaron Burden on Unsplash&lt;/p&gt;
&lt;p&gt;There is no single recipe that covers all the technical problems for a given scientific application, but identifying the software requirements and the known-unknowns will help you to create a crude chart to navigate the sea of monsters and uncertainties on a scientific software development voyage.&lt;/p&gt;</description><pubDate>Wed, 29 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;…The children would remember for the rest of their lives the august solemnity with which their father, devastated by his prolonged vigil and by the wraith of his imagination, revealed his discovery to them:&lt;/p&gt;
&lt;p&gt;-‘The world is round, like an orange.’&lt;/p&gt;
&lt;p&gt;― &lt;strong&gt;Gabriel Garcí­a Márquez, One Hundred Years of Solitude&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_stxtWjVMWisEjKv8-b9b5049c.CGBdkv-8_1xlI93.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Benjamin Davies on Unsplash&lt;/p&gt;
&lt;p&gt;Recently, I have been reading a wonderful book called: &lt;a href=&quot;https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow&quot;&gt;&lt;em&gt;Thinking, fast and slow&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt; In that book, David Kahneman brilliantly guides us through the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dual_process_theory&quot;&gt;two system model&lt;/a&gt; representing the thought process: a fast system in charge of the automatic behavior and a slow one taking analytical decisions. Mr. Kahneman insistently warns us, in his very clever humor, about the lazy slow system and the biased decision-making of the fast system. In this post I will borrow these ideas to share my experience about designing and implementing scientific software.&lt;/p&gt;
&lt;p&gt;Also, in contrast to my [previous blog]( post in which I briefly introduced some guidelines to deal with legacy code, in this one I would like to embark with you on a new journey to the promised land full of nothingness where we can start (almost) from scratch!&lt;/p&gt;
&lt;h3 id=&quot;the-world-is-round-like-an-orange&quot;&gt;The world is round, like an orange!&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“Our comforting conviction that the world makes sense rests on a secure foundation: our almost unlimited ability to ignore our ignorance.”&lt;br&gt;
― Daniel Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;932&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_82ZMt6M1u2kNP0Lf-2869ab36.cObdflL4_Z1ll0Sy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by NASA on Unsplash&lt;/p&gt;
&lt;p&gt;Lets start from the beginning: planet earth. One given day on earth, &lt;em&gt;José Arcadio Buendía&lt;/em&gt;, one of the main characters of o &lt;a href=&quot;https://en.wikipedia.org/wiki/One_Hundred_Years_of_Solitude&quot;&gt;ne hundred years of solitude&lt;/a&gt;, discovered after many months of effort and pain that the earth is round! Which is great, apart from the fact that the Greeks knew it a couple of millennia before.&lt;/p&gt;
&lt;p&gt;Scientific software developing is full of &lt;em&gt;José&lt;/em&gt; Arcadios, they wake up early on the morning and spend febrile days playing with mathematical model in the shape of quick and dirty script that are going to be hopefully clean and polish on the future. Of course, as the famous software engineer &lt;a href=&quot;https://blog.cleancoder.com/&quot;&gt;Robert Martin&lt;/a&gt; brilliantly explains in his &lt;a href=&quot;https://www.pearson.com/us/higher-education/program/Martin-Clean-Code-A-Handbook-of-Agile-Software-Craftsmanship/PGM63937.html&quot;&gt;clean code book&lt;/a&gt;, the code never gets clean and it becomes yet another spaghetti monster.&lt;/p&gt;
&lt;p&gt;So, what can you do to create flexible and functional software for scientific applications? There are many great books about software architecture like &lt;a href=&quot;https://learning.oreilly.com/library/view/clean-architecture-a/9780134494272/&quot;&gt;clean architecture&lt;/a&gt; and &lt;a href=&quot;https://www.oreilly.com/library/view/the-pragmatic-programmer/020161622X/&quot;&gt;the pragmatic programmer&lt;/a&gt;. However, when developing software for scientific applications, we usually do not have a set of well defined specifications, instead we just have hunches and vague ideas of what may or may not work.&lt;/p&gt;
&lt;p&gt;Since we lack a concrete plan, our mind continuously plays tricks on us, making us to believe that we possess both unlimited time and resources. Professional software architects are quite conscious about this &lt;a href=&quot;https://en.wikipedia.org/wiki/Planning_fallacy&quot;&gt;planning fallacy&lt;/a&gt; and have years of experience and painful mistakes to remind them about those biases. But scientific software is usually the toil of a &lt;a href=&quot;https://arxiv.org/abs/1904.09954&quot;&gt;single or few heroes&lt;/a&gt; who work day and night to create software, crunch data and analyze results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The question is then how can we make a concrete plan for implementing half-proven ideas&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What I have found is that the unknowns of the projects can be treated as black boxes that can be encapsulated in a flexible framework. This framework, allows to replace one black box by another with an small amount of effort.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this blog I would like to introduce a simple guideline about best practices for designing scientific software, without entering in any religious battles about whether &lt;a href=&quot;https://en.wikipedia.org/wiki/Agile_software_development&quot;&gt;Agile&lt;/a&gt; methodologies like &lt;a href=&quot;https://en.wikipedia.org/wiki/Scrum_(software_development)&quot;&gt;Scrum&lt;/a&gt; are suitable for scientific software development.&lt;/p&gt;
&lt;h3 id=&quot;make-a-clear-plan-and-discuss-it-with-others&quot;&gt;Make a clear plan and discuss it with others&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“many people are overconfident, prone to place too much faith in their intuitions.”&lt;/p&gt;
&lt;p&gt;― Daniel Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A whiteboard or a piece of paper is a great place to start designing software. Discuss over a cup of coffee with your colleagues what is the functionality that you are expecting from the software. Make a scheme representing the functionality as boxes and the relation between the functions as edges, do not enter on the details of the algorithms for the moment being. Then ask yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Are the components of you design orthogonal? This means that you can replace one component by another without having to change all the other components.&lt;/li&gt;
&lt;li&gt;Is there some information that is duplicate or can be derived from a higher abstraction level?
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_vh8bBvgToPFAyBLk-b840d649.DOgE6tM2_1kEKCo.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Photo by Kaleidico on Unsplash&lt;/p&gt;
&lt;p&gt;Once you have a draft about the functionality and its dependencies, look up for the parts of the system that are independent from the current unknowns of the project. Those independent parts constitute the backbone of your framework and should be flexible enough to allow to plugin other components.&lt;/p&gt;
&lt;p&gt;The development of a modular and flexible software may seem costly, but the invested time will be amortized on the future when you would need to replace a part of the system without having to restart from scratch. And believe me, that is always going to happen!&lt;/p&gt;
&lt;p&gt;If the previous design rings a bell, have a look at the &lt;a href=&quot;https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch03.html&quot;&gt;microkernel architecture&lt;/a&gt;!&lt;/p&gt;
&lt;h3 id=&quot;test-driven-development&quot;&gt;Test Driven Development&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“We are prone to overestimate how much we understand about the world and to underestimate the role of chance in events.”&lt;/p&gt;
&lt;p&gt;―David Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_G2kcC7G4TFHygK9s-679679d1.DSsvtmDW_2rnSvu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by SpaceX on Unsplash&lt;/p&gt;
&lt;p&gt;You may think that since you are navigating uncharted seas, you need to play with the models before testing the code. But, if your goal is to prove an hypothesis based on some data or algorithm, should you not been testing the code that represents the hypothesis since the beginning?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;Test Driven Development&lt;/a&gt; is completely ignored or at best frown upon in scientific software development, but the nature of this software development methodology is deeply rooted on the scientific method. You need to first identity the properties that your system should have and then you progressively build your system around a set of tests that check for the expected functionality.&lt;/p&gt;
&lt;h3 id=&quot;avoid-social-embarrassment-use-the-standard-libraries&quot;&gt;Avoid social embarrassment: use the standard libraries&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;“true experts know the limits of their knowledge”&lt;/p&gt;
&lt;p&gt;―David Kahneman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Duplication and re-implementation of well known algorithms should be avoided, correctness is more important than performance. Remember that the main goals of a scientific library is first reproducibility and then performance. A flexible, well-tested and well-documented library can always be improved in the future.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;https://en.wikiquote.org/wiki/Donald_Knuth&quot;&gt;Donald Knuth&lt;/a&gt; famously said: “Premature optimization is the root of all evil”. You first goal should be a functional and well tested library, once you have something that works as expected, you can start profiling and optimizing.&lt;/p&gt;
&lt;h3 id=&quot;finally&quot;&gt;Finally&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1051&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_wbN9foCe_njdkMbr-24583a61.Co8bTKgK_1k8R0I.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Aaron Burden on Unsplash&lt;/p&gt;
&lt;p&gt;There is no single recipe that covers all the technical problems for a given scientific application, but identifying the software requirements and the known-unknowns will help you to create a crude chart to navigate the sea of monsters and uncertainties on a scientific software development voyage.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_stxtWjVMWisEjKv8-b9b5049c.CGBdkv-8.webp" medium="image"/><author>Felipe</author></item><item><title>democracy</title><link>https://blog2.esciencecenter.nl/posts/2019-05-23---democracy</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-05-23---democracy</guid><description>&lt;p&gt;Dimensional reduction. Who doesn’t love it? Everybody does!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1920&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fCDDMFJQUb5CmCVtxJTyTA-0a6bac2b.0u4fr91r_khJPT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;On that note: EU election week! Time to map our complex individual preferences to one of a few packages of lumped together stances.&lt;/p&gt;
&lt;p&gt;Luckily, with the advent of political matching tool websites, this is as easy as answering a couple of questions on a one dimensional scale. The algorithm then takes care of the optimal mapping, you can cross the right box on the ballot and get on with your life, knowing you’ve been a good citizen and all will be well!&lt;/p&gt;
&lt;p&gt;As much as I love &lt;strong&gt;one&lt;/strong&gt; dimensional reduction, though, I have an odd preference for the &lt;strong&gt;two&lt;/strong&gt; dimensional reduction that Kieskompas (Election Compass) has offered for years now in the Netherlands. Yesterday morning, I took the test.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1354&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sUjONvjaoc0BOrwcCZ0FsA-a86da711.CFC1hIRV_1nhqpE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The balls are the major parties (we got a lot of ’em in the Netherlands), the marker is me. Links = left, rechts = right, progressive, conservative, you get the idea.&lt;/p&gt;
&lt;p&gt;Arrgh, right in the middle of the black hole of despair!&lt;/p&gt;
&lt;p&gt;I’m definitely not going to vote for 50 Plus, the (seemingly) one-issue pensionado party. All the other parties are miles away, so what good is this advice? How could it even be that 50 Plus is so close to me? Is there some kind of weird averaging going on? Are my (or 50 Plus’) answers canceling each other out in such a way that we just happen to end up in the exact same place, even though we’re diametrically opposed on every issue, &lt;strong&gt;which I must assume we are&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;470&quot; height=&quot;325&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7XNAxB-fd2MWHvLfJI7UgA-8f642e21.COPPam7m_Z1HrGYs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The only logical explanation.&lt;/p&gt;
&lt;p&gt;Spoiler alert: it turns out this party actually isn’t such a bad fit for me.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;280&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_2rhyo9zsDj2InUlP-9d354cdd.9D6KzaR2_abugu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;80s meme, suck on that, millennials!&lt;/p&gt;
&lt;p&gt;But I sure as hell wasn’t going to accept that without a fight. I was sure something was wrong with the algorithms. I was going to get to the bottom of this and find out a way to get me a better match. &lt;em&gt;Get me my data sciencing tools!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;859&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GSOpTB1VmBy97pN6gJFxzw-941987fc.M2K1DPwf_ZTxLgP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Me, sciencing them datas! This must have been something like a couple years ago… wait, 2006…?!&lt;/p&gt;
&lt;h2 id=&quot;data-gathering&quot;&gt;Data gathering&lt;/h2&gt;
&lt;p&gt;The Kieskompas contains 30 questions that can be answered on a 5 point scale: “strongly agree” (2), “agree” (1), “neutral” (0), “disagree” (-1) and “strongly disagree” (-2). You can also skip questions. The answers are clustered into 7 topics, but I won’t use that here.&lt;/p&gt;
&lt;p&gt;So there’s two basic pieces of data I need here: my answers and those from the parties.&lt;/p&gt;
&lt;h3 id=&quot;my-own-answers&quot;&gt;My own answers&lt;/h3&gt;
&lt;p&gt;I already filled out all the questions on the website, so the data should be around somewhere in my browser cache. Using Firefox’s development console, I was able to find it in the storage section (Shift-F9) under Local Storage.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;380&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7myn_EenujQiN-KOfts2VA-83ed0a83.DIa--LER_ZJlPRg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;There’s my data.&lt;/p&gt;
&lt;p&gt;This JSON data can be easily copy-pasted into a Jupyter notebook, where I was going to Python-fu this thing into submission. Using an advanced JSON to Python conversion technique (first cell below) and some Pandas magic, we end up with a neat dataframe:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;594&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GLgsmbdbYG87Vrfyqk6Erg-7cf0427c.GuSL3zPB_Z1zdtTC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The important column is &lt;code&gt;answer.value&lt;/code&gt;, which I can compare to the answers given by the political parties.&lt;/p&gt;
&lt;h3 id=&quot;party-answers-enter-ipysheet&quot;&gt;Party answers: enter ipysheet&lt;/h3&gt;
&lt;p&gt;That party answer data, however, was not as readily scrapeable. Possibly, there is some copyright involved there as well (which is also the reason I’m not sharing all this stuff publicly), which forced them to hide the data a bit. Possibly, I’m just not looking in the right places. Whatever the case, I couldn’t find it.&lt;/p&gt;
&lt;p&gt;Luckily, the website offers a page to compare all your answers to all the parties’ answers, so we can just manually copy all 30 of them for all 12 available parties!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;659&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_M0WgX7PajLewKek0CkD0Cg-b2c16c42.BpFEDTHk_2vwYFE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That’s only 360 numbers.&lt;/p&gt;
&lt;p&gt;“Manually copy?!” I hear you object. Normally, I would agree with you, even if it’s just 360 numbers, manual labor goes against everything I stand for as a lazy programmer (or rather: sit for), but I was getting desparate for data and I had hit a wall. Also, this gave me a good excuse to try out &lt;strong&gt;ipysheet&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;The ipysheet Jupyter widget gives you an editable spreadsheet table right in your Jupyter notebooks. We can generate the table we need to fill in all the answers like so:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;288&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_oq8NjXKSdJ0SUXtwbNLPtQ-048ba0d8.D0tFbFvs_Z2uCOt0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That fills it up with zeros that we can then change to their proper values based on the answers on the Kieskompas website. After doing that, you can export them to a dataframe, which you can then easily save to your favorite file format:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;82&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_82StznXtkPV_gaFsoX9e1g-72a03541.Bw86ZTi7_Z1vbTYw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Obviously, csv is the only file format we’ll ever need. None of that newfangled mumbo jumbo for me, no sirree!&lt;/p&gt;
&lt;h2 id=&quot;science-that-data&quot;&gt;Science that data!&lt;/h2&gt;
&lt;p&gt;Now for the fun part: comparing the numbers in such a way that makes the results more palatable.&lt;/p&gt;
&lt;h3 id=&quot;t-sne&quot;&gt;T-SNE&lt;/h3&gt;
&lt;p&gt;My first thought was to try an alternative method of dimensional reduction. And what do we all think of first as true hipster data scientists? T-SNE!&lt;/p&gt;
&lt;p&gt;If you’re interested in learning about this method, check out &lt;a href=&quot;https://distill.pub/2016/misread-tsne/&quot;&gt;this article on T-SNE that looks pretty good&lt;/a&gt;. Since I was impatient, I didn’t read it at all, but just went straight for &lt;a href=&quot;https://scikit-learn.org/&quot;&gt;&lt;strong&gt;scikit-learn&lt;/strong&gt;&lt;/a&gt;, copy pasted the first thing I found, and tried to reduce the differences between my answers and those of all the parties to two dimensions:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;239&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IqebHLjKn1h9h6smE9iWDg-bb7af19b.fnkaln3H_2ttc3W.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Reload and mangle the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;371&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rtLrIntPNY0w7LXSi8Mfmw-5817fc05.DX9MbHtD_hmvd8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Transform the 30-dimensional answer-difference space with T-SNE to a two-dimensional space.&lt;/p&gt;
&lt;p&gt;Being an optimist, I completely expected the T-SNE dimensions to be better than the Kieskompas dimensions (which must have been meticulously designed and perfected over the past decade or even longer).&lt;/p&gt;
&lt;p&gt;Perhaps not surprisingly, I was disappointed. Naive application of T-SNE just gives random results. Each run gives a totally different result:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;722&quot; height=&quot;712&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SvhVI-WKSAL2-8hFo6TPYA-feb4e0c3.D5bPDSfW_ZqyH6e.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;770&quot; height=&quot;714&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8Y3QLpV2X-tTIuv_8UcC3w-6537ca2a.DhqHlSDY_1wgaG9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;774&quot; height=&quot;714&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Kzi2LdadGMo0RNMociY0zw-731aefe7.CzFhOvB0_n3vLW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;At least I’m not on top of 50+ anymore…&lt;/p&gt;
&lt;p&gt;A bit of randomness is not a problem per se, but there doesn’t seem to be any structure to this, so that’s not going to work.&lt;/p&gt;
&lt;h3 id=&quot;simple-distance&quot;&gt;Simple distance&lt;/h3&gt;
&lt;p&gt;When complicated stuff fails out of the box, it’s time to go back to basics. This may allow us to get a better grip on the data.&lt;/p&gt;
&lt;p&gt;Let’s start by just computing the Euclidian distance directly in the 30-dimensional answer difference space:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;666&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2WxMGNnE1BSnZu8TjVpDEA-8d69bcc1.DH4Yfzn5_ZaPLcq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is not completely what I would expect either, but I guess we can make some sense of it. I guess I’m usually a more or less center-left voter, so one could expect that my distance to the traditional center parties (VVD, CDA, PvdA) is small. Their answers are usually not at the extremes, so -1, 0 or 1. Parties like the PVV, FvD, PvdD and GL tend to take stronger stances (particularly on EU and climate matters, which 10 questions are about), so more 2s or -2s. Probably, using Euclidian distance directly on these numbers makes distances to these parties larger, unless you happen to have the exact same stances on most issues. It may help to somehow weigh the numbers to make differences slightly less extreme. But probably transforming the space in a more non-linear way is necessary… which was the original reason for trying T-SNE.&lt;/p&gt;
&lt;h3 id=&quot;principal-component-analysis&quot;&gt;Principal Component Analysis&lt;/h3&gt;
&lt;p&gt;Ok, so let’s try another standard trick of the trade: doing a principal component analysis (PCA). Simply put, PCA transforms a space with points into a space with different axes, ordered by the amount of variance in the data they describe. In other words, if these data predominantly spread out over a clear “left vs right” axis, PCA will find it and transform the points into that space. It is then trivial to plot the points along that axis, or along multiple such dimensions. The second dimension will already explain less of the variation, but might still be significant. Etcetera.&lt;/p&gt;
&lt;p&gt;Note that this is not at all guaranteed to give the same result as the two Kieskompas axes “left-right” and “conservative-progressive”. In fact, the Dutch parties seem more concentrated along the diagonal from left-progressive to right-conservative. This would mean that you would expect PCA to pick up this axis as a first dominant one.&lt;/p&gt;
&lt;p&gt;Again, we can use scikit-learn, where we just replace the TSNE model used above by a PCA model. First, let’s look at just this first, dominant component (or axis):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;72&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0W7lkGiv7z2808OrX7F7JA-66477020.DOG2Sxxq_Z1rBl6h.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When we sort all parties along that axis we get this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;646&quot; height=&quot;1344&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7dJSBaRg71LWfxFlCzRKwg-fb816823.D6iEs9j__ZCx3Cp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;910&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_bq4e2n1tNhgFKXfZu4NdmA-296ab6d2.geNjvpJI_Z1h2tFY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;For comparison, a rotated version of the first image is shown alongside the sorted results. The only two parties that are not ordered exactly like in this diagonal Kieskompas axis are D66 (by a few pixels) and FvD (the bottom one).&lt;/p&gt;
&lt;p&gt;So, clearly this PCA thing agrees in some way with the Kieskompas. Of course, that is exactly the opposite of what I wanted to achieve. I’m still next to 50+. &lt;em&gt;Damn you, data science!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intermezzo&lt;/strong&gt;: if you get annoyed at my overuse of the term data science, I’m with ya, I just noticed it myself. Let’s switch to &lt;em&gt;machine learning&lt;/em&gt; from now on. Then I’ll try &lt;em&gt;statistics&lt;/em&gt; if that starts annoying me as well. Maybe I’ll even throw in a &lt;em&gt;big data analytics&lt;/em&gt; if push comes to shove.&lt;/p&gt;
&lt;p&gt;Let’s add one more PCA axis, see if that brings us any respite:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;628&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ynXjOn7iqBPsP0jtd6llxA-4bec0ddd.BhsVtP7V_ZBb2iS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interestingly, this (vertical) component moves a lot of parties far away from me. I’m really unhappy with the ones I’m clustered left with though. These are typically the parties that are pretty much at the bottom of my “would ever vote for” list. In fact, I most often vote PvdD or SP, the parties that are now furthest from me! What’s going on here? Is this some kind of cyclical component?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1344&quot; height=&quot;646&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CRUXKluu8qkp8a-lsthBCA-3e218400.DBHUc5kZ_Z1V91xN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;However, it does again seem to map pretty well to the second diagonal of the Kieskompas dimensions. The match is a bit sloppier, but you can definitely see the general trend being right. The biggest exception is me! Other than that, the above 2D PCA decomposition matches pretty well to a mirrored and again rotated Kieskompas picture.&lt;/p&gt;
&lt;p&gt;Pretty neat! I guess I should stop blaming Kieskompas and start looking in the mirror… ouch.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Ok, so after all was said and done, I completely failed on my original, important goal: to prove that I was not at all a match to the 50 Plus party. In a moment of clarity, I decided to actually compare the 50 Plus answers to mine… and it turned out they were indeed very close.&lt;/p&gt;
&lt;p&gt;So thanks, Kieskompas for confronting me with this painful truth. Acceptance is the first step. I may write 50 Plus a strongly worded letter someday soon, demanding they change their name to accomodate my sensitivities.&lt;/p&gt;
&lt;p&gt;Some other things that I learned or was reminded of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Finding the right data science tool or model for the job can be quite challenging.&lt;/li&gt;
&lt;li&gt;But so much is so widely available nowadays that really complicated problems can sometimes feel mind blowingly easy. I did all of the above in a couple of hours. &lt;em&gt;&lt;strong&gt;The amount and quality of tools, especially in the Python and Jupyter world, has exploded in recent years&lt;/strong&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Right now, the only two major obstacles that are left in data science are one’s own imagination (and maybe experience) and the complexities that are inherent in the studied subjects themselves. &lt;em&gt;&lt;strong&gt;You can no longer blame the tools!&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Political matching is hard and &lt;em&gt;&lt;strong&gt;Kieskompas is doing a pretty great job&lt;/strong&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;CSV for ever! (I tried saving to JSON, but then the indices would be loaded back as strings instead of integers. Boo!)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that I’m a complete novice in this field of political party space mapping (is that the correct term?). Please shout at me in the comments below or on &lt;a href=&quot;https://www.reddit.com/r/Python/comments/bs61go/political_party_matcher_not_matching_the_way_youd/&quot;&gt;Reddit&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/egpbos/status/1131578689391648773&quot;&gt;Twitter&lt;/a&gt; if I made some stupid mistakes. I’d love to talk to experts about how to do this better!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;819&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-iSyUaurwTwQBygErkBcTQ-730b1f3e.Bc5awxiD_Z1gK76r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Somebody stop me!&lt;/p&gt;</description><pubDate>Thu, 23 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Dimensional reduction. Who doesn’t love it? Everybody does!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1920&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fCDDMFJQUb5CmCVtxJTyTA-0a6bac2b.0u4fr91r_khJPT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;On that note: EU election week! Time to map our complex individual preferences to one of a few packages of lumped together stances.&lt;/p&gt;
&lt;p&gt;Luckily, with the advent of political matching tool websites, this is as easy as answering a couple of questions on a one dimensional scale. The algorithm then takes care of the optimal mapping, you can cross the right box on the ballot and get on with your life, knowing you’ve been a good citizen and all will be well!&lt;/p&gt;
&lt;p&gt;As much as I love &lt;strong&gt;one&lt;/strong&gt; dimensional reduction, though, I have an odd preference for the &lt;strong&gt;two&lt;/strong&gt; dimensional reduction that Kieskompas (Election Compass) has offered for years now in the Netherlands. Yesterday morning, I took the test.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1354&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sUjONvjaoc0BOrwcCZ0FsA-a86da711.CFC1hIRV_1nhqpE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The balls are the major parties (we got a lot of ’em in the Netherlands), the marker is me. Links = left, rechts = right, progressive, conservative, you get the idea.&lt;/p&gt;
&lt;p&gt;Arrgh, right in the middle of the black hole of despair!&lt;/p&gt;
&lt;p&gt;I’m definitely not going to vote for 50 Plus, the (seemingly) one-issue pensionado party. All the other parties are miles away, so what good is this advice? How could it even be that 50 Plus is so close to me? Is there some kind of weird averaging going on? Are my (or 50 Plus’) answers canceling each other out in such a way that we just happen to end up in the exact same place, even though we’re diametrically opposed on every issue, &lt;strong&gt;which I must assume we are&lt;/strong&gt;?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;470&quot; height=&quot;325&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7XNAxB-fd2MWHvLfJI7UgA-8f642e21.COPPam7m_Z1HrGYs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The only logical explanation.&lt;/p&gt;
&lt;p&gt;Spoiler alert: it turns out this party actually isn’t such a bad fit for me.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;280&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_2rhyo9zsDj2InUlP-9d354cdd.9D6KzaR2_abugu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;80s meme, suck on that, millennials!&lt;/p&gt;
&lt;p&gt;But I sure as hell wasn’t going to accept that without a fight. I was sure something was wrong with the algorithms. I was going to get to the bottom of this and find out a way to get me a better match. &lt;em&gt;Get me my data sciencing tools!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;859&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GSOpTB1VmBy97pN6gJFxzw-941987fc.M2K1DPwf_ZTxLgP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Me, sciencing them datas! This must have been something like a couple years ago… wait, 2006…?!&lt;/p&gt;
&lt;h2 id=&quot;data-gathering&quot;&gt;Data gathering&lt;/h2&gt;
&lt;p&gt;The Kieskompas contains 30 questions that can be answered on a 5 point scale: “strongly agree” (2), “agree” (1), “neutral” (0), “disagree” (-1) and “strongly disagree” (-2). You can also skip questions. The answers are clustered into 7 topics, but I won’t use that here.&lt;/p&gt;
&lt;p&gt;So there’s two basic pieces of data I need here: my answers and those from the parties.&lt;/p&gt;
&lt;h3 id=&quot;my-own-answers&quot;&gt;My own answers&lt;/h3&gt;
&lt;p&gt;I already filled out all the questions on the website, so the data should be around somewhere in my browser cache. Using Firefox’s development console, I was able to find it in the storage section (Shift-F9) under Local Storage.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;380&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7myn_EenujQiN-KOfts2VA-83ed0a83.DIa--LER_ZJlPRg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;There’s my data.&lt;/p&gt;
&lt;p&gt;This JSON data can be easily copy-pasted into a Jupyter notebook, where I was going to Python-fu this thing into submission. Using an advanced JSON to Python conversion technique (first cell below) and some Pandas magic, we end up with a neat dataframe:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;594&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GLgsmbdbYG87Vrfyqk6Erg-7cf0427c.GuSL3zPB_Z1zdtTC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The important column is &lt;code&gt;answer.value&lt;/code&gt;, which I can compare to the answers given by the political parties.&lt;/p&gt;
&lt;h3 id=&quot;party-answers-enter-ipysheet&quot;&gt;Party answers: enter ipysheet&lt;/h3&gt;
&lt;p&gt;That party answer data, however, was not as readily scrapeable. Possibly, there is some copyright involved there as well (which is also the reason I’m not sharing all this stuff publicly), which forced them to hide the data a bit. Possibly, I’m just not looking in the right places. Whatever the case, I couldn’t find it.&lt;/p&gt;
&lt;p&gt;Luckily, the website offers a page to compare all your answers to all the parties’ answers, so we can just manually copy all 30 of them for all 12 available parties!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;659&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_M0WgX7PajLewKek0CkD0Cg-b2c16c42.BpFEDTHk_2vwYFE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That’s only 360 numbers.&lt;/p&gt;
&lt;p&gt;“Manually copy?!” I hear you object. Normally, I would agree with you, even if it’s just 360 numbers, manual labor goes against everything I stand for as a lazy programmer (or rather: sit for), but I was getting desparate for data and I had hit a wall. Also, this gave me a good excuse to try out &lt;strong&gt;ipysheet&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;The ipysheet Jupyter widget gives you an editable spreadsheet table right in your Jupyter notebooks. We can generate the table we need to fill in all the answers like so:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;288&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_oq8NjXKSdJ0SUXtwbNLPtQ-048ba0d8.D0tFbFvs_Z2uCOt0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That fills it up with zeros that we can then change to their proper values based on the answers on the Kieskompas website. After doing that, you can export them to a dataframe, which you can then easily save to your favorite file format:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;82&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_82StznXtkPV_gaFsoX9e1g-72a03541.Bw86ZTi7_Z1vbTYw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Obviously, csv is the only file format we’ll ever need. None of that newfangled mumbo jumbo for me, no sirree!&lt;/p&gt;
&lt;h2 id=&quot;science-that-data&quot;&gt;Science that data!&lt;/h2&gt;
&lt;p&gt;Now for the fun part: comparing the numbers in such a way that makes the results more palatable.&lt;/p&gt;
&lt;h3 id=&quot;t-sne&quot;&gt;T-SNE&lt;/h3&gt;
&lt;p&gt;My first thought was to try an alternative method of dimensional reduction. And what do we all think of first as true hipster data scientists? T-SNE!&lt;/p&gt;
&lt;p&gt;If you’re interested in learning about this method, check out &lt;a href=&quot;https://distill.pub/2016/misread-tsne/&quot;&gt;this article on T-SNE that looks pretty good&lt;/a&gt;. Since I was impatient, I didn’t read it at all, but just went straight for &lt;a href=&quot;https://scikit-learn.org/&quot;&gt;&lt;strong&gt;scikit-learn&lt;/strong&gt;&lt;/a&gt;, copy pasted the first thing I found, and tried to reduce the differences between my answers and those of all the parties to two dimensions:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;239&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IqebHLjKn1h9h6smE9iWDg-bb7af19b.fnkaln3H_2ttc3W.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Reload and mangle the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;371&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rtLrIntPNY0w7LXSi8Mfmw-5817fc05.DX9MbHtD_hmvd8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Transform the 30-dimensional answer-difference space with T-SNE to a two-dimensional space.&lt;/p&gt;
&lt;p&gt;Being an optimist, I completely expected the T-SNE dimensions to be better than the Kieskompas dimensions (which must have been meticulously designed and perfected over the past decade or even longer).&lt;/p&gt;
&lt;p&gt;Perhaps not surprisingly, I was disappointed. Naive application of T-SNE just gives random results. Each run gives a totally different result:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;722&quot; height=&quot;712&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SvhVI-WKSAL2-8hFo6TPYA-feb4e0c3.D5bPDSfW_ZqyH6e.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;770&quot; height=&quot;714&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8Y3QLpV2X-tTIuv_8UcC3w-6537ca2a.DhqHlSDY_1wgaG9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;774&quot; height=&quot;714&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Kzi2LdadGMo0RNMociY0zw-731aefe7.CzFhOvB0_n3vLW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;At least I’m not on top of 50+ anymore…&lt;/p&gt;
&lt;p&gt;A bit of randomness is not a problem per se, but there doesn’t seem to be any structure to this, so that’s not going to work.&lt;/p&gt;
&lt;h3 id=&quot;simple-distance&quot;&gt;Simple distance&lt;/h3&gt;
&lt;p&gt;When complicated stuff fails out of the box, it’s time to go back to basics. This may allow us to get a better grip on the data.&lt;/p&gt;
&lt;p&gt;Let’s start by just computing the Euclidian distance directly in the 30-dimensional answer difference space:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;666&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2WxMGNnE1BSnZu8TjVpDEA-8d69bcc1.DH4Yfzn5_ZaPLcq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is not completely what I would expect either, but I guess we can make some sense of it. I guess I’m usually a more or less center-left voter, so one could expect that my distance to the traditional center parties (VVD, CDA, PvdA) is small. Their answers are usually not at the extremes, so -1, 0 or 1. Parties like the PVV, FvD, PvdD and GL tend to take stronger stances (particularly on EU and climate matters, which 10 questions are about), so more 2s or -2s. Probably, using Euclidian distance directly on these numbers makes distances to these parties larger, unless you happen to have the exact same stances on most issues. It may help to somehow weigh the numbers to make differences slightly less extreme. But probably transforming the space in a more non-linear way is necessary… which was the original reason for trying T-SNE.&lt;/p&gt;
&lt;h3 id=&quot;principal-component-analysis&quot;&gt;Principal Component Analysis&lt;/h3&gt;
&lt;p&gt;Ok, so let’s try another standard trick of the trade: doing a principal component analysis (PCA). Simply put, PCA transforms a space with points into a space with different axes, ordered by the amount of variance in the data they describe. In other words, if these data predominantly spread out over a clear “left vs right” axis, PCA will find it and transform the points into that space. It is then trivial to plot the points along that axis, or along multiple such dimensions. The second dimension will already explain less of the variation, but might still be significant. Etcetera.&lt;/p&gt;
&lt;p&gt;Note that this is not at all guaranteed to give the same result as the two Kieskompas axes “left-right” and “conservative-progressive”. In fact, the Dutch parties seem more concentrated along the diagonal from left-progressive to right-conservative. This would mean that you would expect PCA to pick up this axis as a first dominant one.&lt;/p&gt;
&lt;p&gt;Again, we can use scikit-learn, where we just replace the TSNE model used above by a PCA model. First, let’s look at just this first, dominant component (or axis):&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;72&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0W7lkGiv7z2808OrX7F7JA-66477020.DOG2Sxxq_Z1rBl6h.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When we sort all parties along that axis we get this:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;646&quot; height=&quot;1344&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7dJSBaRg71LWfxFlCzRKwg-fb816823.D6iEs9j__ZCx3Cp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;910&quot; height=&quot;910&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_bq4e2n1tNhgFKXfZu4NdmA-296ab6d2.geNjvpJI_Z1h2tFY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;For comparison, a rotated version of the first image is shown alongside the sorted results. The only two parties that are not ordered exactly like in this diagonal Kieskompas axis are D66 (by a few pixels) and FvD (the bottom one).&lt;/p&gt;
&lt;p&gt;So, clearly this PCA thing agrees in some way with the Kieskompas. Of course, that is exactly the opposite of what I wanted to achieve. I’m still next to 50+. &lt;em&gt;Damn you, data science!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intermezzo&lt;/strong&gt;: if you get annoyed at my overuse of the term data science, I’m with ya, I just noticed it myself. Let’s switch to &lt;em&gt;machine learning&lt;/em&gt; from now on. Then I’ll try &lt;em&gt;statistics&lt;/em&gt; if that starts annoying me as well. Maybe I’ll even throw in a &lt;em&gt;big data analytics&lt;/em&gt; if push comes to shove.&lt;/p&gt;
&lt;p&gt;Let’s add one more PCA axis, see if that brings us any respite:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;628&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ynXjOn7iqBPsP0jtd6llxA-4bec0ddd.BhsVtP7V_ZBb2iS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interestingly, this (vertical) component moves a lot of parties far away from me. I’m really unhappy with the ones I’m clustered left with though. These are typically the parties that are pretty much at the bottom of my “would ever vote for” list. In fact, I most often vote PvdD or SP, the parties that are now furthest from me! What’s going on here? Is this some kind of cyclical component?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1344&quot; height=&quot;646&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CRUXKluu8qkp8a-lsthBCA-3e218400.DBHUc5kZ_Z1V91xN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;However, it does again seem to map pretty well to the second diagonal of the Kieskompas dimensions. The match is a bit sloppier, but you can definitely see the general trend being right. The biggest exception is me! Other than that, the above 2D PCA decomposition matches pretty well to a mirrored and again rotated Kieskompas picture.&lt;/p&gt;
&lt;p&gt;Pretty neat! I guess I should stop blaming Kieskompas and start looking in the mirror… ouch.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Ok, so after all was said and done, I completely failed on my original, important goal: to prove that I was not at all a match to the 50 Plus party. In a moment of clarity, I decided to actually compare the 50 Plus answers to mine… and it turned out they were indeed very close.&lt;/p&gt;
&lt;p&gt;So thanks, Kieskompas for confronting me with this painful truth. Acceptance is the first step. I may write 50 Plus a strongly worded letter someday soon, demanding they change their name to accomodate my sensitivities.&lt;/p&gt;
&lt;p&gt;Some other things that I learned or was reminded of:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Finding the right data science tool or model for the job can be quite challenging.&lt;/li&gt;
&lt;li&gt;But so much is so widely available nowadays that really complicated problems can sometimes feel mind blowingly easy. I did all of the above in a couple of hours. &lt;em&gt;&lt;strong&gt;The amount and quality of tools, especially in the Python and Jupyter world, has exploded in recent years&lt;/strong&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Right now, the only two major obstacles that are left in data science are one’s own imagination (and maybe experience) and the complexities that are inherent in the studied subjects themselves. &lt;em&gt;&lt;strong&gt;You can no longer blame the tools!&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Political matching is hard and &lt;em&gt;&lt;strong&gt;Kieskompas is doing a pretty great job&lt;/strong&gt;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;CSV for ever! (I tried saving to JSON, but then the indices would be loaded back as strings instead of integers. Boo!)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that I’m a complete novice in this field of political party space mapping (is that the correct term?). Please shout at me in the comments below or on &lt;a href=&quot;https://www.reddit.com/r/Python/comments/bs61go/political_party_matcher_not_matching_the_way_youd/&quot;&gt;Reddit&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/egpbos/status/1131578689391648773&quot;&gt;Twitter&lt;/a&gt; if I made some stupid mistakes. I’d love to talk to experts about how to do this better!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;819&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-iSyUaurwTwQBygErkBcTQ-730b1f3e.Bc5awxiD_Z1gK76r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Somebody stop me!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_sUjONvjaoc0BOrwcCZ0FsA-a86da711.CFC1hIRV.png" medium="image"/><author>Patrick Bos</author></item><item><title>understanding global corporate networks</title><link>https://blog2.esciencecenter.nl/posts/2019-04-04---understanding-global-corporate-networks</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-04-04---understanding-global-corporate-networks</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1250&quot; height=&quot;833&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7zTznpyO2ZqFmgwCc_Y5Ug-92e253f8.CpzY2RnD_Z1rnqbm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Members of the CORPNET group at the University of Amsterdam&lt;/p&gt;
&lt;p&gt;Frank Takes is an assistant professor at Leiden University and member of the &lt;a href=&quot;https://corpnet.uva.nl/&quot;&gt;CORPNET group&lt;/a&gt; at the University of Amsterdam, where he was previously employed as a postdoctoral researcher.&lt;/p&gt;
&lt;p&gt;In 2017 Frank won the Young eScientist Award. He received in-kind expertise from the eScience Center for his project &lt;a href=&quot;https://www.esciencecenter.nl/project/uncovering-networks-of-corporate-control&quot;&gt;Uncovering Networks of Corporate Control&lt;/a&gt;, where the goal was to create an interactive web-based platform to investigate the dynamics of global corporate networks.&lt;/p&gt;
&lt;p&gt;By collaborating with the eScience Center, Frank and his fellow researchers at UvA CORPNET group aim to better understand the transnational interconnectedness of corporations and how this influences people, organizations and institutions.&lt;/p&gt;
&lt;h2 id=&quot;the-project-uncovering-networks-of-corporate-control&quot;&gt;The Project: Uncovering Networks of Corporate Control&lt;/h2&gt;
&lt;p&gt;The multidisciplinary field of computational social science deals with research on computational methods for understanding our highly complex society. The ERC-funded CORPNET research group at the University of Amsterdam is particularly concerned with understanding the global socioeconomic system. More specifically, the aim is to understand the transnational interconnectedness of corporations and how this influences people, organizations and institutions. The work done so far has provided novel insights in topics such as corporate elites, state investment strategies, the detection of tax havens, but for example also the economic connectedness of global cities in what is called a small-world network.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1132&quot; height=&quot;579&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1oSKdqUFXU_qz3_UAeuCuw-6a373ae6.Bo727jmD_wowkh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yWT6wOIM1kuE6iLaXUY0lQ-eaf9fb67.CTKWk5j5_ZNccE6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Corporate networks model the connectivity of global business, allowing network science techniques to find meaningful patterns&lt;/p&gt;
&lt;h2 id=&quot;novel-insights&quot;&gt;Novel insights&lt;/h2&gt;
&lt;p&gt;Apart from addressing social science questions, we advance methods in the field of computational social science and data science, including modeling, simulation, and most importantly, social network analysis. This field, sometimes also called network science, considers modeling data as a network of entities and the interactions between these entities. By doing so, we can discover novel insights in the underlying complex system that would otherwise remain hidden. We particularly aim to do so for large-scale data; in our case a large network dataset of over one hundred million companies and the various social and economic links between these organizations.&lt;/p&gt;
&lt;h2 id=&quot;collaboration--research-between-different-disciplines&quot;&gt;Collaboration &amp;#x26; Research between different disciplines&lt;/h2&gt;
&lt;p&gt;The type of research done in our group is highly interdisciplinary. The aim is not to have the computational aspect only support the social sciences, or to merely enrich the methodological work with some societal application domain. Instead, we want to advance both the social sciences as well as computer science and eScience methodologies. This involves working together in teams consisting of people with different mixed disciplines that have a natural drive to understand each other’s goals and objectives.&lt;/p&gt;
&lt;p&gt;Netherlands eScience Center research engineers Dafne van Kuppevelt and Laurens Bogaardt joined the CORPNET group in the beginning of 2018 as part of Frank Takes’s eScience pathfinder project Uncovering Networks of Corporate Control. It was a pleasure to collaborate with both of them, as they fully understood the interdisciplinary angle that plays such a central role in our research group.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_l3WpMAnStkaSfVs4yD9PeQ-bbef4163.BGJyjesU_ZiQeFQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Frank Takes (University of Amsterdam) and Laurens Bogaardt (Netherlands eScience Center)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;“&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;The first challenge in any collaboration is communication — understanding what the aim of the project should be. Fortunately, with experience, this challenge can be tackled. The main advantage I see in collaborating with a diverse group of people is the jolt it gives to your creativity, leading to new ideas and solution both within the project and in other, future projects.” — Laurens Bogaardt&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;471&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0l-XYnzUyhIO0JvB2FUqzg-a816fe40.DWNDk9Dr_Z1gtFLg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The advantages of collaborations are that it is fun and rewarding, when coming from different disciplines you can really complement each other. The challenge is that it takes effort to understand where collaborators are coming from and what the norms in a different field are.” — Dafne van Kuppevelt&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;sharing-knowledge-and-tools-to-drive-research-forward&quot;&gt;Sharing knowledge and tools to drive research forward&lt;/h2&gt;
&lt;p&gt;The eScience research engineers were able to quickly identify highly relevant scientific problems relevant to our research group where they could employ their expertise.&lt;/p&gt;
&lt;p&gt;Laurens worked on methods for dynamic social network analysis for which a theoretical model was proposed, but no efficient implementation yet existed. Using a thorough mathematical analysis, he devised a scalable implementation of this model. In the future, this will allow us to study large-scale dynamic network data, surpassing previous computational limits of these types of models.&lt;/p&gt;
&lt;p&gt;Dafne worked on the problem of network community detection, where the goal is to automatically find groups of entities in social network data that are tightly connected. In particular, she devised methods and metrics that allow for more reliable interpretation of community detection results by social scientists. This highlights the interdisciplinary aspect of the work: it is not only about running algorithms and showing the results, but also in interpreting these results in a sensible way within the domain that the underlying data is representing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I learned much about the social sciences and the way social scientists do research. I also had the chance to dive into computer science / network science literature that was relevant for this project, so I also gained more expertise in my own domain.” — Dafne van Kuppervelt&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7x3YKZFe71qHSauea9VTvg-6c0531f9.CVmCkynF_Mhfyd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uX1UAUXtNHmgjDmy2bjtog-eb2af59e.CTmj7RI3_Zt3fTT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FQCBZNeoQ4AfowSIbXjUqA-5a05684b.BJPy_oSV_ZMzq9Q.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pzWZx5tY-MtVQcvAjh9JRw-bc9f4077.C8s4fNon_Z1EIueW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-role-of-openness-and-sharing&quot;&gt;The role of openness and sharing&lt;/h2&gt;
&lt;p&gt;One aspect that the Netherlands eScience Center has ample experience with, is data sharing and the FAIR data principles. Given that we work with large databases consisting of hundreds of millions of records of companies across the globe, a proper assessment of our data management against the FAIR principles and a systematic documentation of preprocessing steps have proven extemely helpful in professionalizing our research activities.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“A proper assessment of our data management against the FAIR principles and a systematic documentation of preprocessing steps have proven extemely helpful in professionalizing our research activities”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;long-term-impact-on-the-domain-social-science-and-society-of-the-project&quot;&gt;Long-term impact on the domain social science and society of the project&lt;/h2&gt;
&lt;p&gt;In general, the collaboration between social scientists and computer scientists is bound to last for a long time. With the ever-increasing amount of data that is nowadays available, social scientists will increasingly more often be confronted with challenges related to the size of the data and meaningful interpretation of patterns found in these big datasets. Similarly, computer scientists are confronted with more and more complex matters related to methods for the automated extraction of knowledge from large-scale data. With data-awareness of the average citizen increasing every year, society increasingly expects researchers, regardless of discipline, to make use of this data for answering today’s big research questions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_eywCY1eIMXCjuslKEvdbjQ-0705a31e.CD7ucLSk_Zfsese.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Diliara Valeeva, Lucas van Straalen, Laurens Bogaardt, Javier Garcia-Bernardo, Eelke Heemskerk, Frank Takes and Milan Babic&lt;/p&gt;
&lt;h2 id=&quot;franks-vision-for-his-research-area-in-three-years&quot;&gt;Frank’s vision for his research area in three years&lt;/h2&gt;
&lt;p&gt;Social science research is becoming increasingly dependent on computational methods, and there is no reason to assume that this trend is not continued in the coming years. For example, the &lt;a href=&quot;https://2019.ic2s2.org/&quot;&gt;International Conference of Computational Social Science&lt;/a&gt; (IC2S2), which is the international flagship conference of computational social science is quickly growing in number of attendants, with over 400 researchers attending the 5th edition, held at University of Amsterdam in July 2019.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography:&lt;/em&gt; Michiel Wijnbergh &lt;em&gt;|&lt;/em&gt; &lt;a href=&quot;http://www.wijnbergh.nl/&quot;&gt;wijnbergh.nl&lt;/a&gt;&lt;/p&gt;</description><pubDate>Thu, 04 Apr 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1250&quot; height=&quot;833&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7zTznpyO2ZqFmgwCc_Y5Ug-92e253f8.CpzY2RnD_Z1rnqbm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Members of the CORPNET group at the University of Amsterdam&lt;/p&gt;
&lt;p&gt;Frank Takes is an assistant professor at Leiden University and member of the &lt;a href=&quot;https://corpnet.uva.nl/&quot;&gt;CORPNET group&lt;/a&gt; at the University of Amsterdam, where he was previously employed as a postdoctoral researcher.&lt;/p&gt;
&lt;p&gt;In 2017 Frank won the Young eScientist Award. He received in-kind expertise from the eScience Center for his project &lt;a href=&quot;https://www.esciencecenter.nl/project/uncovering-networks-of-corporate-control&quot;&gt;Uncovering Networks of Corporate Control&lt;/a&gt;, where the goal was to create an interactive web-based platform to investigate the dynamics of global corporate networks.&lt;/p&gt;
&lt;p&gt;By collaborating with the eScience Center, Frank and his fellow researchers at UvA CORPNET group aim to better understand the transnational interconnectedness of corporations and how this influences people, organizations and institutions.&lt;/p&gt;
&lt;h2 id=&quot;the-project-uncovering-networks-of-corporate-control&quot;&gt;The Project: Uncovering Networks of Corporate Control&lt;/h2&gt;
&lt;p&gt;The multidisciplinary field of computational social science deals with research on computational methods for understanding our highly complex society. The ERC-funded CORPNET research group at the University of Amsterdam is particularly concerned with understanding the global socioeconomic system. More specifically, the aim is to understand the transnational interconnectedness of corporations and how this influences people, organizations and institutions. The work done so far has provided novel insights in topics such as corporate elites, state investment strategies, the detection of tax havens, but for example also the economic connectedness of global cities in what is called a small-world network.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1132&quot; height=&quot;579&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1oSKdqUFXU_qz3_UAeuCuw-6a373ae6.Bo727jmD_wowkh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yWT6wOIM1kuE6iLaXUY0lQ-eaf9fb67.CTKWk5j5_ZNccE6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Corporate networks model the connectivity of global business, allowing network science techniques to find meaningful patterns&lt;/p&gt;
&lt;h2 id=&quot;novel-insights&quot;&gt;Novel insights&lt;/h2&gt;
&lt;p&gt;Apart from addressing social science questions, we advance methods in the field of computational social science and data science, including modeling, simulation, and most importantly, social network analysis. This field, sometimes also called network science, considers modeling data as a network of entities and the interactions between these entities. By doing so, we can discover novel insights in the underlying complex system that would otherwise remain hidden. We particularly aim to do so for large-scale data; in our case a large network dataset of over one hundred million companies and the various social and economic links between these organizations.&lt;/p&gt;
&lt;h2 id=&quot;collaboration--research-between-different-disciplines&quot;&gt;Collaboration &amp;#x26; Research between different disciplines&lt;/h2&gt;
&lt;p&gt;The type of research done in our group is highly interdisciplinary. The aim is not to have the computational aspect only support the social sciences, or to merely enrich the methodological work with some societal application domain. Instead, we want to advance both the social sciences as well as computer science and eScience methodologies. This involves working together in teams consisting of people with different mixed disciplines that have a natural drive to understand each other’s goals and objectives.&lt;/p&gt;
&lt;p&gt;Netherlands eScience Center research engineers Dafne van Kuppevelt and Laurens Bogaardt joined the CORPNET group in the beginning of 2018 as part of Frank Takes’s eScience pathfinder project Uncovering Networks of Corporate Control. It was a pleasure to collaborate with both of them, as they fully understood the interdisciplinary angle that plays such a central role in our research group.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_l3WpMAnStkaSfVs4yD9PeQ-bbef4163.BGJyjesU_ZiQeFQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Frank Takes (University of Amsterdam) and Laurens Bogaardt (Netherlands eScience Center)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;“&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;The first challenge in any collaboration is communication — understanding what the aim of the project should be. Fortunately, with experience, this challenge can be tackled. The main advantage I see in collaborating with a diverse group of people is the jolt it gives to your creativity, leading to new ideas and solution both within the project and in other, future projects.” — Laurens Bogaardt&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;471&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0l-XYnzUyhIO0JvB2FUqzg-a816fe40.DWNDk9Dr_Z1gtFLg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The advantages of collaborations are that it is fun and rewarding, when coming from different disciplines you can really complement each other. The challenge is that it takes effort to understand where collaborators are coming from and what the norms in a different field are.” — Dafne van Kuppevelt&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;sharing-knowledge-and-tools-to-drive-research-forward&quot;&gt;Sharing knowledge and tools to drive research forward&lt;/h2&gt;
&lt;p&gt;The eScience research engineers were able to quickly identify highly relevant scientific problems relevant to our research group where they could employ their expertise.&lt;/p&gt;
&lt;p&gt;Laurens worked on methods for dynamic social network analysis for which a theoretical model was proposed, but no efficient implementation yet existed. Using a thorough mathematical analysis, he devised a scalable implementation of this model. In the future, this will allow us to study large-scale dynamic network data, surpassing previous computational limits of these types of models.&lt;/p&gt;
&lt;p&gt;Dafne worked on the problem of network community detection, where the goal is to automatically find groups of entities in social network data that are tightly connected. In particular, she devised methods and metrics that allow for more reliable interpretation of community detection results by social scientists. This highlights the interdisciplinary aspect of the work: it is not only about running algorithms and showing the results, but also in interpreting these results in a sensible way within the domain that the underlying data is representing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I learned much about the social sciences and the way social scientists do research. I also had the chance to dive into computer science / network science literature that was relevant for this project, so I also gained more expertise in my own domain.” — Dafne van Kuppervelt&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7x3YKZFe71qHSauea9VTvg-6c0531f9.CVmCkynF_Mhfyd.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uX1UAUXtNHmgjDmy2bjtog-eb2af59e.CTmj7RI3_Zt3fTT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FQCBZNeoQ4AfowSIbXjUqA-5a05684b.BJPy_oSV_ZMzq9Q.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pzWZx5tY-MtVQcvAjh9JRw-bc9f4077.C8s4fNon_Z1EIueW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-role-of-openness-and-sharing&quot;&gt;The role of openness and sharing&lt;/h2&gt;
&lt;p&gt;One aspect that the Netherlands eScience Center has ample experience with, is data sharing and the FAIR data principles. Given that we work with large databases consisting of hundreds of millions of records of companies across the globe, a proper assessment of our data management against the FAIR principles and a systematic documentation of preprocessing steps have proven extemely helpful in professionalizing our research activities.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“A proper assessment of our data management against the FAIR principles and a systematic documentation of preprocessing steps have proven extemely helpful in professionalizing our research activities”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;long-term-impact-on-the-domain-social-science-and-society-of-the-project&quot;&gt;Long-term impact on the domain social science and society of the project&lt;/h2&gt;
&lt;p&gt;In general, the collaboration between social scientists and computer scientists is bound to last for a long time. With the ever-increasing amount of data that is nowadays available, social scientists will increasingly more often be confronted with challenges related to the size of the data and meaningful interpretation of patterns found in these big datasets. Similarly, computer scientists are confronted with more and more complex matters related to methods for the automated extraction of knowledge from large-scale data. With data-awareness of the average citizen increasing every year, society increasingly expects researchers, regardless of discipline, to make use of this data for answering today’s big research questions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_eywCY1eIMXCjuslKEvdbjQ-0705a31e.CD7ucLSk_Zfsese.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Diliara Valeeva, Lucas van Straalen, Laurens Bogaardt, Javier Garcia-Bernardo, Eelke Heemskerk, Frank Takes and Milan Babic&lt;/p&gt;
&lt;h2 id=&quot;franks-vision-for-his-research-area-in-three-years&quot;&gt;Frank’s vision for his research area in three years&lt;/h2&gt;
&lt;p&gt;Social science research is becoming increasingly dependent on computational methods, and there is no reason to assume that this trend is not continued in the coming years. For example, the &lt;a href=&quot;https://2019.ic2s2.org/&quot;&gt;International Conference of Computational Social Science&lt;/a&gt; (IC2S2), which is the international flagship conference of computational social science is quickly growing in number of attendants, with over 400 researchers attending the 5th edition, held at University of Amsterdam in July 2019.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography:&lt;/em&gt; Michiel Wijnbergh &lt;em&gt;|&lt;/em&gt; &lt;a href=&quot;http://www.wijnbergh.nl/&quot;&gt;wijnbergh.nl&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_1oSKdqUFXU_qz3_UAeuCuw-6a373ae6.Bo727jmD.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>superhuman blog post</title><link>https://blog2.esciencecenter.nl/posts/2019-03-04---superhuman-blog-post</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-03-04---superhuman-blog-post</guid><description>&lt;p&gt;&lt;strong&gt;#demystifyAI series&lt;/strong&gt; (this small series aims at putting important AI-related aspects into perspective)&lt;/p&gt;
&lt;p&gt;Why you shouldn’t be afraid of AI tools occasionally performing &lt;em&gt;&lt;strong&gt;superhuman&lt;/strong&gt;&lt;/em&gt; in some tasks. And why &lt;strong&gt;you&lt;/strong&gt; are the true superhuman being.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iVaxGnagIZ6i2haK1ZH1LQ-86ec2227.DNLl_96q_Z1rf5WU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Superhuman performance is nothing rare. Here: humans forming a “superhuman” tower. Photo by Alessandra Pezzotta, published under CC BY license.&lt;/p&gt;
&lt;p&gt;I started my first hands-on training in machine learning and AI right after the GO matches between alpha go and Lee Sedol. At that time, it still felt a bit like a miracle to me. Not the shear fact that a computer would beat a world leading go player, but more the way it played and surprised the professional commentators.&lt;/p&gt;
&lt;p&gt;That was 3 years ago and the news were full of the “rise of AI” and the new area of superhuman AI. I had the feeling that a lot of that was silly, but at the same time I had not enough in-depth knowledge on AI to prove some wild claims to be wrong.&lt;/p&gt;
&lt;p&gt;I guess over time it just became a bit too much for me. If you sit in the wrong social media bubble, &lt;strong&gt;it must feel as if Superhuman AIs are already taking over&lt;/strong&gt; the world. A recent headline I saw in a bigger newspaper was &lt;em&gt;“Superhuman’ robots will outstrip mankind within 50 years, warns AI expert”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yeah. Sure…&lt;/p&gt;
&lt;h2 id=&quot;superhuman-so-what&quot;&gt;Superhuman? So what!&lt;/h2&gt;
&lt;p&gt;So here’s the thing. &lt;em&gt;&lt;strong&gt;Superhuman&lt;/strong&gt;&lt;/em&gt; apparently sounds like something special, like science fiction that has become real. It absolutely is not. It only means “above”, “over”, “beyond”, “better than” a human. And if you think about it for a second, this is something entirely ordinary. We make use of superhuman powers since thousands of years!&lt;/p&gt;
&lt;p&gt;Humans started domesticating animals more than 10.000 years ago.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; And this was often not primarily to get meat, but to make use of their &lt;em&gt;&lt;strong&gt;superhuman&lt;/strong&gt;&lt;/em&gt; powers. Dogs would have superhuman smell and hearing. Oxen or horses were used for their superhuman strength.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1190&quot; height=&quot;530&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_G3vAyVSVlYS3BapnW-Og3g-ebe36034.Xbenv8M4_Z2hP3sa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;718&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ai8XN0GpjdROoqQyiMhwEQ-8c6efd60.ChzIttnF_ZmELIm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1. There is a long history of using animals for their superhuman powers. Top: Ancient picture of oxen, dogs (“Painter of the burial chamber of Sennedjem”, ca. 1200 BCE, &lt;a href=&quot;https://en.wikipedia.org/wiki/File:Maler%5C_der%5C_Grabkammer%5C_des%5C_Sennudem%5C_001.jpg&quot;&gt;https://en.wikipedia.org/wiki/File:Maler\_der\_Grabkammer\_des\_Sennudem\_001.jpg&lt;/a&gt; Bottom: Image from a Krater depicting an ancient boar hunt, 550BC, British Museum, &lt;a href=&quot;https://en.wikipedia.org/wiki/File:Boar%5C_Hunting.jpg&quot;&gt;https://en.wikipedia.org/wiki/File:Boar\_Hunting.jpg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Yes, true. Those aspects wouldn’t touch our holiest humans-only domain: cognitive tasks! But here as well, &lt;em&gt;&lt;strong&gt;superhuman&lt;/strong&gt;&lt;/em&gt; might be little more than an over-used buzzword.&lt;/p&gt;
&lt;p&gt;Take the development of “writing” for instance. This can be seen as a way to externalize knowledge or memories. Also a diverse set of tools to help humans to do calculations have a long history, going back thousands of years.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Electronic calculators have long beaten our modest capabilities to doing calculations (quickly). And yet, nowadays nobody would look at one of them and feel the terror of being beaten by a machine!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_C3CUR9YuXawj_MwVQOTmEw-ad584207.CLDIhQA9_1TvdaN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2. Olivetti Programma 101, 1965–1971, Museo nazionale della scienza e della tecnologia Leonardo da Vinci, Milano, Creative Commons Attribution-Share Alike 4.0 International license. ( &lt;a href=&quot;https://en.wikipedia.org/wiki/File:Olivetti%5C_Programma%5C_101%5C_-%5C_Museo%5C_scienza%5C_e%5C_tecnologia%5C_Milano.jpg&quot;&gt;https://en.wikipedia.org/wiki/File:Olivetti\_Programma\_101\_-\_Museo\_scienza\_e\_tecnologia\_Milano.jpg&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;But let’s finally quick jump to today. Now, with the help of modern computers and algorithms, AI finally seems to be ahead of us in an ever increasing number of tasks! And that’s true. Current computers are fast enough to produce amazing results using modern or semi-modern algorithms or methods.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Computers now can beat us in the most classical board games (GO, chess). They correctly classify pictures, spoken and written language, and to some extent can drive a car. Amazing stuff. And those developments have quite an impact already. And they for sure will have far more impact in the near future. But the way the adjective &lt;strong&gt;superhuman&lt;/strong&gt; is used in those contexts is often heavily misleading.&lt;/p&gt;
&lt;h2 id=&quot;ai-savantism&quot;&gt;AI savantism&lt;/h2&gt;
&lt;p&gt;Until today, all, really &lt;strong&gt;all&lt;/strong&gt; AI and machine-learning tools and products are only superhuman in one or few very specific aspects. Not much difference to the historic examples given above.&lt;/p&gt;
&lt;p&gt;Intelligence and learning are very complex concepts. Projecting the isolated performance in only one single, restricted area onto a “general” concept of intelligence or learning, will nearly always lead to wrong and often ridiculous conclusions. Such entirely wrong predictions were made based on early AI successes in the 1960s and then later in the 1980s. And I am convinced that we see something very similar happening in recent years.[4]&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“In from three to eight years we will have a machine with the general intelligence of an average human being.”&lt;br&gt;
Marvin Minsky, 1970 in Life Magazine (though he believed to be misquoted here…)&lt;/p&gt;
&lt;p&gt;“machines will be capable, within twenty years, of doing any work a man can do”,&lt;br&gt;
H.A. Simon, 1965&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Along the same lines, a very nice 2017 article in the magazine &lt;em&gt;Wired&lt;/em&gt; made very clear that describing intelligence as an one-dimensional characteristic is the wrong way to go. They also make a strong case against a linear ladder-like evolution towards high, human intelligence.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Intelligence is not a single dimension, so ‘smarter than humans’ is a meaningless concept.”&lt;br&gt;
&lt;a href=&quot;https://www.wired.com/2017/04/the-myth-of-a-superhuman-ai/&quot;&gt;Wired, 2017&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am not saying that there is no threat for certain parts of the job markets. Just as the industrial revolution(s), and later phase of automation has already made many jobs obsolete, this is very likely to happen through AI-based applications as well. Maybe even more rapidly and drastically. And there are huge issues with AI algorithms being applied improperly or being given too much trust at important positions (e.g. deciding about loans, assurances etc.).&lt;/p&gt;
&lt;p&gt;But the mere ability to perform superhuman in &lt;strong&gt;ONE&lt;/strong&gt; thing, shouldn’t spark too much terror. No matter how long we train their neural networks, alpha Zero and his brothers and sisters will never learn why we play a board game at all. Or how to leave the building when the fire alarm goes off. It is only trained to understand &lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot; id=&quot;user-content-fnref-5&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; one narrow interpretation of a 19x19 grid with black and white stones on it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;692&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3b6qyqxxy22iS-2mK75WJg-73b33427.ZY2C727K_61kXc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3. Alpha Zero can outplay any human go player easily. But anything that is not a typical go situation, even if it’s within the limited 19-by-19 grid horizon, it won’t get. Both board situations depicted here will mean the same to the AI: ‘100% black wins, white to resign’. Illustration by Florian Huber, can be reused under the CC BY license&lt;/p&gt;
&lt;p&gt;How little current AI tools are able to generalize, and how restricted their trained capabilities are, becomes evident if we look at so called “adversarial examples”. In essence, these are examples that were specifically designed to trick AI tools. The same way optical illusions reveal a lot about how we humans perceive the world, adversarial examples give us a good sense of how AI tools work. One of the earlier examples that became widely known in the AI community was a technique to add a specifically designed but imperceptible (imperceptible to humans that is) signal to an image which would result in an entirely wrong classification of the image by the respective neural network (Figure X).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;407&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_14bg7Qj-2BHR96ebKjbKOQ-07acef95.SNv5QOhe_Z2mvHaH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4. An adversarial example from 2015 which became quite popular. Here an image of a panda is altered by adding a specific, but imperceptible signal on top. To the human eye the picture obviously remains a panda, while the neural network suddenly is convinced that the picture shows a gibbon. Figure adapted from [Goodfellow, Shlens, Szegedy, 2015].&lt;/p&gt;
&lt;p&gt;A more recent example reveals the AI’s very limited “understanding of the world” even more strikingly. A group of AI researchers designed a sticker that will trick a neural network to believe it sees a toaster. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-6&quot; id=&quot;user-content-fnref-6&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; This example is surprisingly robust and works for many standard neural networks used for image interpretation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Figure 5&lt;/strong&gt; / Youtube-movie. More recent adversarial examples. The authors of &lt;a href=&quot;https://arxiv.org/pdf/1712.09665.pdf&quot;&gt;this paper&lt;/a&gt; designed a sticker that will trick a typical neural network used on images to believe it sees a toaster.&lt;/p&gt;
&lt;p&gt;Every AI technique that hits the market right now is of the most extreme form of &lt;strong&gt;hyper-savantism&lt;/strong&gt;. Very good at one thing. Terrible at practically anything else. Let them be mono-superhuman then. It will still never make them truly super-human.&lt;/p&gt;
&lt;h2 id=&quot;collective-intelligence&quot;&gt;Collective intelligence&lt;/h2&gt;
&lt;p&gt;A much more meaningful concept of “superhuman” lies in the power of collective and symbiotic phenomena. This is also how Francois Chollet &lt;sup&gt;&lt;a href=&quot;#user-content-fn-7&quot; id=&quot;user-content-fnref-7&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; describes it in his &lt;a href=&quot;https://medium.com/@francois.chollet/the-impossibility-of-intelligence-explosion-5be4a9eda6ec&quot;&gt;fantastic blog post on the same topic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The baseline here is: You know what has more general intelligence than a human? &lt;strong&gt;More humans collaborating!&lt;/strong&gt;&lt;br&gt;
Following his arguments, human intelligence and learning are concepts that cannot be understood by looking at individual brain power, but are tightly linked to collective and collaborative interactions and human civilization or society as a whole.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Most of our intelligence is not in our brain, it is externalized as our civilization”&lt;br&gt;
Francois Chollet (in his &lt;a href=&quot;https://medium.com/@francois.chollet/the-impossibility-of-intelligence-explosion-5be4a9eda6ec.&quot;&gt;blog post&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;844&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ouXj6qH779t7p_Ziw1r-Ug-a2bb8c5e.DjZieqmS_2qnwGD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 6: Human intelligence cannot be thought as an isolated, individual brain. Our tools, surroundings, and our society are part of us. We are hence all truly superhuman beings! Illustration by Florian Huber, can be reused under the CC BY license.&lt;/p&gt;
&lt;p&gt;More than ever we rely on knowledge, expertise, and skills of other human beings in our daily life. We rely on superhuman bodies of knowledge collected and processed over countless generations. We rely on complex societal constructs, on a sophisticated educational and health care system, etc. As human beings, we cannot be described by only looking at our individual brain. What we are, what we do, and what we think is inextricably linked with our body, our surroundings, and the society around us.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-8&quot; id=&quot;user-content-fnref-8&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;AI tools, agents, methods will continue to grow into more and more functions around us. AI will hence become a bigger part of our society. And thereby AI will become a bigger part of us. Next to our supposedly essential co-existence with biological life on and within us (think gut microbes &lt;sup&gt;&lt;a href=&quot;#user-content-fn-9&quot; id=&quot;user-content-fnref-9&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;, but also the ecosystem), we will also become more machine. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;sounds-frightening&quot;&gt;Sounds frightening?&lt;/h2&gt;
&lt;p&gt;Well, first of all I would argue most of us are anyway already cyborgs to quite some extent. I know a lot of people that would have less trouble adapting to the removal of one of their legs than to the removal of their smartphone and computer.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-10&quot; id=&quot;user-content-fnref-10&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Secondly, I don’t see how this is qualitatively different from the many other dependencies that we have long accepted in our daily life. In the end, making use of all kind of tools to perform things faster, better, or easier, or achieve things out-of-reach is one key aspect of human civilization.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-11&quot; id=&quot;user-content-fnref-11&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; One could even argue that one of the main driving forces in human history is probably the desire to outgrow human limitations. Currently developed AI tools are only the next items on the list.&lt;/p&gt;
&lt;p&gt;AI might perform at superhuman level in some, typically very narrow, tasks. But AI is no other competing species, AI has no consciousness, no self-awareness, no personality, no own body. In my opinion we should avoid any panicking notion of &lt;strong&gt;“them or us”&lt;/strong&gt;. AI is a tool. And as such it will become part of &lt;em&gt;our&lt;/em&gt; intelligence.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-12&quot; id=&quot;user-content-fnref-12&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;*&lt;/strong&gt; You know what’s even has more general intelligence than a human? More humans collaborating. This blog post was edited and commented on by several other people. Thanks to Nicholas Renaud,&lt;/p&gt;
&lt;p&gt;[Tom Bakker]&lt;/p&gt;
&lt;p&gt;,&lt;/p&gt;
&lt;p&gt;[Maarten van Meersbergen]&lt;/p&gt;
&lt;p&gt;, Christiaan Meijer,&lt;/p&gt;
&lt;p&gt;[Johan Hidding]&lt;/p&gt;
&lt;p&gt;,&lt;/p&gt;
&lt;p&gt;[Patrick Bos]&lt;/p&gt;
&lt;p&gt;, Sophie Pfaff for making it a superhuman blog post.&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes:&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;#_ftnref1&quot;&gt;[10]&lt;/a&gt; &lt;a href=&quot;https://waitbutwhy.com/2017/04/neuralink.html&quot;&gt;In this blog post or I should better say BOOK&lt;/a&gt;, Tim Urban even thinks about humans becoming AI. This text is huge and also makes similar remarks than this post or Francois Chollet’s on why human intelligence needs to be understood as a collective phenomenon. Also contains a lot about the evolution of the brain, the brain itself, and a lot of other stuff worth reading! I am not entirely convinced by the narrative of a steady, continuous evolution of human intelligence, see &lt;a href=&quot;#_ftnref4&quot;&gt;[4]&lt;/a&gt; and &lt;a href=&quot;https://www.wired.com/2017/04/the-myth-of-a-superhuman-ai/&quot;&gt;wired article&lt;/a&gt;.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://en.wikipedia.org/wiki/Animal_husbandry&quot;&gt;animal husbandry&lt;/a&gt;. Or &lt;a href=&quot;https://www.annualreviews.org/doi/10.1146/annurev-animal-022516-022747&quot;&gt;[MacHugh et al. 2017]&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Abacus&quot;&gt;abacus&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;Many of the key ideas behind today’s AI methods come from the 1980s, but there simply wasn’t enough computational power and data to reveal their full potential at that time. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-5&quot;&gt;
&lt;p&gt;If you can even call it understanding! &lt;a href=&quot;#user-content-fnref-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-6&quot;&gt;
&lt;p&gt;There are many different neural networks used to classify and interpret images. The sticker was designed to work with five neural networks with are widely known and recognized in the field if AI (inceptionv3, resnet50, xception, VGG16, and VGG19). This doesn’t mean that the sticker will necessarily fool every AI tool out there. But since virtually all image-based neural networks are built on the same principles (the most relevant part probably being: stacking many convolutional neural network layers), one can safely assume that all those network will be vulnerable to this or similar attempts. See also other blog posts on this, such as &lt;a href=&quot;https://gizmodo.com/this-simple-sticker-can-trick-neural-networks-into-thin-1821735479&quot;&gt;this one&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-6&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-7&quot;&gt;
&lt;p&gt;The man behind Keras, one of the most used machine-learning, deep-learning software tools! &lt;a href=&quot;#user-content-fnref-7&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 6&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-8&quot;&gt;
&lt;p&gt;See for instance &lt;a href=&quot;https://aeon.co/ideas/the-body-is-the-missing-link-for-truly-intelligent-machines&quot;&gt;this blog post&lt;/a&gt; on the role of having a body for becoming intelligent as we understand it. &lt;a href=&quot;#user-content-fnref-8&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 7&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-9&quot;&gt;
&lt;p&gt;There is are more and more reasons to believe that the huge amounts of microbes living in and on our body have tremendous effects on not only our health, but also our mental condition. See for instance &lt;a href=&quot;https://www.theguardian.com/science/2019/feb/04/gut-bacteria-mental-health-depression-study&quot;&gt;guardian article&lt;/a&gt;, &lt;a href=&quot;https://www.scientificamerican.com/article/the-tantalizing-links-between-gut-microbes-and-the-brain/&quot;&gt;scientific american article&lt;/a&gt;, &lt;a href=&quot;https://www.theepochtimes.com/whats-in-your-belly-affects-whats-in-your-head-link-found-between-schizophrenia-gut-bacteria-study-says_2803526.html&quot;&gt;epoch times article&lt;/a&gt;.&lt;br&gt;
Mice, for example were shown to be become more anxious, or more adventurous depending on the microbes in their guts &lt;a href=&quot;https://www.apa.org/monitor/2012/09/gut-feeling&quot;&gt;https://www.apa.org/monitor/2012/09/gut-feeling&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-9&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 8&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-10&quot;&gt;
&lt;p&gt;And that by itself is nothing new either. Because the same is true for many other tools, only that those happen to not be digital or AI related. I would also more easily adapt to a life without one leg than to life without my glasses… &lt;a href=&quot;#user-content-fnref-10&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 9&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-11&quot;&gt;
&lt;p&gt;Going far beyond individual capabilities by collaborating and interacting seems typical for humans, but it is of course also find in many other biological life forms. Think of animal flocks, or of extremely collective life forms such as ants or termites. &lt;a href=&quot;#user-content-fnref-11&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 10&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-12&quot;&gt;
&lt;p&gt;Again, I am not saying that the current, rapid rise of AI tools will not cause serious problems! It can probably with good right be called a “disruptive” technology and could lead to serious problems in many labor markets, but also in decision making. But it will not become the next human. Current AI technologies have virtually nothing to do with science-fiction like conscious AI. But I plan to do another blog post on that… &lt;a href=&quot;#user-content-fnref-12&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 11&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><pubDate>Mon, 04 Mar 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;#demystifyAI series&lt;/strong&gt; (this small series aims at putting important AI-related aspects into perspective)&lt;/p&gt;
&lt;p&gt;Why you shouldn’t be afraid of AI tools occasionally performing &lt;em&gt;&lt;strong&gt;superhuman&lt;/strong&gt;&lt;/em&gt; in some tasks. And why &lt;strong&gt;you&lt;/strong&gt; are the true superhuman being.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iVaxGnagIZ6i2haK1ZH1LQ-86ec2227.DNLl_96q_Z1rf5WU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Superhuman performance is nothing rare. Here: humans forming a “superhuman” tower. Photo by Alessandra Pezzotta, published under CC BY license.&lt;/p&gt;
&lt;p&gt;I started my first hands-on training in machine learning and AI right after the GO matches between alpha go and Lee Sedol. At that time, it still felt a bit like a miracle to me. Not the shear fact that a computer would beat a world leading go player, but more the way it played and surprised the professional commentators.&lt;/p&gt;
&lt;p&gt;That was 3 years ago and the news were full of the “rise of AI” and the new area of superhuman AI. I had the feeling that a lot of that was silly, but at the same time I had not enough in-depth knowledge on AI to prove some wild claims to be wrong.&lt;/p&gt;
&lt;p&gt;I guess over time it just became a bit too much for me. If you sit in the wrong social media bubble, &lt;strong&gt;it must feel as if Superhuman AIs are already taking over&lt;/strong&gt; the world. A recent headline I saw in a bigger newspaper was &lt;em&gt;“Superhuman’ robots will outstrip mankind within 50 years, warns AI expert”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Yeah. Sure…&lt;/p&gt;
&lt;h2 id=&quot;superhuman-so-what&quot;&gt;Superhuman? So what!&lt;/h2&gt;
&lt;p&gt;So here’s the thing. &lt;em&gt;&lt;strong&gt;Superhuman&lt;/strong&gt;&lt;/em&gt; apparently sounds like something special, like science fiction that has become real. It absolutely is not. It only means “above”, “over”, “beyond”, “better than” a human. And if you think about it for a second, this is something entirely ordinary. We make use of superhuman powers since thousands of years!&lt;/p&gt;
&lt;p&gt;Humans started domesticating animals more than 10.000 years ago.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; And this was often not primarily to get meat, but to make use of their &lt;em&gt;&lt;strong&gt;superhuman&lt;/strong&gt;&lt;/em&gt; powers. Dogs would have superhuman smell and hearing. Oxen or horses were used for their superhuman strength.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1190&quot; height=&quot;530&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_G3vAyVSVlYS3BapnW-Og3g-ebe36034.Xbenv8M4_Z2hP3sa.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;718&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ai8XN0GpjdROoqQyiMhwEQ-8c6efd60.ChzIttnF_ZmELIm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1. There is a long history of using animals for their superhuman powers. Top: Ancient picture of oxen, dogs (“Painter of the burial chamber of Sennedjem”, ca. 1200 BCE, &lt;a href=&quot;https://en.wikipedia.org/wiki/File:Maler%5C_der%5C_Grabkammer%5C_des%5C_Sennudem%5C_001.jpg&quot;&gt;https://en.wikipedia.org/wiki/File:Maler\_der\_Grabkammer\_des\_Sennudem\_001.jpg&lt;/a&gt; Bottom: Image from a Krater depicting an ancient boar hunt, 550BC, British Museum, &lt;a href=&quot;https://en.wikipedia.org/wiki/File:Boar%5C_Hunting.jpg&quot;&gt;https://en.wikipedia.org/wiki/File:Boar\_Hunting.jpg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Yes, true. Those aspects wouldn’t touch our holiest humans-only domain: cognitive tasks! But here as well, &lt;em&gt;&lt;strong&gt;superhuman&lt;/strong&gt;&lt;/em&gt; might be little more than an over-used buzzword.&lt;/p&gt;
&lt;p&gt;Take the development of “writing” for instance. This can be seen as a way to externalize knowledge or memories. Also a diverse set of tools to help humans to do calculations have a long history, going back thousands of years.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Electronic calculators have long beaten our modest capabilities to doing calculations (quickly). And yet, nowadays nobody would look at one of them and feel the terror of being beaten by a machine!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_C3CUR9YuXawj_MwVQOTmEw-ad584207.CLDIhQA9_1TvdaN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2. Olivetti Programma 101, 1965–1971, Museo nazionale della scienza e della tecnologia Leonardo da Vinci, Milano, Creative Commons Attribution-Share Alike 4.0 International license. ( &lt;a href=&quot;https://en.wikipedia.org/wiki/File:Olivetti%5C_Programma%5C_101%5C_-%5C_Museo%5C_scienza%5C_e%5C_tecnologia%5C_Milano.jpg&quot;&gt;https://en.wikipedia.org/wiki/File:Olivetti\_Programma\_101\_-\_Museo\_scienza\_e\_tecnologia\_Milano.jpg&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;But let’s finally quick jump to today. Now, with the help of modern computers and algorithms, AI finally seems to be ahead of us in an ever increasing number of tasks! And that’s true. Current computers are fast enough to produce amazing results using modern or semi-modern algorithms or methods.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-3&quot; id=&quot;user-content-fnref-3&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Computers now can beat us in the most classical board games (GO, chess). They correctly classify pictures, spoken and written language, and to some extent can drive a car. Amazing stuff. And those developments have quite an impact already. And they for sure will have far more impact in the near future. But the way the adjective &lt;strong&gt;superhuman&lt;/strong&gt; is used in those contexts is often heavily misleading.&lt;/p&gt;
&lt;h2 id=&quot;ai-savantism&quot;&gt;AI savantism&lt;/h2&gt;
&lt;p&gt;Until today, all, really &lt;strong&gt;all&lt;/strong&gt; AI and machine-learning tools and products are only superhuman in one or few very specific aspects. Not much difference to the historic examples given above.&lt;/p&gt;
&lt;p&gt;Intelligence and learning are very complex concepts. Projecting the isolated performance in only one single, restricted area onto a “general” concept of intelligence or learning, will nearly always lead to wrong and often ridiculous conclusions. Such entirely wrong predictions were made based on early AI successes in the 1960s and then later in the 1980s. And I am convinced that we see something very similar happening in recent years.[4]&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“In from three to eight years we will have a machine with the general intelligence of an average human being.”&lt;br&gt;
Marvin Minsky, 1970 in Life Magazine (though he believed to be misquoted here…)&lt;/p&gt;
&lt;p&gt;“machines will be capable, within twenty years, of doing any work a man can do”,&lt;br&gt;
H.A. Simon, 1965&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Along the same lines, a very nice 2017 article in the magazine &lt;em&gt;Wired&lt;/em&gt; made very clear that describing intelligence as an one-dimensional characteristic is the wrong way to go. They also make a strong case against a linear ladder-like evolution towards high, human intelligence.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Intelligence is not a single dimension, so ‘smarter than humans’ is a meaningless concept.”&lt;br&gt;
&lt;a href=&quot;https://www.wired.com/2017/04/the-myth-of-a-superhuman-ai/&quot;&gt;Wired, 2017&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am not saying that there is no threat for certain parts of the job markets. Just as the industrial revolution(s), and later phase of automation has already made many jobs obsolete, this is very likely to happen through AI-based applications as well. Maybe even more rapidly and drastically. And there are huge issues with AI algorithms being applied improperly or being given too much trust at important positions (e.g. deciding about loans, assurances etc.).&lt;/p&gt;
&lt;p&gt;But the mere ability to perform superhuman in &lt;strong&gt;ONE&lt;/strong&gt; thing, shouldn’t spark too much terror. No matter how long we train their neural networks, alpha Zero and his brothers and sisters will never learn why we play a board game at all. Or how to leave the building when the fire alarm goes off. It is only trained to understand &lt;sup&gt;&lt;a href=&quot;#user-content-fn-5&quot; id=&quot;user-content-fnref-5&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; one narrow interpretation of a 19x19 grid with black and white stones on it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;692&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3b6qyqxxy22iS-2mK75WJg-73b33427.ZY2C727K_61kXc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 3. Alpha Zero can outplay any human go player easily. But anything that is not a typical go situation, even if it’s within the limited 19-by-19 grid horizon, it won’t get. Both board situations depicted here will mean the same to the AI: ‘100% black wins, white to resign’. Illustration by Florian Huber, can be reused under the CC BY license&lt;/p&gt;
&lt;p&gt;How little current AI tools are able to generalize, and how restricted their trained capabilities are, becomes evident if we look at so called “adversarial examples”. In essence, these are examples that were specifically designed to trick AI tools. The same way optical illusions reveal a lot about how we humans perceive the world, adversarial examples give us a good sense of how AI tools work. One of the earlier examples that became widely known in the AI community was a technique to add a specifically designed but imperceptible (imperceptible to humans that is) signal to an image which would result in an entirely wrong classification of the image by the respective neural network (Figure X).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;407&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_14bg7Qj-2BHR96ebKjbKOQ-07acef95.SNv5QOhe_Z2mvHaH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4. An adversarial example from 2015 which became quite popular. Here an image of a panda is altered by adding a specific, but imperceptible signal on top. To the human eye the picture obviously remains a panda, while the neural network suddenly is convinced that the picture shows a gibbon. Figure adapted from [Goodfellow, Shlens, Szegedy, 2015].&lt;/p&gt;
&lt;p&gt;A more recent example reveals the AI’s very limited “understanding of the world” even more strikingly. A group of AI researchers designed a sticker that will trick a neural network to believe it sees a toaster. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-6&quot; id=&quot;user-content-fnref-6&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; This example is surprisingly robust and works for many standard neural networks used for image interpretation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Figure 5&lt;/strong&gt; / Youtube-movie. More recent adversarial examples. The authors of &lt;a href=&quot;https://arxiv.org/pdf/1712.09665.pdf&quot;&gt;this paper&lt;/a&gt; designed a sticker that will trick a typical neural network used on images to believe it sees a toaster.&lt;/p&gt;
&lt;p&gt;Every AI technique that hits the market right now is of the most extreme form of &lt;strong&gt;hyper-savantism&lt;/strong&gt;. Very good at one thing. Terrible at practically anything else. Let them be mono-superhuman then. It will still never make them truly super-human.&lt;/p&gt;
&lt;h2 id=&quot;collective-intelligence&quot;&gt;Collective intelligence&lt;/h2&gt;
&lt;p&gt;A much more meaningful concept of “superhuman” lies in the power of collective and symbiotic phenomena. This is also how Francois Chollet &lt;sup&gt;&lt;a href=&quot;#user-content-fn-7&quot; id=&quot;user-content-fnref-7&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; describes it in his &lt;a href=&quot;https://medium.com/@francois.chollet/the-impossibility-of-intelligence-explosion-5be4a9eda6ec&quot;&gt;fantastic blog post on the same topic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The baseline here is: You know what has more general intelligence than a human? &lt;strong&gt;More humans collaborating!&lt;/strong&gt;&lt;br&gt;
Following his arguments, human intelligence and learning are concepts that cannot be understood by looking at individual brain power, but are tightly linked to collective and collaborative interactions and human civilization or society as a whole.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Most of our intelligence is not in our brain, it is externalized as our civilization”&lt;br&gt;
Francois Chollet (in his &lt;a href=&quot;https://medium.com/@francois.chollet/the-impossibility-of-intelligence-explosion-5be4a9eda6ec.&quot;&gt;blog post&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;844&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ouXj6qH779t7p_Ziw1r-Ug-a2bb8c5e.DjZieqmS_2qnwGD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 6: Human intelligence cannot be thought as an isolated, individual brain. Our tools, surroundings, and our society are part of us. We are hence all truly superhuman beings! Illustration by Florian Huber, can be reused under the CC BY license.&lt;/p&gt;
&lt;p&gt;More than ever we rely on knowledge, expertise, and skills of other human beings in our daily life. We rely on superhuman bodies of knowledge collected and processed over countless generations. We rely on complex societal constructs, on a sophisticated educational and health care system, etc. As human beings, we cannot be described by only looking at our individual brain. What we are, what we do, and what we think is inextricably linked with our body, our surroundings, and the society around us.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-8&quot; id=&quot;user-content-fnref-8&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;AI tools, agents, methods will continue to grow into more and more functions around us. AI will hence become a bigger part of our society. And thereby AI will become a bigger part of us. Next to our supposedly essential co-existence with biological life on and within us (think gut microbes &lt;sup&gt;&lt;a href=&quot;#user-content-fn-9&quot; id=&quot;user-content-fnref-9&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;, but also the ecosystem), we will also become more machine. &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;sounds-frightening&quot;&gt;Sounds frightening?&lt;/h2&gt;
&lt;p&gt;Well, first of all I would argue most of us are anyway already cyborgs to quite some extent. I know a lot of people that would have less trouble adapting to the removal of one of their legs than to the removal of their smartphone and computer.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-10&quot; id=&quot;user-content-fnref-10&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Secondly, I don’t see how this is qualitatively different from the many other dependencies that we have long accepted in our daily life. In the end, making use of all kind of tools to perform things faster, better, or easier, or achieve things out-of-reach is one key aspect of human civilization.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-11&quot; id=&quot;user-content-fnref-11&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; One could even argue that one of the main driving forces in human history is probably the desire to outgrow human limitations. Currently developed AI tools are only the next items on the list.&lt;/p&gt;
&lt;p&gt;AI might perform at superhuman level in some, typically very narrow, tasks. But AI is no other competing species, AI has no consciousness, no self-awareness, no personality, no own body. In my opinion we should avoid any panicking notion of &lt;strong&gt;“them or us”&lt;/strong&gt;. AI is a tool. And as such it will become part of &lt;em&gt;our&lt;/em&gt; intelligence.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-12&quot; id=&quot;user-content-fnref-12&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;*&lt;/strong&gt; You know what’s even has more general intelligence than a human? More humans collaborating. This blog post was edited and commented on by several other people. Thanks to Nicholas Renaud,&lt;/p&gt;
&lt;p&gt;[Tom Bakker]&lt;/p&gt;
&lt;p&gt;,&lt;/p&gt;
&lt;p&gt;[Maarten van Meersbergen]&lt;/p&gt;
&lt;p&gt;, Christiaan Meijer,&lt;/p&gt;
&lt;p&gt;[Johan Hidding]&lt;/p&gt;
&lt;p&gt;,&lt;/p&gt;
&lt;p&gt;[Patrick Bos]&lt;/p&gt;
&lt;p&gt;, Sophie Pfaff for making it a superhuman blog post.&lt;/p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes:&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;#_ftnref1&quot;&gt;[10]&lt;/a&gt; &lt;a href=&quot;https://waitbutwhy.com/2017/04/neuralink.html&quot;&gt;In this blog post or I should better say BOOK&lt;/a&gt;, Tim Urban even thinks about humans becoming AI. This text is huge and also makes similar remarks than this post or Francois Chollet’s on why human intelligence needs to be understood as a collective phenomenon. Also contains a lot about the evolution of the brain, the brain itself, and a lot of other stuff worth reading! I am not entirely convinced by the narrative of a steady, continuous evolution of human intelligence, see &lt;a href=&quot;#_ftnref4&quot;&gt;[4]&lt;/a&gt; and &lt;a href=&quot;https://www.wired.com/2017/04/the-myth-of-a-superhuman-ai/&quot;&gt;wired article&lt;/a&gt;.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://en.wikipedia.org/wiki/Animal_husbandry&quot;&gt;animal husbandry&lt;/a&gt;. Or &lt;a href=&quot;https://www.annualreviews.org/doi/10.1146/annurev-animal-022516-022747&quot;&gt;[MacHugh et al. 2017]&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;Such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Abacus&quot;&gt;abacus&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-3&quot;&gt;
&lt;p&gt;Many of the key ideas behind today’s AI methods come from the 1980s, but there simply wasn’t enough computational power and data to reveal their full potential at that time. &lt;a href=&quot;#user-content-fnref-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-5&quot;&gt;
&lt;p&gt;If you can even call it understanding! &lt;a href=&quot;#user-content-fnref-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-6&quot;&gt;
&lt;p&gt;There are many different neural networks used to classify and interpret images. The sticker was designed to work with five neural networks with are widely known and recognized in the field if AI (inceptionv3, resnet50, xception, VGG16, and VGG19). This doesn’t mean that the sticker will necessarily fool every AI tool out there. But since virtually all image-based neural networks are built on the same principles (the most relevant part probably being: stacking many convolutional neural network layers), one can safely assume that all those network will be vulnerable to this or similar attempts. See also other blog posts on this, such as &lt;a href=&quot;https://gizmodo.com/this-simple-sticker-can-trick-neural-networks-into-thin-1821735479&quot;&gt;this one&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-6&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-7&quot;&gt;
&lt;p&gt;The man behind Keras, one of the most used machine-learning, deep-learning software tools! &lt;a href=&quot;#user-content-fnref-7&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 6&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-8&quot;&gt;
&lt;p&gt;See for instance &lt;a href=&quot;https://aeon.co/ideas/the-body-is-the-missing-link-for-truly-intelligent-machines&quot;&gt;this blog post&lt;/a&gt; on the role of having a body for becoming intelligent as we understand it. &lt;a href=&quot;#user-content-fnref-8&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 7&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-9&quot;&gt;
&lt;p&gt;There is are more and more reasons to believe that the huge amounts of microbes living in and on our body have tremendous effects on not only our health, but also our mental condition. See for instance &lt;a href=&quot;https://www.theguardian.com/science/2019/feb/04/gut-bacteria-mental-health-depression-study&quot;&gt;guardian article&lt;/a&gt;, &lt;a href=&quot;https://www.scientificamerican.com/article/the-tantalizing-links-between-gut-microbes-and-the-brain/&quot;&gt;scientific american article&lt;/a&gt;, &lt;a href=&quot;https://www.theepochtimes.com/whats-in-your-belly-affects-whats-in-your-head-link-found-between-schizophrenia-gut-bacteria-study-says_2803526.html&quot;&gt;epoch times article&lt;/a&gt;.&lt;br&gt;
Mice, for example were shown to be become more anxious, or more adventurous depending on the microbes in their guts &lt;a href=&quot;https://www.apa.org/monitor/2012/09/gut-feeling&quot;&gt;https://www.apa.org/monitor/2012/09/gut-feeling&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-9&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 8&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-10&quot;&gt;
&lt;p&gt;And that by itself is nothing new either. Because the same is true for many other tools, only that those happen to not be digital or AI related. I would also more easily adapt to a life without one leg than to life without my glasses… &lt;a href=&quot;#user-content-fnref-10&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 9&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-11&quot;&gt;
&lt;p&gt;Going far beyond individual capabilities by collaborating and interacting seems typical for humans, but it is of course also find in many other biological life forms. Think of animal flocks, or of extremely collective life forms such as ants or termites. &lt;a href=&quot;#user-content-fnref-11&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 10&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-12&quot;&gt;
&lt;p&gt;Again, I am not saying that the current, rapid rise of AI tools will not cause serious problems! It can probably with good right be called a “disruptive” technology and could lead to serious problems in many labor markets, but also in decision making. But it will not become the next human. Current AI technologies have virtually nothing to do with science-fiction like conscious AI. But I plan to do another blog post on that… &lt;a href=&quot;#user-content-fnref-12&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 11&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_G3vAyVSVlYS3BapnW-Og3g-ebe36034.Xbenv8M4.jpeg" medium="image"/><author>Florian Huber</author></item><item><title>fairifying ewatercycle</title><link>https://blog2.esciencecenter.nl/posts/2019-02-05---fairifying-ewatercycle</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-02-05---fairifying-ewatercycle</guid><description>&lt;h2 id=&quot;towards-reproducible-science-and-better-flooding-forecasts&quot;&gt;Towards reproducible science and better flooding forecasts&lt;/h2&gt;
&lt;p&gt;Growing populations, economies, industries and urbanization are increasing the demand for water, while extreme weather spurred by climate change is projected to lead to major changes in water availability. With more and more people moving into delta areas, more and more people become vulnerable to flooding. Naturally this increases the demand for flood forecasts. If we know that a flood is likely to happen in 10 days time, is there still something we can do to prevent this flood from actually happening? Can we take preparations to mitigate the effect of the flood?&lt;/p&gt;
&lt;p&gt;This was exactly the aim of the &lt;a href=&quot;https://www.esciencecenter.nl/project/ewatercycle&quot;&gt;eWaterCycle&lt;/a&gt; project: to predict flood and drought events 10 days in advance, worldwide and at unprecedentedly high resolution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ERr4etL8sVWeV98P0oKrzQ-c9858abf.CHJ2pQUM_ZzuF4t.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;reproducibility&quot;&gt;Reproducibility&lt;/h3&gt;
&lt;p&gt;While the complex system created in the &lt;a href=&quot;https://www.esciencecenter.nl/project/ewatercycle&quot;&gt;eWaterCycle project&lt;/a&gt; worked for us, it was extremely difficult for someone else to set up such a system on their own computing resources, let alone to go back, rerun and validate our experiments. This is where the &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;FAIR — Findability, Accessibility, Interoperability, and Reusability —&lt;/a&gt; principles come in, to serve as a guide around these issues, thereby maximizing the added value of the research. It is important to note that these principles not only apply to ‘data’ in the conventional sense, but also to how this data came to be. The issues identified by the FAIR principles are precisely the ones we tried to solve in the &lt;a href=&quot;https://www.esciencecenter.nl/project/fairifying-ewatercycle&quot;&gt;FAIRifying eWaterCycle project&lt;/a&gt; ¹.&lt;/p&gt;
&lt;p&gt;In this project we created a fully reproducible (low resolution) version of the eWaterCycle forecast. The lessons learned will be taken into account moving forward in developing a &lt;em&gt;community multi-model environment for hydrological experiments and analyses&lt;/em&gt; in the follow up project &lt;a href=&quot;https://www.esciencecenter.nl/project/ewatercycle-ii&quot;&gt;eWaterCycle II,&lt;/a&gt; but will also benefit the design of the European Open Science Cloud for Research.&lt;/p&gt;
&lt;p&gt;In our effort to &lt;em&gt;FAIRify&lt;/em&gt; the system, we relied heavily on both &lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt; containerization and the &lt;a href=&quot;https://www.commonwl.org/&quot;&gt;Common Workflow Language (CWL&lt;/a&gt;). Containerization provides a solution to the problem of how to get software to run reliably when moved from one computing environment to another. CWL is a specification for describing analysis workflows and tools in a way that makes them portable and scalable across a variety of software and hardware environments, from workstations to cluster, cloud, and high performance computing (HPC) environments. In addition, CWL is able to provide provenance through &lt;a href=&quot;https://zenodo.org/record/1966881#.XFMIj-2CrJE&quot;&gt;CWLProv&lt;/a&gt;. Workflow provenance saves information about the workflow specification, input and outputs, and executions of the workflow, so that experiments can be verified and reproduced in a precise manner.&lt;/p&gt;
&lt;p&gt;It is technically very hard to connect CWL workflow steps in a cyclic manner. Cyclic workflows are much better controlled using a specialized workflow engine for cycling systems. We therefore opted to only describe the workflow steps in CWL and control the workflow using such a workflow engine. Here we used &lt;a href=&quot;https://cylc.github.io/cylc/&quot;&gt;Cylc&lt;/a&gt;: a workflow engine that orchestrates distributed suites of interdependent cyclingtasks that may continue to run indefinitely. Cylc was originally developed for operational environmental forecasting. Having its roots in environmental forecasting, Cylc provides handy features for these kind of operational forecasts such as &lt;em&gt;clock triggers&lt;/em&gt;, &lt;em&gt;event triggers&lt;/em&gt;, &lt;em&gt;retry handlers&lt;/em&gt; for individual tasks, and more. This allows us for example to wait for input data to be available on the server, retry specific tasks when they failed, or choose alternative paths of the workflow.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;522&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TKU5owFizUEh9ta86rUxKg-b0c7c767.BO1OzBOP_YxvQh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Technical overview FAIRified eWaterCycle system&lt;/p&gt;
&lt;p&gt;In essence, the forecast system (picture above) performs a couple of steps that are executed every day:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Downloading of input data from various sources&lt;/li&gt;
&lt;li&gt;Pre-processing of input data&lt;/li&gt;
&lt;li&gt;Performing data-assimilation and running an ensemble of hydrological forecasts&lt;/li&gt;
&lt;li&gt;Post-processing of model output&lt;/li&gt;
&lt;li&gt;Uploading of the results and provenance to the archive&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;
&lt;p&gt;Using a combination of the CWL standard for workflows, Cylc as a workflow engine, and Docker software containers, we were able to create a fully reproducible (low resolution) version of the eWaterCycle forecast. Output is stored at OneData and made available for analysis in a notebook environment. In addition the hydrological forecasts are visualized in a &lt;a href=&quot;http://forecast.ewatercycle.org/&quot;&gt;web application&lt;/a&gt;. The forecast is running daily now, without any manual intervention and runs on supercomputers without changes needed to the software installed on the system.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1904&quot; height=&quot;996&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_HdGRzjc3O7xInSY9x_vfhQ-99cb942e.BWqJlyFl_Z1KfYQs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interactive forecast&lt;/p&gt;
&lt;p&gt;During this project we learned some valuable lessons that we plan to integrate into our larger &lt;a href=&quot;https://www.ewatercycle.org/&quot;&gt;eWaterCycle II projec&lt;/a&gt; t, with a focus on FAIR hydrological modelling. Some of the lessons learned during this small project include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You cannot build a FAIR system build on un-FAIR components. Sometimes you have no control on e.g. the FAIRness of your input data.&lt;/li&gt;
&lt;li&gt;Improving FAIRness of datasets from third parties is very difficult without involving the original author of such data. Involving authors of these datasets is often not feasible within the scope of small projects.&lt;/li&gt;
&lt;li&gt;Metadata and licensing information for datasets is often unclear or sometimes non-existent.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://onedata.org/#/home&quot;&gt;OneData system&lt;/a&gt; is a really nice concept, but could be further improved by adding some key usability features like file sharing, persistent storage with identifiers, authentication and authorization services and execution services for standards-based workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eWaterCycle/forecast-docker&quot;&gt;Code and instructions available at eWaterCycle github&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This project is funded as part of the &lt;a href=&quot;https://www.eoscpilot.eu/&quot;&gt;European Open Science Cloud for Research Pilot (EOSCPilot) Project&lt;/a&gt; and received funding from the European Commission’s Horizon 2020 research and innovation programme under the Grant Agreement no 739563.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Tue, 05 Feb 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;towards-reproducible-science-and-better-flooding-forecasts&quot;&gt;Towards reproducible science and better flooding forecasts&lt;/h2&gt;
&lt;p&gt;Growing populations, economies, industries and urbanization are increasing the demand for water, while extreme weather spurred by climate change is projected to lead to major changes in water availability. With more and more people moving into delta areas, more and more people become vulnerable to flooding. Naturally this increases the demand for flood forecasts. If we know that a flood is likely to happen in 10 days time, is there still something we can do to prevent this flood from actually happening? Can we take preparations to mitigate the effect of the flood?&lt;/p&gt;
&lt;p&gt;This was exactly the aim of the &lt;a href=&quot;https://www.esciencecenter.nl/project/ewatercycle&quot;&gt;eWaterCycle&lt;/a&gt; project: to predict flood and drought events 10 days in advance, worldwide and at unprecedentedly high resolution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ERr4etL8sVWeV98P0oKrzQ-c9858abf.CHJ2pQUM_ZzuF4t.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;reproducibility&quot;&gt;Reproducibility&lt;/h3&gt;
&lt;p&gt;While the complex system created in the &lt;a href=&quot;https://www.esciencecenter.nl/project/ewatercycle&quot;&gt;eWaterCycle project&lt;/a&gt; worked for us, it was extremely difficult for someone else to set up such a system on their own computing resources, let alone to go back, rerun and validate our experiments. This is where the &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;FAIR — Findability, Accessibility, Interoperability, and Reusability —&lt;/a&gt; principles come in, to serve as a guide around these issues, thereby maximizing the added value of the research. It is important to note that these principles not only apply to ‘data’ in the conventional sense, but also to how this data came to be. The issues identified by the FAIR principles are precisely the ones we tried to solve in the &lt;a href=&quot;https://www.esciencecenter.nl/project/fairifying-ewatercycle&quot;&gt;FAIRifying eWaterCycle project&lt;/a&gt; ¹.&lt;/p&gt;
&lt;p&gt;In this project we created a fully reproducible (low resolution) version of the eWaterCycle forecast. The lessons learned will be taken into account moving forward in developing a &lt;em&gt;community multi-model environment for hydrological experiments and analyses&lt;/em&gt; in the follow up project &lt;a href=&quot;https://www.esciencecenter.nl/project/ewatercycle-ii&quot;&gt;eWaterCycle II,&lt;/a&gt; but will also benefit the design of the European Open Science Cloud for Research.&lt;/p&gt;
&lt;p&gt;In our effort to &lt;em&gt;FAIRify&lt;/em&gt; the system, we relied heavily on both &lt;a href=&quot;https://www.docker.com/&quot;&gt;docker&lt;/a&gt; containerization and the &lt;a href=&quot;https://www.commonwl.org/&quot;&gt;Common Workflow Language (CWL&lt;/a&gt;). Containerization provides a solution to the problem of how to get software to run reliably when moved from one computing environment to another. CWL is a specification for describing analysis workflows and tools in a way that makes them portable and scalable across a variety of software and hardware environments, from workstations to cluster, cloud, and high performance computing (HPC) environments. In addition, CWL is able to provide provenance through &lt;a href=&quot;https://zenodo.org/record/1966881#.XFMIj-2CrJE&quot;&gt;CWLProv&lt;/a&gt;. Workflow provenance saves information about the workflow specification, input and outputs, and executions of the workflow, so that experiments can be verified and reproduced in a precise manner.&lt;/p&gt;
&lt;p&gt;It is technically very hard to connect CWL workflow steps in a cyclic manner. Cyclic workflows are much better controlled using a specialized workflow engine for cycling systems. We therefore opted to only describe the workflow steps in CWL and control the workflow using such a workflow engine. Here we used &lt;a href=&quot;https://cylc.github.io/cylc/&quot;&gt;Cylc&lt;/a&gt;: a workflow engine that orchestrates distributed suites of interdependent cyclingtasks that may continue to run indefinitely. Cylc was originally developed for operational environmental forecasting. Having its roots in environmental forecasting, Cylc provides handy features for these kind of operational forecasts such as &lt;em&gt;clock triggers&lt;/em&gt;, &lt;em&gt;event triggers&lt;/em&gt;, &lt;em&gt;retry handlers&lt;/em&gt; for individual tasks, and more. This allows us for example to wait for input data to be available on the server, retry specific tasks when they failed, or choose alternative paths of the workflow.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;522&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TKU5owFizUEh9ta86rUxKg-b0c7c767.BO1OzBOP_YxvQh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Technical overview FAIRified eWaterCycle system&lt;/p&gt;
&lt;p&gt;In essence, the forecast system (picture above) performs a couple of steps that are executed every day:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Downloading of input data from various sources&lt;/li&gt;
&lt;li&gt;Pre-processing of input data&lt;/li&gt;
&lt;li&gt;Performing data-assimilation and running an ensemble of hydrological forecasts&lt;/li&gt;
&lt;li&gt;Post-processing of model output&lt;/li&gt;
&lt;li&gt;Uploading of the results and provenance to the archive&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;
&lt;p&gt;Using a combination of the CWL standard for workflows, Cylc as a workflow engine, and Docker software containers, we were able to create a fully reproducible (low resolution) version of the eWaterCycle forecast. Output is stored at OneData and made available for analysis in a notebook environment. In addition the hydrological forecasts are visualized in a &lt;a href=&quot;http://forecast.ewatercycle.org/&quot;&gt;web application&lt;/a&gt;. The forecast is running daily now, without any manual intervention and runs on supercomputers without changes needed to the software installed on the system.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1904&quot; height=&quot;996&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_HdGRzjc3O7xInSY9x_vfhQ-99cb942e.BWqJlyFl_Z1KfYQs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interactive forecast&lt;/p&gt;
&lt;p&gt;During this project we learned some valuable lessons that we plan to integrate into our larger &lt;a href=&quot;https://www.ewatercycle.org/&quot;&gt;eWaterCycle II projec&lt;/a&gt; t, with a focus on FAIR hydrological modelling. Some of the lessons learned during this small project include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You cannot build a FAIR system build on un-FAIR components. Sometimes you have no control on e.g. the FAIRness of your input data.&lt;/li&gt;
&lt;li&gt;Improving FAIRness of datasets from third parties is very difficult without involving the original author of such data. Involving authors of these datasets is often not feasible within the scope of small projects.&lt;/li&gt;
&lt;li&gt;Metadata and licensing information for datasets is often unclear or sometimes non-existent.&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://onedata.org/#/home&quot;&gt;OneData system&lt;/a&gt; is a really nice concept, but could be further improved by adding some key usability features like file sharing, persistent storage with identifiers, authentication and authorization services and execution services for standards-based workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eWaterCycle/forecast-docker&quot;&gt;Code and instructions available at eWaterCycle github&lt;/a&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;This project is funded as part of the &lt;a href=&quot;https://www.eoscpilot.eu/&quot;&gt;European Open Science Cloud for Research Pilot (EOSCPilot) Project&lt;/a&gt; and received funding from the European Commission’s Horizon 2020 research and innovation programme under the Grant Agreement no 739563.&lt;/li&gt;
&lt;/ol&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_ERr4etL8sVWeV98P0oKrzQ-c9858abf.CHJ2pQUM.jpeg" medium="image"/><author>Ronald van Haren</author></item><item><title>enTangleD</title><link>https://blog2.esciencecenter.nl/posts/2019-01-30---entangled</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-01-30---entangled</guid><description>&lt;h2 id=&quot;a-bi-directional-literate-programming-tool&quot;&gt;a bi-directional Literate Programming tool&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;864&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tzRmbKxAvetqVm7znEY8Sw-a155b882.BMgx7_Hg_1qJEd9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;© Alessandra Sequeira, Entanglement ( &lt;a href=&quot;http://sinapsisequeira.blogspot.com/&quot;&gt;http://sinapsisequeira.blogspot.com/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;I present &lt;em&gt;enTangleD&lt;/em&gt; (&lt;a href=&quot;https://entangled.github.io/&quot;&gt;github.io pages&lt;/a&gt;), a tool for pain free literate programming.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8eN_G62FYBlXK3FUDIheAA-045cab11.ELYAvYF-_bPcHI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Donald Knuth&lt;/p&gt;
&lt;p&gt;There’s no way I can write about literate programming not starting at the source: Donald Knuth, the great master and chief, writer of “The Art of Computer Programming”, “Surreal Numbers” and inventor of &lt;em&gt;literate programming&lt;/em&gt;. He coined this term somewhat maliciously, thinking that “nobody wants to admit writing an &lt;em&gt;illiterate&lt;/em&gt; program”. So what is literate programming?&lt;/p&gt;
&lt;p&gt;Knuth considers code as a way of communicating with a computer. As you write code you are &lt;em&gt;teaching&lt;/em&gt; the computer how to perform a certain task. However, many times when you’re programming, you’re not just teaching the computer. You are also teaching your (very human) peers. This is why so many teachers drone on about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clean code&lt;/li&gt;
&lt;li&gt;simple solutions&lt;/li&gt;
&lt;li&gt;extensive documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Literate programming goes much further than that. A literate program is a program that can be read as a work of literature. Specifically, we write the &lt;em&gt;entire&lt;/em&gt; program as a document (be it Markdown, Org-mode or LaTeX) explaining what the program does and how this is implemented in plain English. The actual implementation, in whatever language you may prefer, is sprinkled around in the form of code blocks. For those who are familiar with Jupyter notebooks, or the notebook interface to Mathematica: notebooks can be considered a form of literate programming, but there are differences which we will discuss later on.&lt;/p&gt;
&lt;p&gt;An example of how a woven literate program looks can be found in my numerical code to compute cosmological structure formation &lt;a href=&quot;https://jhidding.github.io/adhesion-code/&quot;&gt;“Computing the adhesion model using C++ and CGAL”&lt;/a&gt; (&lt;a href=&quot;https://doi.org/10.5281/zenodo.1477536&quot;&gt;DOI:10.5281/zenodo.1477535&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;382&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pctd-x7jhr6iOnt-QmCIeg-6a025195.CSCilTSa_ZjyUAB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of woven literate code.&lt;/p&gt;
&lt;p&gt;The principles underlying literate programming, merely prudent in most circumstances, become essential once we consider writing and publishing code for the scientific community, for several reasons.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;scientific meticulousness:&lt;/strong&gt; Scientific works are supposed to be held to exacting standards. These standards are upheld by systems of peer-review and demands of precise reporting of methodology. These standards are often surprisingly lax when it concerns the use of software. This problem is for a large part addressed by the “Open Science” movement in general, stimulating the use of open source software in science. Still, even if code is open source, this does not mean that this code can be easily understood.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;epistemology:&lt;/strong&gt; Epistemology is the theory of &lt;em&gt;knowledge&lt;/em&gt; and part of the philosophy of science. When can we say we know something? When was the theory of relativity born? Was it when Einstein woke up after having a dream about trains, mirrors and flashlights, or after he successfully wrote his theory down in such a way that one other person could understand it? Think about it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;programming literacy:&lt;/strong&gt; Scientists create a lot of computer code, but are, in general, not professionally trained programmers. This increases the need for exposure to each others code. Literate programming stimulates other people to actually read your code, while you’ll have an easier time reading other people’s code. This interaction should make better programmers of all of us.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Knuth developed a system called &lt;em&gt;WEB&lt;/em&gt; for annotating TeX with the relations between the different code blocks. &lt;em&gt;WEB&lt;/em&gt; came with two tools: &lt;em&gt;tangle&lt;/em&gt; and &lt;em&gt;weave&lt;/em&gt;. The &lt;em&gt;tangle&lt;/em&gt; tool takes the literary source, parses the &lt;em&gt;WEB&lt;/em&gt; references therein and pastes together traditional source files that can be subsequently compiled into a working binary. &lt;em&gt;Weave&lt;/em&gt; converts the (annotated) TeX source into a secondary TeX that is ready for type setting and publishing. We will refer to these programs as the &lt;em&gt;tangler&lt;/em&gt; and &lt;em&gt;weaver&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There is a practical issue with this form of literate programming. We’re having the true source code in a different place than the compiler, debugger and IDE think it is, and this breaks the usual development cycle. If one were to develop a system for literate programming today, it would look a bit different. I will now explain a Markdown based system and present a tool called &lt;em&gt;enTangleD&lt;/em&gt; that makes the development cycle of literate programs a smoother experience.&lt;/p&gt;
&lt;h2 id=&quot;literate-programming-in-markdown&quot;&gt;Literate programming in Markdown&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;840&quot; height=&quot;616&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Vcp-iI0RG5iIsgZxrSK4AA-3fd6c180.dg4GqzLX_Z296FII.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;© Alessandra Sequeira, Inner Foliage ( &lt;a href=&quot;http://sinapsisequeira.blogspot.com/&quot;&gt;http://sinapsisequeira.blogspot.com/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt; has become a standard way of expressing text documents (without there being a standard and moreover many different flavours). Markdown can be converted to HTML, LaTeX and many other formats. Everyone’s favourite tool for markdown conversion is of course &lt;a href=&quot;https://pandoc.org/&quot;&gt;PanDoc&lt;/a&gt;. One guiding principle in the following design is that the resulting Markdown is parsable by PanDoc. We will be denoting code blocks using three back ticks on the opening and closing line of the code block like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, Amsterdam!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One way of denoting the programming language of the code block is by extending the opening back ticks with an accepted abbreviation of the language. In the above example we tell the document formatter that the given source code is written in Python. For our purpose this syntax is not flexible enough. We want to extend the code block meta-data with other properties. PanDoc supports attaching a CSS class, id and attributes to code blocks using curly brackets:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;` {.py file&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this system of literate programming the tangler will extract this code block and write it to a file `hello.py`. More complicated programs can be built using a system of references. Keeping with Python, it is considered good form to enclose a main script using the following `if`-statement:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;` {.py file&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hello2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; __name__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;__main__&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can define the body anywhere else in the document:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;` {.py &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;body}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, Universe!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The tangler will then combine these code blocks into a single file:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; __name__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;__main__&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, Universe!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The system of references allows us to decompose a program into literary parts, putting the code in a didactic narrative.&lt;/p&gt;
&lt;h2 id=&quot;entangled&quot;&gt;enTangleD&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;840&quot; height=&quot;622&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_s724R83u1MtKlug5I9wL0w-ac82b154.8hz4Hk6x_Z1l3BSb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;© Alessandra Sequeira, Inner Shadow ( &lt;a href=&quot;http://sinapsisequeira.blogspot.com/&quot;&gt;http://sinapsisequeira.blogspot.com/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;As I mentioned before, there is a practical problem with developing software in the way I described above. All our code is in one or more Markdown files. If we want to build it, we first have to tangle, then, if we work with a compiled language, compile, hope that nothing goes wrong and run. But what if we have compiler errors, or worse, the program compiles but doesn’t give the expected output? We then enter the usual edit-compile-debug cycle. The source files that we work on were generated by the tangler and it makes no sense editing them directly. In comes &lt;em&gt;enTangleD&lt;/em&gt;! The D stands for &lt;em&gt;daemon&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;enTangleD&lt;/em&gt; monitors both the Markdown and the generated source files for changes. If a source file changes, the corresponding code blocks in the Markdown are updated accordingly, and the other way around. To make this work, &lt;em&gt;enTangleD&lt;/em&gt; writes the source code with commented markers telling the daemon where in the Markdown file the code comes from.&lt;/p&gt;
&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;There exist alternatives to our Markdown based literate programming model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jupyter:&lt;/strong&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt; gives you an interactive notebook environment for any language that has a Jupyter kernel written (there are many). Advantages are: interactivity, inline graphing, good for experimentation. Disadvantages: Jupyter notebooks do not play well with git version control, the interactivity also doesn’t play well with compiled languages and lastly provenance is not guaranteed since the order of cell-execution is not fixed. Jupyter is awesome, but it is not perfect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;literate Haskell:&lt;/strong&gt; Haskell programmers write their papers in &lt;em&gt;literate Haskell&lt;/em&gt;. This is very fine for Haskell. &lt;em&gt;enTangleD&lt;/em&gt; is completely language agnostic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pweave&lt;/strong&gt;, &lt;strong&gt;Weave.jl&lt;/strong&gt;, &lt;strong&gt;Racket Scribble&lt;/strong&gt;, etc: these are all language specific.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Org-mode:&lt;/strong&gt; if your editor of choice is Emacs and your document is only supposed to be opened by like-minded people, Org-mode is the awesomest;). Still, it does not support bi-directional tangling.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself!&lt;/h2&gt;
&lt;p&gt;Try &lt;em&gt;enTangleD&lt;/em&gt; for yourself! &lt;em&gt;enTangleD&lt;/em&gt; is written in Haskell and source code is hosted on &lt;a href=&quot;https://github.com/jhidding/entangled&quot;&gt;GitHub&lt;/a&gt;. The repository also contains an example Markdown file containing source code for an over-engineered C++ implementation of &lt;a href=&quot;https://jhidding.github.io/enTangleD/99-bottles.html&quot;&gt;“99 bottles of beer”,&lt;/a&gt; and a small browser game called &lt;a href=&quot;https://jhidding.github.io/enTangleD/slasher.html&quot;&gt;“Slasher”&lt;/a&gt; which is &lt;a href=&quot;https://jhidding.github.io/enTangleD/elm-slasher.html&quot;&gt;implemented in Elm&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Wed, 30 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;a-bi-directional-literate-programming-tool&quot;&gt;a bi-directional Literate Programming tool&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;864&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tzRmbKxAvetqVm7znEY8Sw-a155b882.BMgx7_Hg_1qJEd9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;© Alessandra Sequeira, Entanglement ( &lt;a href=&quot;http://sinapsisequeira.blogspot.com/&quot;&gt;http://sinapsisequeira.blogspot.com/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;I present &lt;em&gt;enTangleD&lt;/em&gt; (&lt;a href=&quot;https://entangled.github.io/&quot;&gt;github.io pages&lt;/a&gt;), a tool for pain free literate programming.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8eN_G62FYBlXK3FUDIheAA-045cab11.ELYAvYF-_bPcHI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Donald Knuth&lt;/p&gt;
&lt;p&gt;There’s no way I can write about literate programming not starting at the source: Donald Knuth, the great master and chief, writer of “The Art of Computer Programming”, “Surreal Numbers” and inventor of &lt;em&gt;literate programming&lt;/em&gt;. He coined this term somewhat maliciously, thinking that “nobody wants to admit writing an &lt;em&gt;illiterate&lt;/em&gt; program”. So what is literate programming?&lt;/p&gt;
&lt;p&gt;Knuth considers code as a way of communicating with a computer. As you write code you are &lt;em&gt;teaching&lt;/em&gt; the computer how to perform a certain task. However, many times when you’re programming, you’re not just teaching the computer. You are also teaching your (very human) peers. This is why so many teachers drone on about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clean code&lt;/li&gt;
&lt;li&gt;simple solutions&lt;/li&gt;
&lt;li&gt;extensive documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Literate programming goes much further than that. A literate program is a program that can be read as a work of literature. Specifically, we write the &lt;em&gt;entire&lt;/em&gt; program as a document (be it Markdown, Org-mode or LaTeX) explaining what the program does and how this is implemented in plain English. The actual implementation, in whatever language you may prefer, is sprinkled around in the form of code blocks. For those who are familiar with Jupyter notebooks, or the notebook interface to Mathematica: notebooks can be considered a form of literate programming, but there are differences which we will discuss later on.&lt;/p&gt;
&lt;p&gt;An example of how a woven literate program looks can be found in my numerical code to compute cosmological structure formation &lt;a href=&quot;https://jhidding.github.io/adhesion-code/&quot;&gt;“Computing the adhesion model using C++ and CGAL”&lt;/a&gt; (&lt;a href=&quot;https://doi.org/10.5281/zenodo.1477536&quot;&gt;DOI:10.5281/zenodo.1477535&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;382&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pctd-x7jhr6iOnt-QmCIeg-6a025195.CSCilTSa_ZjyUAB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of woven literate code.&lt;/p&gt;
&lt;p&gt;The principles underlying literate programming, merely prudent in most circumstances, become essential once we consider writing and publishing code for the scientific community, for several reasons.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;scientific meticulousness:&lt;/strong&gt; Scientific works are supposed to be held to exacting standards. These standards are upheld by systems of peer-review and demands of precise reporting of methodology. These standards are often surprisingly lax when it concerns the use of software. This problem is for a large part addressed by the “Open Science” movement in general, stimulating the use of open source software in science. Still, even if code is open source, this does not mean that this code can be easily understood.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;epistemology:&lt;/strong&gt; Epistemology is the theory of &lt;em&gt;knowledge&lt;/em&gt; and part of the philosophy of science. When can we say we know something? When was the theory of relativity born? Was it when Einstein woke up after having a dream about trains, mirrors and flashlights, or after he successfully wrote his theory down in such a way that one other person could understand it? Think about it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;programming literacy:&lt;/strong&gt; Scientists create a lot of computer code, but are, in general, not professionally trained programmers. This increases the need for exposure to each others code. Literate programming stimulates other people to actually read your code, while you’ll have an easier time reading other people’s code. This interaction should make better programmers of all of us.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Knuth developed a system called &lt;em&gt;WEB&lt;/em&gt; for annotating TeX with the relations between the different code blocks. &lt;em&gt;WEB&lt;/em&gt; came with two tools: &lt;em&gt;tangle&lt;/em&gt; and &lt;em&gt;weave&lt;/em&gt;. The &lt;em&gt;tangle&lt;/em&gt; tool takes the literary source, parses the &lt;em&gt;WEB&lt;/em&gt; references therein and pastes together traditional source files that can be subsequently compiled into a working binary. &lt;em&gt;Weave&lt;/em&gt; converts the (annotated) TeX source into a secondary TeX that is ready for type setting and publishing. We will refer to these programs as the &lt;em&gt;tangler&lt;/em&gt; and &lt;em&gt;weaver&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There is a practical issue with this form of literate programming. We’re having the true source code in a different place than the compiler, debugger and IDE think it is, and this breaks the usual development cycle. If one were to develop a system for literate programming today, it would look a bit different. I will now explain a Markdown based system and present a tool called &lt;em&gt;enTangleD&lt;/em&gt; that makes the development cycle of literate programs a smoother experience.&lt;/p&gt;
&lt;h2 id=&quot;literate-programming-in-markdown&quot;&gt;Literate programming in Markdown&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;840&quot; height=&quot;616&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Vcp-iI0RG5iIsgZxrSK4AA-3fd6c180.dg4GqzLX_Z296FII.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;© Alessandra Sequeira, Inner Foliage ( &lt;a href=&quot;http://sinapsisequeira.blogspot.com/&quot;&gt;http://sinapsisequeira.blogspot.com/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt; has become a standard way of expressing text documents (without there being a standard and moreover many different flavours). Markdown can be converted to HTML, LaTeX and many other formats. Everyone’s favourite tool for markdown conversion is of course &lt;a href=&quot;https://pandoc.org/&quot;&gt;PanDoc&lt;/a&gt;. One guiding principle in the following design is that the resulting Markdown is parsable by PanDoc. We will be denoting code blocks using three back ticks on the opening and closing line of the code block like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, Amsterdam!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One way of denoting the programming language of the code block is by extending the opening back ticks with an accepted abbreviation of the language. In the above example we tell the document formatter that the given source code is written in Python. For our purpose this syntax is not flexible enough. We want to extend the code block meta-data with other properties. PanDoc supports attaching a CSS class, id and attributes to code blocks using curly brackets:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;` {.py file&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hello&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, World!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this system of literate programming the tangler will extract this code block and write it to a file `hello.py`. More complicated programs can be built using a system of references. Keeping with Python, it is considered good form to enclose a main script using the following `if`-statement:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;` {.py file&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hello2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; __name__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;__main__&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;body&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can define the body anywhere else in the document:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;` {.py &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;body}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, Universe!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The tangler will then combine these code blocks into a single file:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; __name__ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;__main__&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    print(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;Hello, Universe!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The system of references allows us to decompose a program into literary parts, putting the code in a didactic narrative.&lt;/p&gt;
&lt;h2 id=&quot;entangled&quot;&gt;enTangleD&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;840&quot; height=&quot;622&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_s724R83u1MtKlug5I9wL0w-ac82b154.8hz4Hk6x_Z1l3BSb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;© Alessandra Sequeira, Inner Shadow ( &lt;a href=&quot;http://sinapsisequeira.blogspot.com/&quot;&gt;http://sinapsisequeira.blogspot.com/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;As I mentioned before, there is a practical problem with developing software in the way I described above. All our code is in one or more Markdown files. If we want to build it, we first have to tangle, then, if we work with a compiled language, compile, hope that nothing goes wrong and run. But what if we have compiler errors, or worse, the program compiles but doesn’t give the expected output? We then enter the usual edit-compile-debug cycle. The source files that we work on were generated by the tangler and it makes no sense editing them directly. In comes &lt;em&gt;enTangleD&lt;/em&gt;! The D stands for &lt;em&gt;daemon&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;enTangleD&lt;/em&gt; monitors both the Markdown and the generated source files for changes. If a source file changes, the corresponding code blocks in the Markdown are updated accordingly, and the other way around. To make this work, &lt;em&gt;enTangleD&lt;/em&gt; writes the source code with commented markers telling the daemon where in the Markdown file the code comes from.&lt;/p&gt;
&lt;h2 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;There exist alternatives to our Markdown based literate programming model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jupyter:&lt;/strong&gt; &lt;a href=&quot;https://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt; gives you an interactive notebook environment for any language that has a Jupyter kernel written (there are many). Advantages are: interactivity, inline graphing, good for experimentation. Disadvantages: Jupyter notebooks do not play well with git version control, the interactivity also doesn’t play well with compiled languages and lastly provenance is not guaranteed since the order of cell-execution is not fixed. Jupyter is awesome, but it is not perfect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;literate Haskell:&lt;/strong&gt; Haskell programmers write their papers in &lt;em&gt;literate Haskell&lt;/em&gt;. This is very fine for Haskell. &lt;em&gt;enTangleD&lt;/em&gt; is completely language agnostic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pweave&lt;/strong&gt;, &lt;strong&gt;Weave.jl&lt;/strong&gt;, &lt;strong&gt;Racket Scribble&lt;/strong&gt;, etc: these are all language specific.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Org-mode:&lt;/strong&gt; if your editor of choice is Emacs and your document is only supposed to be opened by like-minded people, Org-mode is the awesomest;). Still, it does not support bi-directional tangling.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself!&lt;/h2&gt;
&lt;p&gt;Try &lt;em&gt;enTangleD&lt;/em&gt; for yourself! &lt;em&gt;enTangleD&lt;/em&gt; is written in Haskell and source code is hosted on &lt;a href=&quot;https://github.com/jhidding/entangled&quot;&gt;GitHub&lt;/a&gt;. The repository also contains an example Markdown file containing source code for an over-engineered C++ implementation of &lt;a href=&quot;https://jhidding.github.io/enTangleD/99-bottles.html&quot;&gt;“99 bottles of beer”,&lt;/a&gt; and a small browser game called &lt;a href=&quot;https://jhidding.github.io/enTangleD/slasher.html&quot;&gt;“Slasher”&lt;/a&gt; which is &lt;a href=&quot;https://jhidding.github.io/enTangleD/elm-slasher.html&quot;&gt;implemented in Elm&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_8eN_G62FYBlXK3FUDIheAA-045cab11.ELYAvYF-.jpeg" medium="image"/><author>Johan Hidding</author></item><item><title>c++ compile-time exceptions</title><link>https://blog2.esciencecenter.nl/posts/2019-01-23---c-compile-time-exceptions</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-01-23---c-compile-time-exceptions</guid><description>&lt;h2 id=&quot;debugging-c-templates-should-be-less-surreal-and-horrible&quot;&gt;Debugging C++ templates should be less surreal and horrible&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2100&quot; height=&quot;1881&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TExYOrq8ehGu-dpzBiD0sQ-453b61e8.BUGFrNNm_Z1wXjy9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;C++ programmers in their natural habitat, building awesome things and staring at walls of error text.&lt;/p&gt;
&lt;p&gt;A C++ template error can be pages long, really dense and basically horrible. Often, they are not at all helpful for users of a library and you have to ==ask the developers for help==. Developers will often be able to filter or modify the error message to be far more productive to their users. In this post, I propose adding &lt;em&gt;compile-time exceptions&lt;/em&gt; to C++ that will allow the developer to implement custom compiler errors for these cases.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with C++ templates: these allow you to do &lt;a href=&quot;https://en.wikipedia.org/wiki/Generic_programming&quot;&gt;generic programming&lt;/a&gt;, meaning you can write functions without immediately specifying types, for instance a mathematical function that you want to be able to use with regular floats, double precision or even integers.&lt;/p&gt;
&lt;h2 id=&quot;implicit-failure-through-implementation&quot;&gt;Implicit failure through implementation&lt;/h2&gt;
&lt;p&gt;Reading through Scott Meyers’ timeless classic &lt;em&gt;Effective C++&lt;/em&gt;, I was struck by the following template in Item 45, especially the templated constructor:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  explicit &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;realPtr);  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { … }  &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const { return heldPtr; }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;heldPtr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This piece of code will allow you to initialize a &lt;code&gt;SmartPtr&lt;/code&gt; by any “compatible type”. This for instance means derived types, as Meyers illustrates:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Middle:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Bottom:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With regular pointers you can do:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pt1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pct2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pt1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;SmartPtr&lt;/code&gt; from the template above thus emulates the behavior of regular pointers, because thanks to the templated constructor you can do&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spct2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The trick is that this will compile only if the implicit conversion from e.g. a &lt;code&gt;Middle&lt;/code&gt; pointer to a &lt;code&gt;Top&lt;/code&gt; pointer is allowed. This is, of course, the case, since a &lt;code&gt;Middle&lt;/code&gt; pointer &lt;strong&gt;is&lt;/strong&gt; a &lt;code&gt;Top&lt;/code&gt; pointer (plus extra &lt;code&gt;Middle&lt;/code&gt; stuff).&lt;/p&gt;
&lt;p&gt;However, if the implicit conversion is not allowed, say if you try to initialize a child class object by a parent class one like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the compiler will complain as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compile_fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize a member subobject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ~~~~~~~~~~~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compile_fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; instantiation &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function template specialization &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; requested here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; compileth not&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error generated&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Welcome to C++ templates! What the hell am I seeing here? Bytecode?!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_F5Z9hOuRxMz3C9jktqZPhw-58556d0e.CyRPPh5Z_1LS7R0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looks perfectly normal to me…. ( © wardyboy400, CC BY 2.0 )&lt;/p&gt;
&lt;p&gt;Debug messages should not be this ridiculously hard to read, should they? I honestly sometimes laugh hysterically at these kinds of errors, especially when they go on for many more lines, as they often do. &lt;strong&gt;It’s just too surreal&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now, to be honest, once you succeeded in cutting through the clutter, this is a more or less clear message:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize a member subobject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [obtuse hint that the error was caused by the template specialization &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the constructor]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, to make it maybe a bit more understandable to an English speaker:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;You&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot construct a &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; using a &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; constructor, because this will lead to an error, namely&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize a member subobject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;compile-time-exceptions-make-intent-explicit&quot;&gt;Compile-time exceptions: make intent explicit&lt;/h2&gt;
&lt;p&gt;The above “English” exception still does not convey one crucial fact: that the developer meant for this error to happen.&lt;/p&gt;
&lt;p&gt;And for a specific reason: they want to emulate the behavior of regular pointers. A user of the &lt;code&gt;SmartPtr&lt;/code&gt; should not be able to use this class in other ways.&lt;/p&gt;
&lt;p&gt;But this fact is hidden from sight by the compiler messages that — while maybe helpful to developers and certainly very complete— are not at all helpful to end-users (not to mention the fact that the developer probably is an end-user themselves as well).&lt;/p&gt;
&lt;p&gt;To help the end-user, a far better compiler error message would therefore be very similar to the one used for the normal pointers, for instance:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize an object &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or a bit more explicit:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize an object &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, because &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is not implicitly convertible to &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the compiler can detect these errors, which apparently it can, as evidenced by the error message, then why not allow the programmer to make use of this?&lt;/p&gt;
&lt;p&gt;This would make the generic error message &lt;strong&gt;context specific&lt;/strong&gt;, as in the above example: the developer adds their &lt;strong&gt;intention&lt;/strong&gt;, the way the developer meant for the class to be used. This way, the user of the template does not have to browse documentation, nor parse huge template-error messages. Rather, they can fix the error and get back to work, as I must assume error messages were meant.&lt;/p&gt;
&lt;p&gt;This line of thinking lead me to my eureka-moment: &lt;em&gt;&lt;strong&gt;C++ should have compile-time exceptions&lt;/strong&gt;&lt;/em&gt;! Consider the following (bold face) modification of our constructor:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; …&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;U&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  compile_except(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;E2064&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    compile_cerr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;error: cannot initialize a &apos;SmartPtr&amp;#x3C;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&gt;&apos; with an rvalue of type &apos;SmartPtr&amp;#x3C;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&gt;&apos;, because &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot; is not implicitly convertible to &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    compile_fail;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; …&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This syntax would mean that if a specific exception occurs during compilation of the template — specifically in this case error &lt;code&gt;E2064&lt;/code&gt;, a code which comes from &lt;a href=&quot;http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/devwin32/cppcompmessagespart_xml.html&quot;&gt;this list of errors&lt;/a&gt; — the compiler enters the block, where it is met by some compiler specific syntax that allows for the developer to specifically express their intent.&lt;/p&gt;
&lt;p&gt;Ok, so maybe we don’t need a special compile time output stream (it should rather be &lt;a href=&quot;http://fmtlib.net/&quot;&gt;fmt&lt;/a&gt; based!), but you get the point. For brevity, I stream-print the types &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt; directly, by which I mean their names should be printed.&lt;/p&gt;
&lt;p&gt;This whole approach assumes the developer will know the pitfalls of their API and can provide such an improved error message. In the example given above, I think this is indeed a better message and I’m sure developers can come up with many other good examples of error messages that keep frustrating their users. &lt;strong&gt;Please let me know if you do, I’d love to make a follow-up post with the most interesting examples.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So, almost immediately after I came up with this, I was already enjoying (in my mind) the fame and riches that making this proposal would obviously bring me. I had never heard of this idea before, and indeed some Google searching (no further than page 1, of course, it’s still just a blog post…) did not lead to comparable ideas (I welcome your scorn, derison and ridicule if I missed something obvious).&lt;/p&gt;
&lt;p&gt;However, while writing this post, I suddenly realized to my dismay that maybe we don’t need compile-time exceptions, at least for this use case.&lt;/p&gt;
&lt;p&gt;We have Concepts now.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1704&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zFlz1mv04ReyHwp41ZfRkA-f646b13f.SsILrQfU_20xUzP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Why, Concepts, why? I thought we were friends…&lt;/p&gt;
&lt;h2 id=&quot;well-defined-failure-concepts-to-the-rescue&quot;&gt;Well defined failure: Concepts to the rescue?&lt;/h2&gt;
&lt;p&gt;In C++20, the same class behavior can be programmed with a &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot;&gt;Concept&lt;/a&gt;, which also makes the code’s intent more explicit. It makes the compilation fail at an earlier point: at the first line of the template, where the template argument is immediately tested for compatibility with the template class, instead of relying on the implementation (the incompatible pointer assignment) to fail compilation.&lt;/p&gt;
&lt;p&gt;For instance, in our example, one could add a &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot;&gt;Derived concept, as found on the cppreference page on Concepts&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;concept &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;U&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This concept can then be used to constrain the allowed template types of our constructor by replacing &lt;code&gt;typename&lt;/code&gt; with our Concept:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { … }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Really nice, expressive syntax. I don’t want any old type &lt;code&gt;U&lt;/code&gt;, I only want those that are derived from &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The template now only compiles for types &lt;code&gt;U&lt;/code&gt; that are derived from &lt;code&gt;T&lt;/code&gt; (as it did before, but now because I say so, not because the language happens to). When you try to do otherwise, you get an error message that should be able to make this crystal clear for you! And all will be well.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://godbolt.org/z/Syth7G&quot;&gt;The experimental Concepts-enabled clang on Compiler Explorer outputs this&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; no viable conversion from &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; compileth not&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; candidate constructor (the implicit copy constructor) not viable&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; no known conversion from &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for 1st argument&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; candidate constructor (the implicit move constructor) not viable&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; no known conversion from &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&amp;#x26;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for 1st argument&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; candidate template ignored&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; constraints not satisfied [with &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; initialize this held ptr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; because &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluated to false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; because &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;Bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluated to false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;concept &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;U&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error generated&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Compiler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; returned&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait a minute… this isn’t crystal clear at all. Concepts, why do you pain me so?!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;992&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_o9zM89M99LDuS5zbd3a8kw-57dba38c.Cep_s90H_Z1F3ryC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Halt! Definitely something’s off here…&lt;/p&gt;
&lt;p&gt;Granted, it gives a nice subtle reminder that I forgot to add a templated move constructor and that there’s also a non-templated implicit copy constructor (which, by the way, Scott Meyers also reminds you of in Item 45).&lt;/p&gt;
&lt;p&gt;But honestly, this was not the feedback I was hoping for as a user. That feedback arrives only in the fourth note… of five!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; because &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluated to false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I do like this sentence, especially that it starts with “because” (even though the “evaluated to false” is a bit awkward, but I’m nitpicking). But there is still too much noise in here, at least for an end user.&lt;/p&gt;
&lt;h2 id=&quot;what-about-static_assert&quot;&gt;What about static_assert?&lt;/h2&gt;
&lt;p&gt;[Lourens Veen]&lt;/p&gt;
&lt;p&gt;reminded me that &lt;code&gt;static_assert&lt;/code&gt; should not go unmentioned here. Indeed, this specific case can also be made more explicit using &lt;code&gt;static_assert&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  static_assert(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;U is not derived from T!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach has a number of its own issues though:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It still gives us two error messages (&lt;a href=&quot;https://godbolt.org/z/1GzJ-8&quot;&gt;see this implementation on Compiler Explorer&lt;/a&gt;): first the one about the pointer, which is triggered by the &lt;code&gt;heldPtr&lt;/code&gt; initialization, and then the &lt;code&gt;static_assert&lt;/code&gt; message.&lt;/li&gt;
&lt;li&gt;I don’t know how this could be combined with Concepts. If I understand correctly, neither Concepts nor the related Constraints have a body where a &lt;code&gt;static_assert&lt;/code&gt; could go.&lt;/li&gt;
&lt;li&gt;We still cannot use it exactly the way we want, since the message of a static_assert must be a string literal, so we can’t dynamically display the types that are being passed as &lt;code&gt;U&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;More importantly, in general: not all errors can be represented by a boolean condition, which is necessary for the &lt;code&gt;static_assert&lt;/code&gt;. Syntax errors for instance, by definition cannot be used, since we cannot define the correct syntax for them! If we could, they wouldn’t be syntax errors anymore…&lt;/p&gt;
&lt;h2 id=&quot;the-case-for-compile-time-exceptions&quot;&gt;The case for compile-time exceptions&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;667&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_82PZb6UjPKU4PeckpD0yiA-38a32103.7FBwotYb_Z12hNcL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’m not by far a C++ guru, and also not a computer scientist, so it would take me a long time to come up with more examples and corner cases of what compile-time exceptions would mean. I’m hoping other C++ experts can chime in here.&lt;/p&gt;
&lt;p&gt;Also, probably the name won’t stick. I guess what I’m describing here aren’t really exceptions (you can’t reasonably recover from them, for instance), but rather customized error messages. However, triggering them feels like catching an exception. Perhaps there is a different name for this hybrid thing.&lt;/p&gt;
&lt;p&gt;Nevertheless, I do know that debugging C++, especially the templated kind, can be hell. There is just too much noise to wade through in the general case.&lt;/p&gt;
&lt;p&gt;A library developer will often have a very good idea of the kind of things that are expected and that can go wrong. Why not use this knowledge to make life easier for library users?&lt;/p&gt;
&lt;p&gt;Why can’t I just get a compile error that simply says “ &lt;code&gt;Error: argument to copy ctor for SmartPtr&amp;#x3C;T&gt; can only be SmartPtr&amp;#x3C;U&gt; when U is derived from T, but it’s not&lt;/code&gt; ”? Or something like that.&lt;/p&gt;
&lt;p&gt;For this to work, compiler errors would need to be properly classified, named, detectable with not too much effort, etcetera. I have no idea whether this is currently the case. So another question to you (especially if you’re a compiler expert): &lt;em&gt;&lt;strong&gt;are compile errors defined in such a way (i.e. strict enough, in the language itself) that they could be implemented as specific exceptions?&lt;/strong&gt;&lt;/em&gt; Could they even be defined like that?&lt;/p&gt;
&lt;p&gt;Be sure to leave your comments below or on &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/aj3ayo/c_compiletime_exceptions_debugging_templates/&quot;&gt;Reddit&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/egpbos/status/1088152720740110342&quot;&gt;Twitter&lt;/a&gt;!&lt;/p&gt;</description><pubDate>Wed, 23 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;debugging-c-templates-should-be-less-surreal-and-horrible&quot;&gt;Debugging C++ templates should be less surreal and horrible&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2100&quot; height=&quot;1881&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TExYOrq8ehGu-dpzBiD0sQ-453b61e8.BUGFrNNm_Z1wXjy9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;C++ programmers in their natural habitat, building awesome things and staring at walls of error text.&lt;/p&gt;
&lt;p&gt;A C++ template error can be pages long, really dense and basically horrible. Often, they are not at all helpful for users of a library and you have to ==ask the developers for help==. Developers will often be able to filter or modify the error message to be far more productive to their users. In this post, I propose adding &lt;em&gt;compile-time exceptions&lt;/em&gt; to C++ that will allow the developer to implement custom compiler errors for these cases.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with C++ templates: these allow you to do &lt;a href=&quot;https://en.wikipedia.org/wiki/Generic_programming&quot;&gt;generic programming&lt;/a&gt;, meaning you can write functions without immediately specifying types, for instance a mathematical function that you want to be able to use with regular floats, double precision or even integers.&lt;/p&gt;
&lt;h2 id=&quot;implicit-failure-through-implementation&quot;&gt;Implicit failure through implementation&lt;/h2&gt;
&lt;p&gt;Reading through Scott Meyers’ timeless classic &lt;em&gt;Effective C++&lt;/em&gt;, I was struck by the following template in Item 45, especially the templated constructor:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  explicit &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;realPtr);  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { … }  &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; const { return heldPtr; }  &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;heldPtr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This piece of code will allow you to initialize a &lt;code&gt;SmartPtr&lt;/code&gt; by any “compatible type”. This for instance means derived types, as Meyers illustrates:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Middle:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; Bottom:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; public &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With regular pointers you can do:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pt1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pct2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pt1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;SmartPtr&lt;/code&gt; from the template above thus emulates the behavior of regular pointers, because thanks to the templated constructor you can do&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Top&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spct2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt1;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The trick is that this will compile only if the implicit conversion from e.g. a &lt;code&gt;Middle&lt;/code&gt; pointer to a &lt;code&gt;Top&lt;/code&gt; pointer is allowed. This is, of course, the case, since a &lt;code&gt;Middle&lt;/code&gt; pointer &lt;strong&gt;is&lt;/strong&gt; a &lt;code&gt;Top&lt;/code&gt; pointer (plus extra &lt;code&gt;Middle&lt;/code&gt; stuff).&lt;/p&gt;
&lt;p&gt;However, if the implicit conversion is not allowed, say if you try to initialize a child class object by a parent class one like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt1 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the compiler will complain as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compile_fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize a member subobject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ~~~~~~~~~~~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;compile_fail&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cpp&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; instantiation &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; function template specialization &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; requested here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; compileth not&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error generated&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Welcome to C++ templates! What the hell am I seeing here? Bytecode?!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_F5Z9hOuRxMz3C9jktqZPhw-58556d0e.CyRPPh5Z_1LS7R0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looks perfectly normal to me…. ( © wardyboy400, CC BY 2.0 )&lt;/p&gt;
&lt;p&gt;Debug messages should not be this ridiculously hard to read, should they? I honestly sometimes laugh hysterically at these kinds of errors, especially when they go on for many more lines, as they often do. &lt;strong&gt;It’s just too surreal&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now, to be honest, once you succeeded in cutting through the clutter, this is a more or less clear message:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize a member subobject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [obtuse hint that the error was caused by the template specialization &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; the constructor]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, to make it maybe a bit more understandable to an English speaker:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;You&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot construct a &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; using a &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; constructor, because this will lead to an error, namely&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize a member subobject &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; *’.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;compile-time-exceptions-make-intent-explicit&quot;&gt;Compile-time exceptions: make intent explicit&lt;/h2&gt;
&lt;p&gt;The above “English” exception still does not convey one crucial fact: that the developer meant for this error to happen.&lt;/p&gt;
&lt;p&gt;And for a specific reason: they want to emulate the behavior of regular pointers. A user of the &lt;code&gt;SmartPtr&lt;/code&gt; should not be able to use this class in other ways.&lt;/p&gt;
&lt;p&gt;But this fact is hidden from sight by the compiler messages that — while maybe helpful to developers and certainly very complete— are not at all helpful to end-users (not to mention the fact that the developer probably is an end-user themselves as well).&lt;/p&gt;
&lt;p&gt;To help the end-user, a far better compiler error message would therefore be very similar to the one used for the normal pointers, for instance:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize an object &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or a bit more explicit:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cannot initialize an object &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; with an rvalue &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;of&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; type &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, because &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; is not implicitly convertible to &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the compiler can detect these errors, which apparently it can, as evidenced by the error message, then why not allow the programmer to make use of this?&lt;/p&gt;
&lt;p&gt;This would make the generic error message &lt;strong&gt;context specific&lt;/strong&gt;, as in the above example: the developer adds their &lt;strong&gt;intention&lt;/strong&gt;, the way the developer meant for the class to be used. This way, the user of the template does not have to browse documentation, nor parse huge template-error messages. Rather, they can fix the error and get back to work, as I must assume error messages were meant.&lt;/p&gt;
&lt;p&gt;This line of thinking lead me to my eureka-moment: &lt;em&gt;&lt;strong&gt;C++ should have compile-time exceptions&lt;/strong&gt;&lt;/em&gt;! Consider the following (bold face) modification of our constructor:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; …&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;U&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  compile_except(&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;E2064&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    compile_cerr &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;error: cannot initialize a &apos;SmartPtr&amp;#x3C;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&gt;&apos; with an rvalue of type &apos;SmartPtr&amp;#x3C;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&gt;&apos;, because &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot; is not implicitly convertible to &quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    compile_fail;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; …&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This syntax would mean that if a specific exception occurs during compilation of the template — specifically in this case error &lt;code&gt;E2064&lt;/code&gt;, a code which comes from &lt;a href=&quot;http://docs.embarcadero.com/products/rad_studio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/devwin32/cppcompmessagespart_xml.html&quot;&gt;this list of errors&lt;/a&gt; — the compiler enters the block, where it is met by some compiler specific syntax that allows for the developer to specifically express their intent.&lt;/p&gt;
&lt;p&gt;Ok, so maybe we don’t need a special compile time output stream (it should rather be &lt;a href=&quot;http://fmtlib.net/&quot;&gt;fmt&lt;/a&gt; based!), but you get the point. For brevity, I stream-print the types &lt;code&gt;T&lt;/code&gt; and &lt;code&gt;U&lt;/code&gt; directly, by which I mean their names should be printed.&lt;/p&gt;
&lt;p&gt;This whole approach assumes the developer will know the pitfalls of their API and can provide such an improved error message. In the example given above, I think this is indeed a better message and I’m sure developers can come up with many other good examples of error messages that keep frustrating their users. &lt;strong&gt;Please let me know if you do, I’d love to make a follow-up post with the most interesting examples.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So, almost immediately after I came up with this, I was already enjoying (in my mind) the fame and riches that making this proposal would obviously bring me. I had never heard of this idea before, and indeed some Google searching (no further than page 1, of course, it’s still just a blog post…) did not lead to comparable ideas (I welcome your scorn, derison and ridicule if I missed something obvious).&lt;/p&gt;
&lt;p&gt;However, while writing this post, I suddenly realized to my dismay that maybe we don’t need compile-time exceptions, at least for this use case.&lt;/p&gt;
&lt;p&gt;We have Concepts now.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1704&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_zFlz1mv04ReyHwp41ZfRkA-f646b13f.SsILrQfU_20xUzP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Why, Concepts, why? I thought we were friends…&lt;/p&gt;
&lt;h2 id=&quot;well-defined-failure-concepts-to-the-rescue&quot;&gt;Well defined failure: Concepts to the rescue?&lt;/h2&gt;
&lt;p&gt;In C++20, the same class behavior can be programmed with a &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot;&gt;Concept&lt;/a&gt;, which also makes the code’s intent more explicit. It makes the compilation fail at an earlier point: at the first line of the template, where the template argument is immediately tested for compatibility with the template class, instead of relying on the implementation (the incompatible pointer assignment) to fail compilation.&lt;/p&gt;
&lt;p&gt;For instance, in our example, one could add a &lt;a href=&quot;https://en.cppreference.com/w/cpp/language/constraints&quot;&gt;Derived concept, as found on the cppreference page on Concepts&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;concept &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;U&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This concept can then be used to constrain the allowed template types of our constructor by replacing &lt;code&gt;typename&lt;/code&gt; with our Concept:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other)&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) { … }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Really nice, expressive syntax. I don’t want any old type &lt;code&gt;U&lt;/code&gt;, I only want those that are derived from &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The template now only compiles for types &lt;code&gt;U&lt;/code&gt; that are derived from &lt;code&gt;T&lt;/code&gt; (as it did before, but now because I say so, not because the language happens to). When you try to do otherwise, you get an error message that should be able to make this crystal clear for you! And all will be well.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://godbolt.org/z/Syth7G&quot;&gt;The experimental Concepts-enabled clang on Compiler Explorer outputs this&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;20&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; no viable conversion from &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; spt2 &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(new &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; compileth not&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; candidate constructor (the implicit copy constructor) not viable&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; no known conversion from &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for 1st argument&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; candidate constructor (the implicit move constructor) not viable&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; no known conversion from &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; to &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&amp;#x26;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; for 1st argument&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; candidate template ignored&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; constraints not satisfied [with &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other) &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; initialize this held ptr&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; because &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluated to false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;19&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; because &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;Bottom&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluated to false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;concept &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;U&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; error generated&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Compiler&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; returned&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait a minute… this isn’t crystal clear at all. Concepts, why do you pain me so?!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;992&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_o9zM89M99LDuS5zbd3a8kw-57dba38c.Cep_s90H_Z1F3ryC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Halt! Definitely something’s off here…&lt;/p&gt;
&lt;p&gt;Granted, it gives a nice subtle reminder that I forgot to add a templated move constructor and that there’s also a non-templated implicit copy constructor (which, by the way, Scott Meyers also reminds you of in Item 45).&lt;/p&gt;
&lt;p&gt;But honestly, this was not the feedback I was hoping for as a user. That feedback arrives only in the fourth note… of five!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;11&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; note&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; because &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;‘&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Middle&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Bottom&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;’&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; evaluated to false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Derived&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ^&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I do like this sentence, especially that it starts with “because” (even though the “evaluated to false” is a bit awkward, but I’m nitpicking). But there is still too much noise in here, at least for an end user.&lt;/p&gt;
&lt;h2 id=&quot;what-about-static_assert&quot;&gt;What about static_assert?&lt;/h2&gt;
&lt;p&gt;[Lourens Veen]&lt;/p&gt;
&lt;p&gt;reminded me that &lt;code&gt;static_assert&lt;/code&gt; should not go unmentioned here. Indeed, this specific case can also be made more explicit using &lt;code&gt;static_assert&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;typename &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(const &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;SmartPtr&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; other)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; heldPtr(other&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  static_assert(std&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;is_base_of&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;T&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;U&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;value, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;U is not derived from T!&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach has a number of its own issues though:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It still gives us two error messages (&lt;a href=&quot;https://godbolt.org/z/1GzJ-8&quot;&gt;see this implementation on Compiler Explorer&lt;/a&gt;): first the one about the pointer, which is triggered by the &lt;code&gt;heldPtr&lt;/code&gt; initialization, and then the &lt;code&gt;static_assert&lt;/code&gt; message.&lt;/li&gt;
&lt;li&gt;I don’t know how this could be combined with Concepts. If I understand correctly, neither Concepts nor the related Constraints have a body where a &lt;code&gt;static_assert&lt;/code&gt; could go.&lt;/li&gt;
&lt;li&gt;We still cannot use it exactly the way we want, since the message of a static_assert must be a string literal, so we can’t dynamically display the types that are being passed as &lt;code&gt;U&lt;/code&gt; and &lt;code&gt;T&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;More importantly, in general: not all errors can be represented by a boolean condition, which is necessary for the &lt;code&gt;static_assert&lt;/code&gt;. Syntax errors for instance, by definition cannot be used, since we cannot define the correct syntax for them! If we could, they wouldn’t be syntax errors anymore…&lt;/p&gt;
&lt;h2 id=&quot;the-case-for-compile-time-exceptions&quot;&gt;The case for compile-time exceptions&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;667&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_82PZb6UjPKU4PeckpD0yiA-38a32103.7FBwotYb_Z12hNcL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’m not by far a C++ guru, and also not a computer scientist, so it would take me a long time to come up with more examples and corner cases of what compile-time exceptions would mean. I’m hoping other C++ experts can chime in here.&lt;/p&gt;
&lt;p&gt;Also, probably the name won’t stick. I guess what I’m describing here aren’t really exceptions (you can’t reasonably recover from them, for instance), but rather customized error messages. However, triggering them feels like catching an exception. Perhaps there is a different name for this hybrid thing.&lt;/p&gt;
&lt;p&gt;Nevertheless, I do know that debugging C++, especially the templated kind, can be hell. There is just too much noise to wade through in the general case.&lt;/p&gt;
&lt;p&gt;A library developer will often have a very good idea of the kind of things that are expected and that can go wrong. Why not use this knowledge to make life easier for library users?&lt;/p&gt;
&lt;p&gt;Why can’t I just get a compile error that simply says “ &lt;code&gt;Error: argument to copy ctor for SmartPtr&amp;#x3C;T&gt; can only be SmartPtr&amp;#x3C;U&gt; when U is derived from T, but it’s not&lt;/code&gt; ”? Or something like that.&lt;/p&gt;
&lt;p&gt;For this to work, compiler errors would need to be properly classified, named, detectable with not too much effort, etcetera. I have no idea whether this is currently the case. So another question to you (especially if you’re a compiler expert): &lt;em&gt;&lt;strong&gt;are compile errors defined in such a way (i.e. strict enough, in the language itself) that they could be implemented as specific exceptions?&lt;/strong&gt;&lt;/em&gt; Could they even be defined like that?&lt;/p&gt;
&lt;p&gt;Be sure to leave your comments below or on &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/aj3ayo/c_compiletime_exceptions_debugging_templates/&quot;&gt;Reddit&lt;/a&gt; or &lt;a href=&quot;https://twitter.com/egpbos/status/1088152720740110342&quot;&gt;Twitter&lt;/a&gt;!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_F5Z9hOuRxMz3C9jktqZPhw-58556d0e.CyRPPh5Z.jpeg" medium="image"/><author>Patrick Bos</author></item><item><title>dealing with dragons and monsters best practices for handling legacy code</title><link>https://blog2.esciencecenter.nl/posts/2019-01-09---dealing-with-dragons-and-monsters-best-practices-for-handling-legacy-code</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2019-01-09---dealing-with-dragons-and-monsters-best-practices-for-handling-legacy-code</guid><description>&lt;blockquote&gt;
&lt;p&gt;“So comes snow after fire, and even dragons have their endings.”&lt;br&gt;
― &lt;strong&gt;J.R.R. Tolkien,&lt;/strong&gt; &lt;a href=&quot;https://www.goodreads.com/work/quotes/1540236&quot;&gt;&lt;strong&gt;The Hobbit&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;712&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_frYHQLnu7557WfFq0j7L1w-0f8293f3.CyV4qt5o_2uriY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typical debugging session&lt;/p&gt;
&lt;p&gt;When I started my PhD in the field of &lt;a href=&quot;https://en.wikipedia.org/wiki/Computational_chemistry&quot;&gt;computational chemistry&lt;/a&gt; I was given the task of improving and contributing to different pieces of code in the infamous &lt;a href=&quot;https://en.wikipedia.org/wiki/Fortran#FORTRAN_77&quot;&gt;FORTRAN 77 standard&lt;/a&gt;. I gathered all my courage and spent several months banging my head against a wall of esoteric compilation errors trying to decipher the arcane arts of compiling and running legacy code.&lt;/p&gt;
&lt;p&gt;Back then the basic idea was to dig into all the blogs, documents and different Q&amp;#x26;A sites, then muddle through the code until it compiled. Subsequently, I put warnings for all the unfortunate souls that would have to deal with the spaghetti monster in the future, warning them to not touch this and that keyword under the threat of eternal damnation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then, I wondered: if dealing with legacy code is such a nightmare, why do we not throw away all the legacy code and start from scratch?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yes, legacy code is ugly, convoluted and sometimes it is indistinguishable from &lt;a href=&quot;https://en.wikipedia.org/wiki/Black_Speech&quot;&gt;black speech of Mordor&lt;/a&gt; (see for instance: &lt;em&gt;goto&lt;/em&gt;, &lt;em&gt;rewind&lt;/em&gt; and &lt;em&gt;common blocks&lt;/em&gt;**).** But, &lt;em&gt;in general scientific legacy code contains the tears, sweat and blood of researchers who have spent many days and nights implementing new features and fixing bugs&lt;/em&gt;. You can argue that all the knowledge lies within publications and therefore we can throw everything away and start from scratch, but as discussed in &lt;a href=&quot;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/&quot;&gt;this excellent post&lt;/a&gt;, the answer is more complex than that and we still need to produce working code while keeping the previous developments alive.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So, how do we then face legacy code while maintaining our sanity?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-quest&quot;&gt;The quest&lt;/h2&gt;
&lt;p&gt;Before embarking on any enterprise about maintaining/modernizing legacy code, let me tell you that on my experience the war against bad code is won battle by battle, one at a time, so be wise when choosing your battles. Experience will tell you what the most urgent issues are to fix, provided that you have experience on the code that you are working on. But since that is seldom the case, the first step to take is read as much as you can about the language/tool that you are going to use.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The time that you spend reading material related to your project’s programming languages, libraries, tools, etc. will pay you back many times in the future when you identify an issue and immediately know how to deal with it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you happened to run into a &lt;em&gt;C++&lt;/em&gt; legacy monster go and read &lt;a href=&quot;http://shop.oreilly.com/product/0636920033707.do&quot;&gt;&lt;em&gt;Effective modern C++&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt; On the other hand if you need to deal with &lt;em&gt;FORTRAN&lt;/em&gt;, I would recommend you to have a look at &lt;a href=&quot;https://global.oup.com/academic/product/modern-fortran-explained-9780198811893?cc=nl&amp;#x26;lang=en&quot;&gt;&lt;em&gt;Modern Fortran Explained&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now, if we follow the &lt;a href=&quot;https://en.wikipedia.org/wiki/Pareto_principle&quot;&gt;Pareto principle&lt;/a&gt;, we can expect that roughly 80% of the performance/functionality of a given software, depends on approximately 20% of the source code. This rule of thumb basically means that we do not need to change every single line of code, but just some core components that most of the functionality depends on. A &lt;a href=&quot;https://en.wikipedia.org/wiki/Profiling_(computer_programming)&quot;&gt;&lt;em&gt;profiler&lt;/em&gt;&lt;/a&gt; is the tool that will help you to identify the hot spots of your software. Profilers can be used together with &lt;a href=&quot;https://github.com/jrfonseca/gprof2dot&quot;&gt;&lt;em&gt;&lt;strong&gt;gprof2dot&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; to generate a graph showing the most used functions together with their dependencies.&lt;/p&gt;
&lt;h2 id=&quot;the-strategy&quot;&gt;The strategy&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Would you go on the quest for unraveling the mysteries of the universe with a rusted and lousy tool?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once you know how to use the tools of your language and have identified the core functionality of your software, it is time to reflect on what you want to get out of the code. You may come out with several words like: performance, efficiency, etc. but if you are doing science, in my view the really important word is &lt;em&gt;&lt;strong&gt;reproducibility&lt;/strong&gt;&lt;/em&gt;*.* Reproducibility is fundamental within science, because it is what sets up the basis of hypotheses and subsequently theories. Without it we will go blind searching for ghosts.&lt;/p&gt;
&lt;p&gt;To my knowledge, there are three fundamental features that scientific code must contain in order to be reproducible: &lt;em&gt;&lt;strong&gt;a test suite, a portable installation&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;and&lt;/em&gt; &lt;em&gt;&lt;strong&gt;documentation&lt;/strong&gt;&lt;/em&gt;. A test suite is simply a collection that asserts that a software behaves as expected. While a portable installation refers to a simple procedure that allows to easily install the software in different platforms and operative systems. I will elaborate more about these three important features in the following section.&lt;/p&gt;
&lt;p&gt;Notice that these three features are extremely difficult to implement without a &lt;a href=&quot;https://guide.esciencecenter.nl/best_practices/version_control.html&quot;&gt;version control system&lt;/a&gt;, that in modern scientific development boils down to using &lt;a href=&quot;https://git-scm.com/book/en/v2&quot;&gt;&lt;em&gt;&lt;strong&gt;git&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; (specifically one of the several free &lt;a href=&quot;https://medium.com/flow-ci/github-vs-bitbucket-vs-gitlab-vs-coding-7cf2b43888a1&quot;&gt;&lt;em&gt;&lt;strong&gt;repository management services&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;). I am aware that there are some politics among scientists against making the code open source, mainly due to the prejudice that someone else is going to steal their ideas. Admittedly, no serious scientist will go through the pain of understanding thousands of lines of obfuscated code to steal a complex mathematical model that is already public knowledge. But more importantly, science is about probing reality with experiments and simulations. How can an obscure and inaccessible code achieve those goals?&lt;/p&gt;
&lt;h2 id=&quot;even-heroes-need-help&quot;&gt;Even heroes need help&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not reinvent the wheel, use the high quality and free available software for testing and building&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;testing&quot;&gt;Testing&lt;/h3&gt;
&lt;p&gt;A test suite is extremely important since it will guarantee that we do not introduce new bugs when we are refactoring the core components. If there are no tests you may need to come out with your own test suite using a &lt;a href=&quot;https://guide.esciencecenter.nl/best_practices/testing.html&quot;&gt;&lt;em&gt;test infrastructure for your&lt;/em&gt; language&lt;/a&gt;. Notice that testing does not mean to run the whole software with hundreds of complicated calculations in a supercomputer, producing Gigabytes of output. Testing is about making sure that small components (e.g. functions and methods) behave as you expect. Yes, it means that you should have a lot of small tests! Also, in order to help with the process of refactoring the legacy code you will certainly need to get familiar with the concept of &lt;a href=&quot;https://realpython.com/python-continuous-integration/&quot;&gt;&lt;strong&gt;continuous integration&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;
&lt;p&gt;Legacy code usually lacks a portable installation and users are forced to deal with low level shell scripts or &lt;a href=&quot;https://www.gnu.org/software/make/&quot;&gt;Make files&lt;/a&gt; (or whatever &lt;a href=&quot;https://en.wikipedia.org/wiki/Build_automation&quot;&gt;build system&lt;/a&gt; you are using), in order to install the code. If you are using C/C++ or FORTRAN, &lt;a href=&quot;https://cmake.org/&quot;&gt;&lt;strong&gt;CMake&lt;/strong&gt;&lt;/a&gt; is the tool that you are looking for in order to make your software easy to install, most of the instructions that you will need are nicely explained in the &lt;a href=&quot;https://www.packtpub.com/application-development/cmake-cookbook&quot;&gt;CMake Cookbook&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Being portable is important not only for the people interested in using the software but also for you in order to work in a continuous integration model*.*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;documentation&quot;&gt;Documentation&lt;/h3&gt;
&lt;p&gt;Testing and installing the code is half of the story, a software without documentation is basically inaccessible even for the experts in a given field. By documentation I do not mean a lengthy and detailed description of every feature available in the software. What users of the software want to see is a short and clear description of a given feature or functionality, while implementation details can be moved to the source code.&lt;/p&gt;
&lt;p&gt;There are several choices to write documentation in C/C++, while for FORTRAN the standard tool is &lt;a href=&quot;https://github.com/doxygen/doxygen&quot;&gt;&lt;strong&gt;Doxygen&lt;/strong&gt;&lt;/a&gt;. For an extensive discussion about how to write documentation for scientific code, check the &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1006561&quot;&gt;Ten simple rules for documenting scientific code&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;here-be-dragons&quot;&gt;“Here be dragons”&lt;/h2&gt;
&lt;p&gt;Together we have just piped out at some guidelines and tools to face scientific legacy code. They are not silver bullets and only intended to give some help when navigating uncharted seas. Finally, bear in mind that cleaning, testing and documenting while coding are the most powerful tools against prospective code-monsters.&lt;/p&gt;</description><pubDate>Wed, 09 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;“So comes snow after fire, and even dragons have their endings.”&lt;br&gt;
― &lt;strong&gt;J.R.R. Tolkien,&lt;/strong&gt; &lt;a href=&quot;https://www.goodreads.com/work/quotes/1540236&quot;&gt;&lt;strong&gt;The Hobbit&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;712&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_frYHQLnu7557WfFq0j7L1w-0f8293f3.CyV4qt5o_2uriY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Typical debugging session&lt;/p&gt;
&lt;p&gt;When I started my PhD in the field of &lt;a href=&quot;https://en.wikipedia.org/wiki/Computational_chemistry&quot;&gt;computational chemistry&lt;/a&gt; I was given the task of improving and contributing to different pieces of code in the infamous &lt;a href=&quot;https://en.wikipedia.org/wiki/Fortran#FORTRAN_77&quot;&gt;FORTRAN 77 standard&lt;/a&gt;. I gathered all my courage and spent several months banging my head against a wall of esoteric compilation errors trying to decipher the arcane arts of compiling and running legacy code.&lt;/p&gt;
&lt;p&gt;Back then the basic idea was to dig into all the blogs, documents and different Q&amp;#x26;A sites, then muddle through the code until it compiled. Subsequently, I put warnings for all the unfortunate souls that would have to deal with the spaghetti monster in the future, warning them to not touch this and that keyword under the threat of eternal damnation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then, I wondered: if dealing with legacy code is such a nightmare, why do we not throw away all the legacy code and start from scratch?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yes, legacy code is ugly, convoluted and sometimes it is indistinguishable from &lt;a href=&quot;https://en.wikipedia.org/wiki/Black_Speech&quot;&gt;black speech of Mordor&lt;/a&gt; (see for instance: &lt;em&gt;goto&lt;/em&gt;, &lt;em&gt;rewind&lt;/em&gt; and &lt;em&gt;common blocks&lt;/em&gt;**).** But, &lt;em&gt;in general scientific legacy code contains the tears, sweat and blood of researchers who have spent many days and nights implementing new features and fixing bugs&lt;/em&gt;. You can argue that all the knowledge lies within publications and therefore we can throw everything away and start from scratch, but as discussed in &lt;a href=&quot;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/&quot;&gt;this excellent post&lt;/a&gt;, the answer is more complex than that and we still need to produce working code while keeping the previous developments alive.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So, how do we then face legacy code while maintaining our sanity?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;the-quest&quot;&gt;The quest&lt;/h2&gt;
&lt;p&gt;Before embarking on any enterprise about maintaining/modernizing legacy code, let me tell you that on my experience the war against bad code is won battle by battle, one at a time, so be wise when choosing your battles. Experience will tell you what the most urgent issues are to fix, provided that you have experience on the code that you are working on. But since that is seldom the case, the first step to take is read as much as you can about the language/tool that you are going to use.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The time that you spend reading material related to your project’s programming languages, libraries, tools, etc. will pay you back many times in the future when you identify an issue and immediately know how to deal with it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you happened to run into a &lt;em&gt;C++&lt;/em&gt; legacy monster go and read &lt;a href=&quot;http://shop.oreilly.com/product/0636920033707.do&quot;&gt;&lt;em&gt;Effective modern C++&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt; On the other hand if you need to deal with &lt;em&gt;FORTRAN&lt;/em&gt;, I would recommend you to have a look at &lt;a href=&quot;https://global.oup.com/academic/product/modern-fortran-explained-9780198811893?cc=nl&amp;#x26;lang=en&quot;&gt;&lt;em&gt;Modern Fortran Explained&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now, if we follow the &lt;a href=&quot;https://en.wikipedia.org/wiki/Pareto_principle&quot;&gt;Pareto principle&lt;/a&gt;, we can expect that roughly 80% of the performance/functionality of a given software, depends on approximately 20% of the source code. This rule of thumb basically means that we do not need to change every single line of code, but just some core components that most of the functionality depends on. A &lt;a href=&quot;https://en.wikipedia.org/wiki/Profiling_(computer_programming)&quot;&gt;&lt;em&gt;profiler&lt;/em&gt;&lt;/a&gt; is the tool that will help you to identify the hot spots of your software. Profilers can be used together with &lt;a href=&quot;https://github.com/jrfonseca/gprof2dot&quot;&gt;&lt;em&gt;&lt;strong&gt;gprof2dot&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; to generate a graph showing the most used functions together with their dependencies.&lt;/p&gt;
&lt;h2 id=&quot;the-strategy&quot;&gt;The strategy&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Would you go on the quest for unraveling the mysteries of the universe with a rusted and lousy tool?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once you know how to use the tools of your language and have identified the core functionality of your software, it is time to reflect on what you want to get out of the code. You may come out with several words like: performance, efficiency, etc. but if you are doing science, in my view the really important word is &lt;em&gt;&lt;strong&gt;reproducibility&lt;/strong&gt;&lt;/em&gt;*.* Reproducibility is fundamental within science, because it is what sets up the basis of hypotheses and subsequently theories. Without it we will go blind searching for ghosts.&lt;/p&gt;
&lt;p&gt;To my knowledge, there are three fundamental features that scientific code must contain in order to be reproducible: &lt;em&gt;&lt;strong&gt;a test suite, a portable installation&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;and&lt;/em&gt; &lt;em&gt;&lt;strong&gt;documentation&lt;/strong&gt;&lt;/em&gt;. A test suite is simply a collection that asserts that a software behaves as expected. While a portable installation refers to a simple procedure that allows to easily install the software in different platforms and operative systems. I will elaborate more about these three important features in the following section.&lt;/p&gt;
&lt;p&gt;Notice that these three features are extremely difficult to implement without a &lt;a href=&quot;https://guide.esciencecenter.nl/best_practices/version_control.html&quot;&gt;version control system&lt;/a&gt;, that in modern scientific development boils down to using &lt;a href=&quot;https://git-scm.com/book/en/v2&quot;&gt;&lt;em&gt;&lt;strong&gt;git&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; (specifically one of the several free &lt;a href=&quot;https://medium.com/flow-ci/github-vs-bitbucket-vs-gitlab-vs-coding-7cf2b43888a1&quot;&gt;&lt;em&gt;&lt;strong&gt;repository management services&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;). I am aware that there are some politics among scientists against making the code open source, mainly due to the prejudice that someone else is going to steal their ideas. Admittedly, no serious scientist will go through the pain of understanding thousands of lines of obfuscated code to steal a complex mathematical model that is already public knowledge. But more importantly, science is about probing reality with experiments and simulations. How can an obscure and inaccessible code achieve those goals?&lt;/p&gt;
&lt;h2 id=&quot;even-heroes-need-help&quot;&gt;Even heroes need help&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not reinvent the wheel, use the high quality and free available software for testing and building&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;testing&quot;&gt;Testing&lt;/h3&gt;
&lt;p&gt;A test suite is extremely important since it will guarantee that we do not introduce new bugs when we are refactoring the core components. If there are no tests you may need to come out with your own test suite using a &lt;a href=&quot;https://guide.esciencecenter.nl/best_practices/testing.html&quot;&gt;&lt;em&gt;test infrastructure for your&lt;/em&gt; language&lt;/a&gt;. Notice that testing does not mean to run the whole software with hundreds of complicated calculations in a supercomputer, producing Gigabytes of output. Testing is about making sure that small components (e.g. functions and methods) behave as you expect. Yes, it means that you should have a lot of small tests! Also, in order to help with the process of refactoring the legacy code you will certainly need to get familiar with the concept of &lt;a href=&quot;https://realpython.com/python-continuous-integration/&quot;&gt;&lt;strong&gt;continuous integration&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;
&lt;p&gt;Legacy code usually lacks a portable installation and users are forced to deal with low level shell scripts or &lt;a href=&quot;https://www.gnu.org/software/make/&quot;&gt;Make files&lt;/a&gt; (or whatever &lt;a href=&quot;https://en.wikipedia.org/wiki/Build_automation&quot;&gt;build system&lt;/a&gt; you are using), in order to install the code. If you are using C/C++ or FORTRAN, &lt;a href=&quot;https://cmake.org/&quot;&gt;&lt;strong&gt;CMake&lt;/strong&gt;&lt;/a&gt; is the tool that you are looking for in order to make your software easy to install, most of the instructions that you will need are nicely explained in the &lt;a href=&quot;https://www.packtpub.com/application-development/cmake-cookbook&quot;&gt;CMake Cookbook&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Being portable is important not only for the people interested in using the software but also for you in order to work in a continuous integration model*.*&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;documentation&quot;&gt;Documentation&lt;/h3&gt;
&lt;p&gt;Testing and installing the code is half of the story, a software without documentation is basically inaccessible even for the experts in a given field. By documentation I do not mean a lengthy and detailed description of every feature available in the software. What users of the software want to see is a short and clear description of a given feature or functionality, while implementation details can be moved to the source code.&lt;/p&gt;
&lt;p&gt;There are several choices to write documentation in C/C++, while for FORTRAN the standard tool is &lt;a href=&quot;https://github.com/doxygen/doxygen&quot;&gt;&lt;strong&gt;Doxygen&lt;/strong&gt;&lt;/a&gt;. For an extensive discussion about how to write documentation for scientific code, check the &lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371%2Fjournal.pcbi.1006561&quot;&gt;Ten simple rules for documenting scientific code&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;here-be-dragons&quot;&gt;“Here be dragons”&lt;/h2&gt;
&lt;p&gt;Together we have just piped out at some guidelines and tools to face scientific legacy code. They are not silver bullets and only intended to give some help when navigating uncharted seas. Finally, bear in mind that cleaning, testing and documenting while coding are the most powerful tools against prospective code-monsters.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_frYHQLnu7557WfFq0j7L1w-0f8293f3.CyV4qt5o.png" medium="image"/><author>Felipe</author></item><item><title>portable hpc workflows with snakemake and xenon</title><link>https://blog2.esciencecenter.nl/posts/2018-12-20---portable-hpc-workflows-with-snakemake-and-xenon</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-12-20---portable-hpc-workflows-with-snakemake-and-xenon</guid><description>&lt;h3 id=&quot;migrate-your-scientific-workflows-to-different-remote-machines-in-minutes-instead-of-days&quot;&gt;Migrate your scientific workflows to different remote machines in minutes instead of days&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Dkns3eBVvWMJHsR08BZaCQ-a2000236.BbtVlfSa_Z2gnYCh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image courtesy of WallpaperUP&lt;/p&gt;
&lt;p&gt;Scientific workflows are often coupled to the computer systems for which they were developed. This can be a problem when you want to migrate a workflow to a different system that has better performance, higher availability, is cheaper to use, or stores data that are difficult to move around etc.&lt;/p&gt;
&lt;p&gt;In this blog, we describe a solution we use in the life science domain to run an analysis of genetic variations in genome sequencing data. For this, we use 4 different algorithms, each implemented in a separate command-line tool.&lt;/p&gt;
&lt;p&gt;Each of these tools requires its own configuration steps such as setting up input and output directories and specifying how many threads to use for parallel execution. Post-processing steps are also needed, to aggregate the results from each tool.&lt;/p&gt;
&lt;h2 id=&quot;snakemake-ties-it-all-together&quot;&gt;Snakemake ties it all together&lt;/h2&gt;
&lt;p&gt;To tie all the tools in the analysis together, we use the workflow tool &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/&quot;&gt;Snakemake&lt;/a&gt;. Snakemake makes it relatively easy to write down the steps that make up an analysis in a “recipe”. We can including things like concurrency (“ &lt;em&gt;Run this part of the analysis at the same time as this other part&lt;/em&gt; ”), and dependencies (“ &lt;em&gt;Don’t start this part of the analysis until these other parts have completed successfully&lt;/em&gt; ”).&lt;/p&gt;
&lt;h2 id=&quot;using-conda-environments&quot;&gt;Using Conda environments&lt;/h2&gt;
&lt;p&gt;The command-line tools included in our workflow are written in a variety of programming languages (C, C++, Python, Java, and R), and each need their own set of software dependencies. To prevent the tools from interfering with one another, we use the &lt;a href=&quot;https://conda.io/docs/&quot;&gt;Conda&lt;/a&gt; package and environment manager. Conda installs the required software into a separate environment, preventing interference and making the execution of a software less dependent on how the host system is set up.&lt;/p&gt;
&lt;p&gt;Snakemake supports both Conda environments, or containerized environments such as &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; or &lt;a href=&quot;https://www.sylabs.io/docs/&quot;&gt;Singularity&lt;/a&gt;. For our purposes, there is no added benefit of using containers, so we just use Conda environments.&lt;/p&gt;
&lt;p&gt;With this setup, we can run all tools and aggregate and analyze the results.&lt;/p&gt;
&lt;h2 id=&quot;portability-problems&quot;&gt;Portability problems&lt;/h2&gt;
&lt;p&gt;Initially, we used a compute cluster based on the Grid Engine scheduler to allocate resources. To submit our workflow to this machine, we can use Snakemake’s &lt;code&gt;--cluster&lt;/code&gt; option:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;snakemake --use-conda --cluster &quot;${SUBMIT_CMD}&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Through this option, you can specify things like which submit command to use, which job submission queue to submit to, the number of process needed per node, how much memory is needed, etc. The following command submits the Snakemake workflow on the Grid Engine cluster:&lt;/p&gt;
&lt;p&gt;The submit command needed by Snakemake to submit to a compute cluster using the Grid Engine scheduler.&lt;/p&gt;
&lt;p&gt;While this lets us specify how our workflow is executed on the remote system, it does have the undesired side effect of making it specific to one type of scheduler or compute cluster. This soon became a problem for us when we started making plans to use a different compute cluster, whose resources were allocated using &lt;a href=&quot;https://slurm.schedmd.com/&quot;&gt;Slurm&lt;/a&gt; instead of Grid Engine. For Slurm a different submit command is needed:&lt;/p&gt;
&lt;p&gt;The submit command needed by Snakemake to submit to a compute cluster using the Slurm scheduler.&lt;/p&gt;
&lt;p&gt;Although the information contained in both commands is the same, the exact command and options are very different. Figuring this out for each new compute cluster can be quite a hassle and makes it hard to share workflows with other researchers.&lt;/p&gt;
&lt;h2 id=&quot;xenon-to-the-rescue&quot;&gt;Xenon to the rescue&lt;/h2&gt;
&lt;p&gt;To improve the portability of our workflow, we use the &lt;a href=&quot;https://github.com/NLeSC/Xenon&quot;&gt;Xenon&lt;/a&gt; command-line tool that hides the differences between Grid Engine, Slurm, and &lt;a href=&quot;http://www.adaptivecomputing.com/products/torque/&quot;&gt;Torque&lt;/a&gt; from the user. Using Xenon, we can provide a single submit command that will be translated on the fly to the exact command expected by the different schedulers. For example:&lt;/p&gt;
&lt;p&gt;By simply changing the value of SCHEDULER, this submit command works on both Grid Engine and Slurm clusters — everything else stays the same.&lt;/p&gt;
&lt;p&gt;Switching from an Grid Engine system to a Slurm system is now as simple as replacing&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SCHEDULER=gridengine&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;by&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SCHEDULER=slurm&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;while the rest of the submit command can remain exactly as is. This approach makes it much easier to port our workflow to other compute clusters and to share them with our fellow researchers.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;To summarize, our setup provides separation of concerns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;use the Snakemake workflow system to describe the steps that make up an analysis;&lt;/li&gt;
&lt;li&gt;use Conda environments or containers for installing the tools needed by the workflow steps and to stop them interfering with each other or with the host system’s setup;&lt;/li&gt;
&lt;li&gt;use Xenon to make the workflow easily portable to HPC systems that use different schedulers for resource allocation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you’re interested in learning more about how to use Xenon, its command line interface, or how to use it from a variety of programming languages, &lt;a href=&quot;https://github.com/NLeSC/Xenon/blob/master/README.md&quot;&gt;Xenon’s README on GitHub&lt;/a&gt; is probably your best starting point. Happy porting!&lt;/p&gt;</description><pubDate>Thu, 20 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h3 id=&quot;migrate-your-scientific-workflows-to-different-remote-machines-in-minutes-instead-of-days&quot;&gt;Migrate your scientific workflows to different remote machines in minutes instead of days&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Dkns3eBVvWMJHsR08BZaCQ-a2000236.BbtVlfSa_Z2gnYCh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image courtesy of WallpaperUP&lt;/p&gt;
&lt;p&gt;Scientific workflows are often coupled to the computer systems for which they were developed. This can be a problem when you want to migrate a workflow to a different system that has better performance, higher availability, is cheaper to use, or stores data that are difficult to move around etc.&lt;/p&gt;
&lt;p&gt;In this blog, we describe a solution we use in the life science domain to run an analysis of genetic variations in genome sequencing data. For this, we use 4 different algorithms, each implemented in a separate command-line tool.&lt;/p&gt;
&lt;p&gt;Each of these tools requires its own configuration steps such as setting up input and output directories and specifying how many threads to use for parallel execution. Post-processing steps are also needed, to aggregate the results from each tool.&lt;/p&gt;
&lt;h2 id=&quot;snakemake-ties-it-all-together&quot;&gt;Snakemake ties it all together&lt;/h2&gt;
&lt;p&gt;To tie all the tools in the analysis together, we use the workflow tool &lt;a href=&quot;https://snakemake.readthedocs.io/en/stable/&quot;&gt;Snakemake&lt;/a&gt;. Snakemake makes it relatively easy to write down the steps that make up an analysis in a “recipe”. We can including things like concurrency (“ &lt;em&gt;Run this part of the analysis at the same time as this other part&lt;/em&gt; ”), and dependencies (“ &lt;em&gt;Don’t start this part of the analysis until these other parts have completed successfully&lt;/em&gt; ”).&lt;/p&gt;
&lt;h2 id=&quot;using-conda-environments&quot;&gt;Using Conda environments&lt;/h2&gt;
&lt;p&gt;The command-line tools included in our workflow are written in a variety of programming languages (C, C++, Python, Java, and R), and each need their own set of software dependencies. To prevent the tools from interfering with one another, we use the &lt;a href=&quot;https://conda.io/docs/&quot;&gt;Conda&lt;/a&gt; package and environment manager. Conda installs the required software into a separate environment, preventing interference and making the execution of a software less dependent on how the host system is set up.&lt;/p&gt;
&lt;p&gt;Snakemake supports both Conda environments, or containerized environments such as &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; or &lt;a href=&quot;https://www.sylabs.io/docs/&quot;&gt;Singularity&lt;/a&gt;. For our purposes, there is no added benefit of using containers, so we just use Conda environments.&lt;/p&gt;
&lt;p&gt;With this setup, we can run all tools and aggregate and analyze the results.&lt;/p&gt;
&lt;h2 id=&quot;portability-problems&quot;&gt;Portability problems&lt;/h2&gt;
&lt;p&gt;Initially, we used a compute cluster based on the Grid Engine scheduler to allocate resources. To submit our workflow to this machine, we can use Snakemake’s &lt;code&gt;--cluster&lt;/code&gt; option:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;snakemake --use-conda --cluster &quot;${SUBMIT_CMD}&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Through this option, you can specify things like which submit command to use, which job submission queue to submit to, the number of process needed per node, how much memory is needed, etc. The following command submits the Snakemake workflow on the Grid Engine cluster:&lt;/p&gt;
&lt;p&gt;The submit command needed by Snakemake to submit to a compute cluster using the Grid Engine scheduler.&lt;/p&gt;
&lt;p&gt;While this lets us specify how our workflow is executed on the remote system, it does have the undesired side effect of making it specific to one type of scheduler or compute cluster. This soon became a problem for us when we started making plans to use a different compute cluster, whose resources were allocated using &lt;a href=&quot;https://slurm.schedmd.com/&quot;&gt;Slurm&lt;/a&gt; instead of Grid Engine. For Slurm a different submit command is needed:&lt;/p&gt;
&lt;p&gt;The submit command needed by Snakemake to submit to a compute cluster using the Slurm scheduler.&lt;/p&gt;
&lt;p&gt;Although the information contained in both commands is the same, the exact command and options are very different. Figuring this out for each new compute cluster can be quite a hassle and makes it hard to share workflows with other researchers.&lt;/p&gt;
&lt;h2 id=&quot;xenon-to-the-rescue&quot;&gt;Xenon to the rescue&lt;/h2&gt;
&lt;p&gt;To improve the portability of our workflow, we use the &lt;a href=&quot;https://github.com/NLeSC/Xenon&quot;&gt;Xenon&lt;/a&gt; command-line tool that hides the differences between Grid Engine, Slurm, and &lt;a href=&quot;http://www.adaptivecomputing.com/products/torque/&quot;&gt;Torque&lt;/a&gt; from the user. Using Xenon, we can provide a single submit command that will be translated on the fly to the exact command expected by the different schedulers. For example:&lt;/p&gt;
&lt;p&gt;By simply changing the value of SCHEDULER, this submit command works on both Grid Engine and Slurm clusters — everything else stays the same.&lt;/p&gt;
&lt;p&gt;Switching from an Grid Engine system to a Slurm system is now as simple as replacing&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SCHEDULER=gridengine&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;by&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SCHEDULER=slurm&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;while the rest of the submit command can remain exactly as is. This approach makes it much easier to port our workflow to other compute clusters and to share them with our fellow researchers.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;To summarize, our setup provides separation of concerns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;use the Snakemake workflow system to describe the steps that make up an analysis;&lt;/li&gt;
&lt;li&gt;use Conda environments or containers for installing the tools needed by the workflow steps and to stop them interfering with each other or with the host system’s setup;&lt;/li&gt;
&lt;li&gt;use Xenon to make the workflow easily portable to HPC systems that use different schedulers for resource allocation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you’re interested in learning more about how to use Xenon, its command line interface, or how to use it from a variety of programming languages, &lt;a href=&quot;https://github.com/NLeSC/Xenon/blob/master/README.md&quot;&gt;Xenon’s README on GitHub&lt;/a&gt; is probably your best starting point. Happy porting!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Dkns3eBVvWMJHsR08BZaCQ-a2000236.BbtVlfSa.jpeg" medium="image"/><author>Jurriaan H. Spaaks</author></item><item><title>using agile methods in scientific software development</title><link>https://blog2.esciencecenter.nl/posts/2018-12-17---using-agile-methods-in-scientific-software-development</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-12-17---using-agile-methods-in-scientific-software-development</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4cOctoypHHDbrgkQ1CGUvA-30a9a8fb.Czms6Wdd_Z7w9Pe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo: &lt;a href=&quot;http://www.unsplash.com&quot;&gt;www.unsplash.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software plays an increasingly important role in all aspects of the modern scientific enterprise. The practice of developing scientific software, however, is still young and uncultivated compared to more traditional methods and instruments. In this sense, the full potential of software for science has yet to be realised, but to reach that point, we must improve upon the methods by which the software is conceived, produced, and maintained. In this post, we consider what Agile methodologies have to offer scientific software development, with the hope of stimulating discussion around what practices can help improve the quality and longevity of scientific software.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Software engineering research has long recognised the importance of having adequate processes and methodologies to guide software development, but much more needs to be done to realise the benefits of good practices in the scientific software domain. Systematic &lt;a href=&quot;https://doi.org/10.1145/1985782.1985784&quot;&gt;reviews of the literature&lt;/a&gt; support Agile methodologies as being beneficial to scientific software developers as there appears to be a natural fit between iterative development and the exploratory character of science. However, “Agile” is often a term applied post hoc to scientific software developers, who, without formal training, have independently arrived at approaches that resemble agile ones. Domain scientists would benefit from having a closer dialogue with software engineers in order to create approaches that are more tailored to their needs and that take advantage of the best practices known in conventional industry. But what does it mean for “Agile” to work in the context in scientific software development, and how do we sell these ideas to our audience?&lt;/p&gt;
&lt;p&gt;Agile itself is a term laden with meaning in industry, and for the sake of clarity, we begin by defining just what is meant by it. Here we use the language of the &lt;a href=&quot;http://agilemanifesto.org/&quot;&gt;Agile Manifesto&lt;/a&gt;, which identified the four principles of Agile: (1) individuals and interactions over processes and tools, (2) working software over comprehensive documentation, (3) customer collaboration over contract negotiation, and (4) responding to change over following a plan. There are many methodologies which support these principles (e.g. scrum), but a pitfall of applying these methodologies to scientific software is that they may not match the needs and expectations of these teams. For example, we cannot focus our attention on the individual without recognising their context: scientific software developers are often self-taught, uniquely qualified in their domain, and divided between many different commitments; this does not mesh well with the implicit assumption of many agile methods that developers are trained, interchangeable, and fully committed to a project. The realities of scientific software development demand a principled approach to adapting and adopting Agile. Along these lines, we provide several guidelines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make priorities explicit.&lt;/strong&gt; Know what tasks need to be done, understand their priority and make realistic time predictions. One way to make your tasks and priorities visual is by using a physical to-do board with post-its. Of course, this is not always practical when the team is physically separated, but platforms like Github offer digital alternatives to create and organise issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Work iteratively.&lt;/strong&gt; During a research project, insights evolve and the requirements for the software change. This is exactly where iterative, agile development is a good fit. Implement features during relatively short iterations, for example based on a 2-week sprint, if that fits your team. After each iteration, review and revise the plans and tasks, and make adjustments based on feedback from stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Communication within a clear framework.&lt;/strong&gt; Ensure that all collaborators involved understand the Agile way of working, and preferably have them committed to the process. Make an inventory of who the key actors are in the project — who are the developers, who is the “product owner” (one of the developers, the project PI, an external collaborator, etc.) and who the end-users are. For all of these people, determine how they are involved in the process and how to get their feedback during development. This helps you shape the development process. Communication between both team members and stakeholders is key for an effective agile workway. Therefore, facilitate both informal and formal contact moments to keep everyone involved. How to do this in practice depends very much on the size, composition and location of your team. If possible, organise a short daily stand-up: this provides a natural occasion to keep each other up-to-date and to ask for help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduce Agile working in an agile way.&lt;/strong&gt; The million dollar question is what aspects of Agile working are beneficial to your research software project. Each project is different, and defining a good development process is a process in itself! It is unlikely that you know the ideal way of working at day one of your project. Therefore, start with small steps to improve the process, and iterate and reflect along the way.&lt;/p&gt;
&lt;p&gt;Scientific software developers can benefit from Agile practices for scientific software. The adoption and proper tailoring of these practices can increase the efficiency and effectiveness of teams working to provide software to scientists. Many scientists know about the benefits of agile methods and partially implement them even without knowing about agile development. The simple steps of making a plan, continuously adapting the plan, effective communication and iteratively adjusting the working method to test and include more agile methods can help them create software.To support scientific software developers on this way, we all need to help point software engineers in the right direction. We suggest the conduction of empirical studies to assess benefits and challenges of agile practices in scientific software engineering. One step in this direction is the creation of an “Agile in Research Software Development” carpentries course by the WSSSPE/SSI/RSE community.&lt;/p&gt;</description><pubDate>Mon, 17 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4cOctoypHHDbrgkQ1CGUvA-30a9a8fb.Czms6Wdd_Z7w9Pe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo: &lt;a href=&quot;http://www.unsplash.com&quot;&gt;www.unsplash.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software plays an increasingly important role in all aspects of the modern scientific enterprise. The practice of developing scientific software, however, is still young and uncultivated compared to more traditional methods and instruments. In this sense, the full potential of software for science has yet to be realised, but to reach that point, we must improve upon the methods by which the software is conceived, produced, and maintained. In this post, we consider what Agile methodologies have to offer scientific software development, with the hope of stimulating discussion around what practices can help improve the quality and longevity of scientific software.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Software engineering research has long recognised the importance of having adequate processes and methodologies to guide software development, but much more needs to be done to realise the benefits of good practices in the scientific software domain. Systematic &lt;a href=&quot;https://doi.org/10.1145/1985782.1985784&quot;&gt;reviews of the literature&lt;/a&gt; support Agile methodologies as being beneficial to scientific software developers as there appears to be a natural fit between iterative development and the exploratory character of science. However, “Agile” is often a term applied post hoc to scientific software developers, who, without formal training, have independently arrived at approaches that resemble agile ones. Domain scientists would benefit from having a closer dialogue with software engineers in order to create approaches that are more tailored to their needs and that take advantage of the best practices known in conventional industry. But what does it mean for “Agile” to work in the context in scientific software development, and how do we sell these ideas to our audience?&lt;/p&gt;
&lt;p&gt;Agile itself is a term laden with meaning in industry, and for the sake of clarity, we begin by defining just what is meant by it. Here we use the language of the &lt;a href=&quot;http://agilemanifesto.org/&quot;&gt;Agile Manifesto&lt;/a&gt;, which identified the four principles of Agile: (1) individuals and interactions over processes and tools, (2) working software over comprehensive documentation, (3) customer collaboration over contract negotiation, and (4) responding to change over following a plan. There are many methodologies which support these principles (e.g. scrum), but a pitfall of applying these methodologies to scientific software is that they may not match the needs and expectations of these teams. For example, we cannot focus our attention on the individual without recognising their context: scientific software developers are often self-taught, uniquely qualified in their domain, and divided between many different commitments; this does not mesh well with the implicit assumption of many agile methods that developers are trained, interchangeable, and fully committed to a project. The realities of scientific software development demand a principled approach to adapting and adopting Agile. Along these lines, we provide several guidelines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make priorities explicit.&lt;/strong&gt; Know what tasks need to be done, understand their priority and make realistic time predictions. One way to make your tasks and priorities visual is by using a physical to-do board with post-its. Of course, this is not always practical when the team is physically separated, but platforms like Github offer digital alternatives to create and organise issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Work iteratively.&lt;/strong&gt; During a research project, insights evolve and the requirements for the software change. This is exactly where iterative, agile development is a good fit. Implement features during relatively short iterations, for example based on a 2-week sprint, if that fits your team. After each iteration, review and revise the plans and tasks, and make adjustments based on feedback from stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Communication within a clear framework.&lt;/strong&gt; Ensure that all collaborators involved understand the Agile way of working, and preferably have them committed to the process. Make an inventory of who the key actors are in the project — who are the developers, who is the “product owner” (one of the developers, the project PI, an external collaborator, etc.) and who the end-users are. For all of these people, determine how they are involved in the process and how to get their feedback during development. This helps you shape the development process. Communication between both team members and stakeholders is key for an effective agile workway. Therefore, facilitate both informal and formal contact moments to keep everyone involved. How to do this in practice depends very much on the size, composition and location of your team. If possible, organise a short daily stand-up: this provides a natural occasion to keep each other up-to-date and to ask for help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduce Agile working in an agile way.&lt;/strong&gt; The million dollar question is what aspects of Agile working are beneficial to your research software project. Each project is different, and defining a good development process is a process in itself! It is unlikely that you know the ideal way of working at day one of your project. Therefore, start with small steps to improve the process, and iterate and reflect along the way.&lt;/p&gt;
&lt;p&gt;Scientific software developers can benefit from Agile practices for scientific software. The adoption and proper tailoring of these practices can increase the efficiency and effectiveness of teams working to provide software to scientists. Many scientists know about the benefits of agile methods and partially implement them even without knowing about agile development. The simple steps of making a plan, continuously adapting the plan, effective communication and iteratively adjusting the working method to test and include more agile methods can help them create software.To support scientific software developers on this way, we all need to help point software engineers in the right direction. We suggest the conduction of empirical studies to assess benefits and challenges of agile practices in scientific software engineering. One step in this direction is the creation of an “Agile in Research Software Development” carpentries course by the WSSSPE/SSI/RSE community.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_4cOctoypHHDbrgkQ1CGUvA-30a9a8fb.Czms6Wdd.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>using agile methods in scientific software development 1</title><link>https://blog2.esciencecenter.nl/posts/2018-12-17---using-agile-methods-in-scientific-software-development-1</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-12-17---using-agile-methods-in-scientific-software-development-1</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4cOctoypHHDbrgkQ1CGUvA-30a9a8fb.Czms6Wdd_Z7w9Pe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo: &lt;a href=&quot;http://www.unsplash.com&quot;&gt;www.unsplash.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software plays an increasingly important role in all aspects of the modern scientific enterprise. The practice of developing scientific software, however, is still young and uncultivated compared to more traditional methods and instruments. In this sense, the full potential of software for science has yet to be realised, but to reach that point, we must improve upon the methods by which the software is conceived, produced, and maintained. In this post, we consider what Agile methodologies have to offer scientific software development, with the hope of stimulating discussion around what practices can help improve the quality and longevity of scientific software.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Software engineering research has long recognised the importance of having adequate processes and methodologies to guide software development, but much more needs to be done to realise the benefits of good practices in the scientific software domain. Systematic &lt;a href=&quot;https://doi.org/10.1145/1985782.1985784&quot;&gt;reviews of the literature&lt;/a&gt; support Agile methodologies as being beneficial to scientific software developers as there appears to be a natural fit between iterative development and the exploratory character of science. However, “Agile” is often a term applied post hoc to scientific software developers, who, without formal training, have independently arrived at approaches that resemble agile ones. Domain scientists would benefit from having a closer dialogue with software engineers in order to create approaches that are more tailored to their needs and that take advantage of the best practices known in conventional industry. But what does it mean for “Agile” to work in the context in scientific software development, and how do we sell these ideas to our audience?&lt;/p&gt;
&lt;p&gt;Agile itself is a term laden with meaning in industry, and for the sake of clarity, we begin by defining just what is meant by it. Here we use the language of the &lt;a href=&quot;http://agilemanifesto.org/&quot;&gt;Agile Manifesto&lt;/a&gt;, which identified the four principles of Agile: (1) individuals and interactions over processes and tools, (2) working software over comprehensive documentation, (3) customer collaboration over contract negotiation, and (4) responding to change over following a plan. There are many methodologies which support these principles (e.g. scrum), but a pitfall of applying these methodologies to scientific software is that they may not match the needs and expectations of these teams. For example, we cannot focus our attention on the individual without recognising their context: scientific software developers are often self-taught, uniquely qualified in their domain, and divided between many different commitments; this does not mesh well with the implicit assumption of many agile methods that developers are trained, interchangeable, and fully committed to a project. The realities of scientific software development demand a principled approach to adapting and adopting Agile. Along these lines, we provide several guidelines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make priorities explicit.&lt;/strong&gt; Know what tasks need to be done, understand their priority and make realistic time predictions. One way to make your tasks and priorities visual is by using a physical to-do board with post-its. Of course, this is not always practical when the team is physically separated, but platforms like Github offer digital alternatives to create and organise issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Work iteratively.&lt;/strong&gt; During a research project, insights evolve and the requirements for the software change. This is exactly where iterative, agile development is a good fit. Implement features during relatively short iterations, for example based on a 2-week sprint, if that fits your team. After each iteration, review and revise the plans and tasks, and make adjustments based on feedback from stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Communication within a clear framework.&lt;/strong&gt; Ensure that all collaborators involved understand the Agile way of working, and preferably have them committed to the process. Make an inventory of who the key actors are in the project — who are the developers, who is the “product owner” (one of the developers, the project PI, an external collaborator, etc.) and who the end-users are. For all of these people, determine how they are involved in the process and how to get their feedback during development. This helps you shape the development process. Communication between both team members and stakeholders is key for an effective agile workway. Therefore, facilitate both informal and formal contact moments to keep everyone involved. How to do this in practice depends very much on the size, composition and location of your team. If possible, organise a short daily stand-up: this provides a natural occasion to keep each other up-to-date and to ask for help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduce Agile working in an agile way.&lt;/strong&gt; The million dollar question is what aspects of Agile working are beneficial to your research software project. Each project is different, and defining a good development process is a process in itself! It is unlikely that you know the ideal way of working at day one of your project. Therefore, start with small steps to improve the process, and iterate and reflect along the way.&lt;/p&gt;
&lt;p&gt;Scientific software developers can benefit from Agile practices for scientific software. The adoption and proper tailoring of these practices can increase the efficiency and effectiveness of teams working to provide software to scientists. Many scientists know about the benefits of agile methods and partially implement them even without knowing about agile development. The simple steps of making a plan, continuously adapting the plan, effective communication and iteratively adjusting the working method to test and include more agile methods can help them create software.To support scientific software developers on this way, we all need to help point software engineers in the right direction. We suggest the conduction of empirical studies to assess benefits and challenges of agile practices in scientific software engineering. One step in this direction is the creation of an “Agile in Research Software Development” carpentries course by the WSSSPE/SSI/RSE community.&lt;/p&gt;</description><pubDate>Mon, 17 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_4cOctoypHHDbrgkQ1CGUvA-30a9a8fb.Czms6Wdd_Z7w9Pe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo: &lt;a href=&quot;http://www.unsplash.com&quot;&gt;www.unsplash.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software plays an increasingly important role in all aspects of the modern scientific enterprise. The practice of developing scientific software, however, is still young and uncultivated compared to more traditional methods and instruments. In this sense, the full potential of software for science has yet to be realised, but to reach that point, we must improve upon the methods by which the software is conceived, produced, and maintained. In this post, we consider what Agile methodologies have to offer scientific software development, with the hope of stimulating discussion around what practices can help improve the quality and longevity of scientific software.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Software engineering research has long recognised the importance of having adequate processes and methodologies to guide software development, but much more needs to be done to realise the benefits of good practices in the scientific software domain. Systematic &lt;a href=&quot;https://doi.org/10.1145/1985782.1985784&quot;&gt;reviews of the literature&lt;/a&gt; support Agile methodologies as being beneficial to scientific software developers as there appears to be a natural fit between iterative development and the exploratory character of science. However, “Agile” is often a term applied post hoc to scientific software developers, who, without formal training, have independently arrived at approaches that resemble agile ones. Domain scientists would benefit from having a closer dialogue with software engineers in order to create approaches that are more tailored to their needs and that take advantage of the best practices known in conventional industry. But what does it mean for “Agile” to work in the context in scientific software development, and how do we sell these ideas to our audience?&lt;/p&gt;
&lt;p&gt;Agile itself is a term laden with meaning in industry, and for the sake of clarity, we begin by defining just what is meant by it. Here we use the language of the &lt;a href=&quot;http://agilemanifesto.org/&quot;&gt;Agile Manifesto&lt;/a&gt;, which identified the four principles of Agile: (1) individuals and interactions over processes and tools, (2) working software over comprehensive documentation, (3) customer collaboration over contract negotiation, and (4) responding to change over following a plan. There are many methodologies which support these principles (e.g. scrum), but a pitfall of applying these methodologies to scientific software is that they may not match the needs and expectations of these teams. For example, we cannot focus our attention on the individual without recognising their context: scientific software developers are often self-taught, uniquely qualified in their domain, and divided between many different commitments; this does not mesh well with the implicit assumption of many agile methods that developers are trained, interchangeable, and fully committed to a project. The realities of scientific software development demand a principled approach to adapting and adopting Agile. Along these lines, we provide several guidelines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Make priorities explicit.&lt;/strong&gt; Know what tasks need to be done, understand their priority and make realistic time predictions. One way to make your tasks and priorities visual is by using a physical to-do board with post-its. Of course, this is not always practical when the team is physically separated, but platforms like Github offer digital alternatives to create and organise issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Work iteratively.&lt;/strong&gt; During a research project, insights evolve and the requirements for the software change. This is exactly where iterative, agile development is a good fit. Implement features during relatively short iterations, for example based on a 2-week sprint, if that fits your team. After each iteration, review and revise the plans and tasks, and make adjustments based on feedback from stakeholders.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Communication within a clear framework.&lt;/strong&gt; Ensure that all collaborators involved understand the Agile way of working, and preferably have them committed to the process. Make an inventory of who the key actors are in the project — who are the developers, who is the “product owner” (one of the developers, the project PI, an external collaborator, etc.) and who the end-users are. For all of these people, determine how they are involved in the process and how to get their feedback during development. This helps you shape the development process. Communication between both team members and stakeholders is key for an effective agile workway. Therefore, facilitate both informal and formal contact moments to keep everyone involved. How to do this in practice depends very much on the size, composition and location of your team. If possible, organise a short daily stand-up: this provides a natural occasion to keep each other up-to-date and to ask for help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Introduce Agile working in an agile way.&lt;/strong&gt; The million dollar question is what aspects of Agile working are beneficial to your research software project. Each project is different, and defining a good development process is a process in itself! It is unlikely that you know the ideal way of working at day one of your project. Therefore, start with small steps to improve the process, and iterate and reflect along the way.&lt;/p&gt;
&lt;p&gt;Scientific software developers can benefit from Agile practices for scientific software. The adoption and proper tailoring of these practices can increase the efficiency and effectiveness of teams working to provide software to scientists. Many scientists know about the benefits of agile methods and partially implement them even without knowing about agile development. The simple steps of making a plan, continuously adapting the plan, effective communication and iteratively adjusting the working method to test and include more agile methods can help them create software.To support scientific software developers on this way, we all need to help point software engineers in the right direction. We suggest the conduction of empirical studies to assess benefits and challenges of agile practices in scientific software engineering. One step in this direction is the creation of an “Agile in Research Software Development” carpentries course by the WSSSPE/SSI/RSE community.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_4cOctoypHHDbrgkQ1CGUvA-30a9a8fb.Czms6Wdd.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Testing shell commands from Python</title><link>https://blog2.esciencecenter.nl/posts/2018-12-12---testing-shell-commands-from-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-12-12---testing-shell-commands-from-python</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1620&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_N20Y3NBxkdLlHLvJpOtxEQ-2b975963.C-Dpalwb_Z1uSdLe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What to do with these shells?&lt;/p&gt;
&lt;p&gt;How do you test shell commands? Recently, I came across several cases where I wanted to run shell commands for testing, but couldn’t find a tutorial about how to do it from Python. After a lot of Googling, I found a solution that worked for me, and maybe it works for you too!&lt;/p&gt;
&lt;h3 id=&quot;why-test-from-python&quot;&gt;Why test from Python?&lt;/h3&gt;
&lt;p&gt;You could use &lt;a href=&quot;https://spin.atomicobject.com/2016/01/11/command-line-interface-testing-tools/&quot;&gt;dedicated tools&lt;/a&gt; to test shell commands. Why choose Python over those? If you are working on a Python package, it makes sense to use Python, because Python already includes robust test functionality that is easy to integrate with other tools. Testing shell commands from Python allows you to harness those facilities and prevents you from having to keep track of tests in different places. Plus, if you are already familiar with writing tests in Python, writing tests for shell commands becomes a breeze.&lt;/p&gt;
&lt;h3 id=&quot;use-cases&quot;&gt;Use cases&lt;/h3&gt;
&lt;p&gt;For the &lt;a href=&quot;https://github.com/NLeSC/python-template&quot;&gt;Netherlands eScience Center Python package template&lt;/a&gt;, I wanted tests to verify that the generated package can be installed, that the tests can be run, and that the documentation can be generated without errors. My Python text processing package &lt;a href=&quot;https://github.com/nlppln/nlppln&quot;&gt;nlppln&lt;/a&gt; contains &lt;a href=&quot;https://www.commonwl.org/&quot;&gt;CWL&lt;/a&gt; specifications of text mining tools, that can be validated by running them using a command line tool called &lt;code&gt;cwltool&lt;/code&gt;. Another use case would be testing your package’s &lt;a href=&quot;https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html&quot;&gt;console scripts&lt;/a&gt; (although in this case it might be more convenient to use a package for creating command line interfaces that comes with built-in testing functionality, such as &lt;a href=&quot;http://click.pocoo.org/&quot;&gt;Click&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;the-sh-package&quot;&gt;The sh package&lt;/h3&gt;
&lt;p&gt;You can run shell commands from Python using the &lt;a href=&quot;https://docs.python.org/3/library/subprocess.html&quot;&gt;subprocess&lt;/a&gt; module from the Python standard library. However, using this module is a hassle, because you have to do all the error handling yourself. &lt;a href=&quot;https://amoffat.github.io/sh/&quot;&gt;Sh&lt;/a&gt; is a Python package that takes care of all that and allows you to run shell commands using a single line of code. If you want to run &lt;code&gt;python setup.py install&lt;/code&gt;, all you have to do is:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; shsh.python([&apos;setup.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;py&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &apos;install&apos;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to run &lt;code&gt;foo&lt;/code&gt; and it is installed on your system, you can just do &lt;code&gt;sh.foo()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;writing-a-test&quot;&gt;Writing a test&lt;/h3&gt;
&lt;p&gt;So how can we use this for testing? Let’s look at an example. For the Python template, I want to test whether a project generated from the &lt;a href=&quot;https://github.com/audreyr/cookiecutter&quot;&gt;cookiecutter&lt;/a&gt; template can be installed without errors. The goal of the template is to help users write high quality code with less effort, and having an installable empty project is a good first step. The code for the &lt;a href=&quot;https://github.com/NLeSC/python-template/blob/90273feba08376faea12cd154479ba64fbccf81d/tests/test_project.py#L15&quot;&gt;test that tests the installation&lt;/a&gt; is:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pytest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; os&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; shdef test_install(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cookies&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  # generate a temporary project using the cookiecutter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  # cookies fixture&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  project = cookies.bake()                                                    # remember the directory &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tests should be run from&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cwd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; os&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;getcwd&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; change directories to the generated project directory &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (the installation command must be run from here)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  os&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chdir(str(project&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;project))  try&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run the shell command&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python([&apos;setup&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py&apos;, &apos;install&apos;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  except sh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ErrorReturnCode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; as e&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; print the error, so we know what went wrong&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    print(e)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; make sure the test fails&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pytest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fail(e)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  finally&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; always change directories to the test directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    os&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chdir(cwd)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is all there is to it!&lt;/p&gt;
&lt;h3 id=&quot;more-examples&quot;&gt;More examples&lt;/h3&gt;
&lt;p&gt;Of course there is a lot more you can do, e.g., &lt;a href=&quot;https://github.com/NLeSC/python-template/blob/90273feba08376faea12cd154479ba64fbccf81d/tests/test_project.py#L66&quot;&gt;checking whether files exist&lt;/a&gt; after running a shell command, or &lt;a href=&quot;https://github.com/nlppln/nlppln/blob/67bdee66f2ca3f2f15d6764235de619942e148a0/tests/test_prettify_xml.py#L38&quot;&gt;verifying the contents of generated files&lt;/a&gt;. What use cases can you come up with?&lt;/p&gt;
&lt;h3 id=&quot;on-windows-use-subprocess&quot;&gt;On Windows: use subprocess&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://amoffat.github.io/sh/sections/faq.html?highlight=windows#will-windows-be-supported&quot;&gt;Sh does not work on Windows&lt;/a&gt;. If you need to test shell commands on Windows, you are stuck with &lt;a href=&quot;https://docs.python.org/3/library/subprocess.html&quot;&gt;subprocess&lt;/a&gt;. Provenance tracking package &lt;a href=&quot;https://github.com/recipy/recipy&quot;&gt;recipy&lt;/a&gt; contains some nice examples of &lt;a href=&quot;https://github.com/recipy/recipy/blob/c877026602372d85e83b058e833d86e3e407d990/integration_test/test_recipy.py#L93&quot;&gt;tests using subprocess&lt;/a&gt; that might help you on your way.&lt;/p&gt;</description><pubDate>Wed, 12 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1620&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_N20Y3NBxkdLlHLvJpOtxEQ-2b975963.C-Dpalwb_Z1uSdLe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;What to do with these shells?&lt;/p&gt;
&lt;p&gt;How do you test shell commands? Recently, I came across several cases where I wanted to run shell commands for testing, but couldn’t find a tutorial about how to do it from Python. After a lot of Googling, I found a solution that worked for me, and maybe it works for you too!&lt;/p&gt;
&lt;h3 id=&quot;why-test-from-python&quot;&gt;Why test from Python?&lt;/h3&gt;
&lt;p&gt;You could use &lt;a href=&quot;https://spin.atomicobject.com/2016/01/11/command-line-interface-testing-tools/&quot;&gt;dedicated tools&lt;/a&gt; to test shell commands. Why choose Python over those? If you are working on a Python package, it makes sense to use Python, because Python already includes robust test functionality that is easy to integrate with other tools. Testing shell commands from Python allows you to harness those facilities and prevents you from having to keep track of tests in different places. Plus, if you are already familiar with writing tests in Python, writing tests for shell commands becomes a breeze.&lt;/p&gt;
&lt;h3 id=&quot;use-cases&quot;&gt;Use cases&lt;/h3&gt;
&lt;p&gt;For the &lt;a href=&quot;https://github.com/NLeSC/python-template&quot;&gt;Netherlands eScience Center Python package template&lt;/a&gt;, I wanted tests to verify that the generated package can be installed, that the tests can be run, and that the documentation can be generated without errors. My Python text processing package &lt;a href=&quot;https://github.com/nlppln/nlppln&quot;&gt;nlppln&lt;/a&gt; contains &lt;a href=&quot;https://www.commonwl.org/&quot;&gt;CWL&lt;/a&gt; specifications of text mining tools, that can be validated by running them using a command line tool called &lt;code&gt;cwltool&lt;/code&gt;. Another use case would be testing your package’s &lt;a href=&quot;https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html&quot;&gt;console scripts&lt;/a&gt; (although in this case it might be more convenient to use a package for creating command line interfaces that comes with built-in testing functionality, such as &lt;a href=&quot;http://click.pocoo.org/&quot;&gt;Click&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&quot;the-sh-package&quot;&gt;The sh package&lt;/h3&gt;
&lt;p&gt;You can run shell commands from Python using the &lt;a href=&quot;https://docs.python.org/3/library/subprocess.html&quot;&gt;subprocess&lt;/a&gt; module from the Python standard library. However, using this module is a hassle, because you have to do all the error handling yourself. &lt;a href=&quot;https://amoffat.github.io/sh/&quot;&gt;Sh&lt;/a&gt; is a Python package that takes care of all that and allows you to run shell commands using a single line of code. If you want to run &lt;code&gt;python setup.py install&lt;/code&gt;, all you have to do is:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; shsh.python([&apos;setup.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;py&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &apos;install&apos;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to run &lt;code&gt;foo&lt;/code&gt; and it is installed on your system, you can just do &lt;code&gt;sh.foo()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;writing-a-test&quot;&gt;Writing a test&lt;/h3&gt;
&lt;p&gt;So how can we use this for testing? Let’s look at an example. For the Python template, I want to test whether a project generated from the &lt;a href=&quot;https://github.com/audreyr/cookiecutter&quot;&gt;cookiecutter&lt;/a&gt; template can be installed without errors. The goal of the template is to help users write high quality code with less effort, and having an installable empty project is a good first step. The code for the &lt;a href=&quot;https://github.com/NLeSC/python-template/blob/90273feba08376faea12cd154479ba64fbccf81d/tests/test_project.py#L15&quot;&gt;test that tests the installation&lt;/a&gt; is:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pytest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; os&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; shdef test_install(&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;cookies&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  # generate a temporary project using the cookiecutter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  # cookies fixture&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  project = cookies.bake()                                                    # remember the directory &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; tests should be run from&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  cwd &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; os&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;getcwd&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; change directories to the generated project directory &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (the installation command must be run from here)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  os&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chdir(str(project&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;project))  try&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; run the shell command&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    sh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python([&apos;setup&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;py&apos;, &apos;install&apos;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  except sh&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;ErrorReturnCode&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; as e&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; print the error, so we know what went wrong&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    print(e)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; make sure the test fails&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    pytest&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fail(e)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  finally&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    #&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; always change directories to the test directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    os&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;chdir(cwd)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is all there is to it!&lt;/p&gt;
&lt;h3 id=&quot;more-examples&quot;&gt;More examples&lt;/h3&gt;
&lt;p&gt;Of course there is a lot more you can do, e.g., &lt;a href=&quot;https://github.com/NLeSC/python-template/blob/90273feba08376faea12cd154479ba64fbccf81d/tests/test_project.py#L66&quot;&gt;checking whether files exist&lt;/a&gt; after running a shell command, or &lt;a href=&quot;https://github.com/nlppln/nlppln/blob/67bdee66f2ca3f2f15d6764235de619942e148a0/tests/test_prettify_xml.py#L38&quot;&gt;verifying the contents of generated files&lt;/a&gt;. What use cases can you come up with?&lt;/p&gt;
&lt;h3 id=&quot;on-windows-use-subprocess&quot;&gt;On Windows: use subprocess&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://amoffat.github.io/sh/sections/faq.html?highlight=windows#will-windows-be-supported&quot;&gt;Sh does not work on Windows&lt;/a&gt;. If you need to test shell commands on Windows, you are stuck with &lt;a href=&quot;https://docs.python.org/3/library/subprocess.html&quot;&gt;subprocess&lt;/a&gt;. Provenance tracking package &lt;a href=&quot;https://github.com/recipy/recipy&quot;&gt;recipy&lt;/a&gt; contains some nice examples of &lt;a href=&quot;https://github.com/recipy/recipy/blob/c877026602372d85e83b058e833d86e3e407d990/integration_test/test_recipy.py#L93&quot;&gt;tests using subprocess&lt;/a&gt; that might help you on your way.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_N20Y3NBxkdLlHLvJpOtxEQ-2b975963.C-Dpalwb.jpeg" medium="image"/><author>Janneke van der Zwaan</author></item><item><title>the research software directory and how it promotes software citation</title><link>https://blog2.esciencecenter.nl/posts/2018-12-11---the-research-software-directory-and-how-it-promotes-software-citation</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-12-11---the-research-software-directory-and-how-it-promotes-software-citation</guid><description>&lt;h2 id=&quot;improve-the-findability-citability-and-reproducibility-of-research-software&quot;&gt;Improve the findability, citability, and reproducibility of research software&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;705&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KteAGyYbSFJ3vQ2vZYAxww-7a7d8df7.BY11XHjy_gGoiH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, Tom Klaver,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-8172-4865&quot;&gt;&lt;em&gt;Jason Maassen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, (Netherlands eScience Center) and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0003-4925-7248&quot;&gt;&lt;em&gt;Stephan Druskat&lt;/em&gt;&lt;/a&gt; &lt;em&gt;(Humboldt Universität zu Berlin)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center currently employs about 50 Research Software Engineers who work side-by-side with domain scientists to address technological challenges that need to be overcome in order to answer the research questions. As a result, much of the scientific output of our institute comes in the form of software. To show the outside world that our work matters, we wanted a mechanism to improve transparency of our organization, some sort of virtual shop window if you will. This ultimately resulted in development of what we call the &lt;a href=&quot;https://github.com/research-software-directory/research-software-directory&quot;&gt;Research Software Directory&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-content-management-system--tailored-to-software&quot;&gt;A content management system — tailored to software&lt;/h2&gt;
&lt;p&gt;A Research Software Directory is a kind of content management system, tailored to software. A Research Software Directory aims to improve the &lt;em&gt;findability&lt;/em&gt;, &lt;em&gt;citability&lt;/em&gt;, and &lt;em&gt;reproducibility&lt;/em&gt; of the software advertised in it. In practice, this entails creating a so-called &lt;em&gt;product page&lt;/em&gt; for each software package which we want to showcase. A product page presents a given software package along with its relevant context (Figure 1).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;867&quot; height=&quot;976&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UEjKIiw6kEXX6s8BQYp6BQ-c5d469cc.d2Am_0Kk_ZXYzar.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1. Research Software Directory product page. For the live version, go here.&lt;/p&gt;
&lt;h2 id=&quot;understanding-the-journey-of-potential-software-users&quot;&gt;Understanding the journey of potential software users&lt;/h2&gt;
&lt;p&gt;So what makes a good product page? Ultimately, we think it should promote adoption of the software by others. To better understand what that meant in practice, we enlisted the help of communication and design agency &lt;a href=&quot;https://www.siloagency.com/en/&quot;&gt;Silo&lt;/a&gt;, and quickly realized that adoption of software is actually preceded by a few other steps, as follows.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, people need to be able to find the software;&lt;/li&gt;
&lt;li&gt;Then they need to judge whether what they found can potentially contribute to solving to their problem;&lt;/li&gt;
&lt;li&gt;Then they need to be able to get started with using the software;&lt;/li&gt;
&lt;li&gt;Such that they can adopt the software into their own workflow.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At face value, these steps may seem obvious, but it is important to realize that failing even a single step of this ‘journey’ ultimately prohibits adoption of the software. Luckily, for each step there are things that we as developers can do to help make the life of our users easier.&lt;/p&gt;
&lt;h2 id=&quot;improving-the-findability-of-software&quot;&gt;Improving the findability of software&lt;/h2&gt;
&lt;p&gt;For example, most people nowadays use search engines such as Google whenever they are looking for something, so being indexed by Google is an important factor in being found at all. Therefore, in order to maximize our chances of being listed in the first couple of pages of search results, we follow &lt;a href=&quot;https://support.google.com/webmasters/answer/35769?hl=en&quot;&gt;Google’s advice&lt;/a&gt; regarding so-called &lt;em&gt;search engine optimization&lt;/em&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Search_engine_optimization&quot;&gt;SEO&lt;/a&gt;). Generally speaking, Google will like your site better if the search engine has some understanding of what your web page is about. To this end, we add metadata to each product page. The metadata uses vocabularies from &lt;a href=&quot;https://schema.org/&quot;&gt;schema.org&lt;/a&gt; and &lt;a href=&quot;https://codemeta.github.io/&quot;&gt;CodeMeta&lt;/a&gt; to help describe the page’s subject in such a way that Google’s indexing algorithm can understand it.&lt;/p&gt;
&lt;p&gt;It is important to realize though, that many SEO techniques are geared towards optimizing the experience that a website provides to a &lt;em&gt;human&lt;/em&gt; visitor. Generally speaking, human visitors will like your site better if it presents relevant information in a clear and concise manner. So, when describing the software, we try to make it very easy to consume the page’s content, by using inclusive language as much as possible, and by steering clear of acronyms.&lt;/p&gt;
&lt;p&gt;Similarly, human visitors benefit if the subject of a web page is presented alongside its context. For this reason, the software on each product page is presented along with related presentations, blogs, YouTube videos, whitepapers, tweets, posters, peer-reviewed papers, as well as descriptions of projects in which the software was applied (Figure 2). This allows people to quickly judge if a given software package is interesting for them, while providing machines with the necessary information to place the web page in the appropriate filter bubble.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1336&quot; height=&quot;1573&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0Zk6MV-9GAdsj842QtYWFw-2ad65125.Cwt9Dnyp_Z1wdC7p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2. These sections help visitors judge the software by placing it within the relevant (scientific) context. For the live version, go here.&lt;/p&gt;
&lt;p&gt;By offering attractive product pages with relevant information, and by following Google’s SEO guidelines, the Research Software Directory thus improves the findability of our software, for machines as well as for humans.&lt;/p&gt;
&lt;p&gt;So let’s say that a visitor has used Google to look for a solution to a problem they are having, and found one of our product pages. They liked what they saw there, but now they want to give our software a whirl. Where should they start? For this, we added a prominent &lt;em&gt;Get started&lt;/em&gt; button, which links to additional materials that help first time users to get started with the software. Examples of such materials include tutorials (e.g. PDF documents), interactive examples (e.g. on &lt;a href=&quot;https://codeocean.com/&quot;&gt;codeocean.com&lt;/a&gt;, &lt;a href=&quot;https://mybinder.org/&quot;&gt;mybinder.org&lt;/a&gt;, or &lt;a href=&quot;https://renkulab.io/&quot;&gt;renkulab.io&lt;/a&gt;), and video walkthroughs (e.g. demonstrating how to use a graphical interface to accomplish a given task). Naturally, creating such additional materials requires an extra effort, sometimes considerably so, but good entry level documentation can be really valuable in attracting users.&lt;/p&gt;
&lt;p&gt;By designing the product pages in this way, we feel that the findability of software is reasonably well covered. Next, let’s take a look at citability.&lt;/p&gt;
&lt;h2 id=&quot;citability&quot;&gt;Citability&lt;/h2&gt;
&lt;p&gt;We chose to make the &lt;em&gt;Cite this software&lt;/em&gt; element (Figure 3) quite a prominent part of the product page. We did so because it emphasizes that software is something that you can, and &lt;a href=&quot;https://cite.research-software.org/&quot;&gt;indeed should&lt;/a&gt;, cite. Furthermore, we wanted to make citing as easy as possible. The importance of the latter reason should not be underestimated: Citing research software is intrinsically more difficult than citing, say, research papers, because relevant information is often a lot less obvious. For example, a person wanting to cite software may face questions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the name of the software (given that it’s probably not&lt;br&gt;
&lt;code&gt;my_scripts/run.m&lt;/code&gt; or &lt;code&gt;analysis.py&lt;/code&gt;)?&lt;/li&gt;
&lt;li&gt;What label should I use to uniquely identify the version of the software?&lt;/li&gt;
&lt;li&gt;What is the appropriate set of people that should be identified as authors?
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1230&quot; height=&quot;259&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1G6Z9_KIZo4PN40y1nBQQw-f66fef60.DINVwLoj_Z1izI6P.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Figure 3. ‘Cite this software’ element.&lt;/p&gt;
&lt;p&gt;The burden of answering these questions typically lies with the person who wants to cite, even though we, as the developers of the software, are in a much better position to answer those questions accurately and consistently. The &lt;em&gt;Cite this software&lt;/em&gt; element therefore provides the information necessary for citation. The element is constructed as follows. Firstly, we keep our source code in public repositories on &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;. For our repositories, we have enabled the &lt;a href=&quot;https://guides.github.com/activities/citable-code/&quot;&gt;GitHub-Zenodo integration&lt;/a&gt;. Thanks to this integration, &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt; stores a snapshot of our code whenever we make a release on GitHub. The snapshot is stored for long term archiving, and Zenodo sticks a persistent identifier (a &lt;a href=&quot;https://en.wikipedia.org/wiki/Digital_object_identifier&quot;&gt;Digital Object Identifier&lt;/a&gt; or DOI, to be exact) on it, so that the specific version of the software may be referenced. Of course this doesn’t guarantee full reproducibility, but at least it is a step in the right direction. Zenodo further provides another DOI that serves as an identifier for the software project as a whole (i.e., all versions together). Zenodo refers to this version-agnostic type of identifier as a &lt;em&gt;conceptDOI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This simple workflow provides basic citability, meaning that without doing anything else, we can already adorn the product page with DOIs for each version of the software. That’s nice, but of course we want to facilitate automated generation of reference manager files (specifically, BibTeX, EndNote and RIS files), for each version of the software. To this end, we ask our engineers to add a &lt;code&gt;CITATION.cff&lt;/code&gt; file to their source code repositories. In short, such files constitute an instruction to users of the software on how it should be cited [&lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://www.software.ac.uk/blog/2017-12-12-standard-format-citation-files&quot;&gt;2&lt;/a&gt;]. Because &lt;code&gt;CITATION.cff&lt;/code&gt; files are formatted according to the Citation File Format specification, they are machine readable, which in turn allowed us to write the &lt;code&gt;cffconvert&lt;/code&gt; Python package that can read citation metadata and convert it to various reference manager formats.&lt;/p&gt;
&lt;h2 id=&quot;the-backend&quot;&gt;The backend&lt;/h2&gt;
&lt;p&gt;After designing and prototyping the frontend, we started work on the backend so we could feed the frontend with the necessary data. We realized that much of the data that we needed was already available from sources such as Zenodo, GitHub, &lt;a href=&quot;https://www.zotero.org/&quot;&gt;Zotero&lt;/a&gt; (the reference manager we use to keep track of our organization’s output) and so forth. Some of these data sources provide access to their data via an API, but for some others, the data were available, but not in a very structured way. As an example, we wanted to include the contents of [our blog]( which uses the Medium publishing platform. As far as we could determine, the blog posts could not be retrieved via the API, so we ended up writing a simple Python script using the &lt;a href=&quot;https://www.crummy.com/software/BeautifulSoup/&quot;&gt;BeautifulSoup&lt;/a&gt; library to harvest this data. Similarly, we wanted to include project descriptions from &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;esciencecenter.nl/projects&lt;/a&gt; which were not accessible via an API, so again we used BeautifulSoup to harvest what we needed.&lt;/p&gt;
&lt;p&gt;With the data harvesting mechanisms in place, we were left with designing a system that would allow our engineers to create, edit, and delete product pages. To make life as easy as possible for them, we chose to use a web form for this. For lack of a better name, we refer to the web form simply as the &lt;em&gt;Admin interface&lt;/em&gt; (Figure 4).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;978&quot; height=&quot;976&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WDAeUR0xu0MLK9OY0b9KDQ-88f363a9.BW9oEunm_Z70vIw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4. Admin interface to a product page.&lt;/p&gt;
&lt;p&gt;For each input field, the Admin interface provides brief instructions on what to enter, so our engineers know what is expected of them. The Admin interface also performs formal form validation against the &lt;a href=&quot;https://github.com/research-software-directory/backend/tree/fb586b3bde46f3b067f6bdbb98c54d65cc9b88b3/schemas&quot;&gt;schema&lt;/a&gt;, such that the data that ends up being fed to the frontend is predictable, which in turn leads to cleaner code in the frontend.&lt;/p&gt;
&lt;p&gt;Most of the required fields need to be filled in only once; for example, the &lt;code&gt;conceptDOI&lt;/code&gt;, repository URLs, the name of the package, and the descriptions will not change very often. Some other fields however are changeable, for example the list of contributors may grow or there may be additional mentions. Generally speaking, our engineers revisit their pages every couple of months or so, to see if anything needs to be added.&lt;/p&gt;
&lt;h2 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h2&gt;
&lt;p&gt;At the Netherlands eScience Center we have created the Research Software Directory to improve the findability, citability, and reproducibility of the software that we create in our projects. We use it to show our software to the world, and to illustrate the impact our software has had in research. You can find our Research Software Directory at &lt;a href=&quot;https://www.research-software.nl/&quot;&gt;research-software.nl&lt;/a&gt;. Like all our software, it is open source and completely free to use and adapt. So if you’re interested, feel free to &lt;a href=&quot;https://github.com/research-software-directory/research-software-directory&quot;&gt;set up your own instance&lt;/a&gt;!&lt;/p&gt;</description><pubDate>Tue, 11 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;improve-the-findability-citability-and-reproducibility-of-research-software&quot;&gt;Improve the findability, citability, and reproducibility of research software&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;705&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KteAGyYbSFJ3vQ2vZYAxww-7a7d8df7.BY11XHjy_gGoiH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;By&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-7064-4069&quot;&gt;&lt;em&gt;Jurriaan H. Spaaks&lt;/em&gt;&lt;/a&gt;&lt;em&gt;,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-5821-2060&quot;&gt;&lt;em&gt;Stefan Verhoeven&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, Tom Klaver,&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0002-8172-4865&quot;&gt;&lt;em&gt;Jason Maassen&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, (Netherlands eScience Center) and&lt;/em&gt; &lt;a href=&quot;https://orcid.org/0000-0003-4925-7248&quot;&gt;&lt;em&gt;Stephan Druskat&lt;/em&gt;&lt;/a&gt; &lt;em&gt;(Humboldt Universität zu Berlin)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Netherlands eScience Center currently employs about 50 Research Software Engineers who work side-by-side with domain scientists to address technological challenges that need to be overcome in order to answer the research questions. As a result, much of the scientific output of our institute comes in the form of software. To show the outside world that our work matters, we wanted a mechanism to improve transparency of our organization, some sort of virtual shop window if you will. This ultimately resulted in development of what we call the &lt;a href=&quot;https://github.com/research-software-directory/research-software-directory&quot;&gt;Research Software Directory&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-content-management-system--tailored-to-software&quot;&gt;A content management system — tailored to software&lt;/h2&gt;
&lt;p&gt;A Research Software Directory is a kind of content management system, tailored to software. A Research Software Directory aims to improve the &lt;em&gt;findability&lt;/em&gt;, &lt;em&gt;citability&lt;/em&gt;, and &lt;em&gt;reproducibility&lt;/em&gt; of the software advertised in it. In practice, this entails creating a so-called &lt;em&gt;product page&lt;/em&gt; for each software package which we want to showcase. A product page presents a given software package along with its relevant context (Figure 1).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;867&quot; height=&quot;976&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UEjKIiw6kEXX6s8BQYp6BQ-c5d469cc.d2Am_0Kk_ZXYzar.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 1. Research Software Directory product page. For the live version, go here.&lt;/p&gt;
&lt;h2 id=&quot;understanding-the-journey-of-potential-software-users&quot;&gt;Understanding the journey of potential software users&lt;/h2&gt;
&lt;p&gt;So what makes a good product page? Ultimately, we think it should promote adoption of the software by others. To better understand what that meant in practice, we enlisted the help of communication and design agency &lt;a href=&quot;https://www.siloagency.com/en/&quot;&gt;Silo&lt;/a&gt;, and quickly realized that adoption of software is actually preceded by a few other steps, as follows.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, people need to be able to find the software;&lt;/li&gt;
&lt;li&gt;Then they need to judge whether what they found can potentially contribute to solving to their problem;&lt;/li&gt;
&lt;li&gt;Then they need to be able to get started with using the software;&lt;/li&gt;
&lt;li&gt;Such that they can adopt the software into their own workflow.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At face value, these steps may seem obvious, but it is important to realize that failing even a single step of this ‘journey’ ultimately prohibits adoption of the software. Luckily, for each step there are things that we as developers can do to help make the life of our users easier.&lt;/p&gt;
&lt;h2 id=&quot;improving-the-findability-of-software&quot;&gt;Improving the findability of software&lt;/h2&gt;
&lt;p&gt;For example, most people nowadays use search engines such as Google whenever they are looking for something, so being indexed by Google is an important factor in being found at all. Therefore, in order to maximize our chances of being listed in the first couple of pages of search results, we follow &lt;a href=&quot;https://support.google.com/webmasters/answer/35769?hl=en&quot;&gt;Google’s advice&lt;/a&gt; regarding so-called &lt;em&gt;search engine optimization&lt;/em&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Search_engine_optimization&quot;&gt;SEO&lt;/a&gt;). Generally speaking, Google will like your site better if the search engine has some understanding of what your web page is about. To this end, we add metadata to each product page. The metadata uses vocabularies from &lt;a href=&quot;https://schema.org/&quot;&gt;schema.org&lt;/a&gt; and &lt;a href=&quot;https://codemeta.github.io/&quot;&gt;CodeMeta&lt;/a&gt; to help describe the page’s subject in such a way that Google’s indexing algorithm can understand it.&lt;/p&gt;
&lt;p&gt;It is important to realize though, that many SEO techniques are geared towards optimizing the experience that a website provides to a &lt;em&gt;human&lt;/em&gt; visitor. Generally speaking, human visitors will like your site better if it presents relevant information in a clear and concise manner. So, when describing the software, we try to make it very easy to consume the page’s content, by using inclusive language as much as possible, and by steering clear of acronyms.&lt;/p&gt;
&lt;p&gt;Similarly, human visitors benefit if the subject of a web page is presented alongside its context. For this reason, the software on each product page is presented along with related presentations, blogs, YouTube videos, whitepapers, tweets, posters, peer-reviewed papers, as well as descriptions of projects in which the software was applied (Figure 2). This allows people to quickly judge if a given software package is interesting for them, while providing machines with the necessary information to place the web page in the appropriate filter bubble.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1336&quot; height=&quot;1573&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0Zk6MV-9GAdsj842QtYWFw-2ad65125.Cwt9Dnyp_Z1wdC7p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 2. These sections help visitors judge the software by placing it within the relevant (scientific) context. For the live version, go here.&lt;/p&gt;
&lt;p&gt;By offering attractive product pages with relevant information, and by following Google’s SEO guidelines, the Research Software Directory thus improves the findability of our software, for machines as well as for humans.&lt;/p&gt;
&lt;p&gt;So let’s say that a visitor has used Google to look for a solution to a problem they are having, and found one of our product pages. They liked what they saw there, but now they want to give our software a whirl. Where should they start? For this, we added a prominent &lt;em&gt;Get started&lt;/em&gt; button, which links to additional materials that help first time users to get started with the software. Examples of such materials include tutorials (e.g. PDF documents), interactive examples (e.g. on &lt;a href=&quot;https://codeocean.com/&quot;&gt;codeocean.com&lt;/a&gt;, &lt;a href=&quot;https://mybinder.org/&quot;&gt;mybinder.org&lt;/a&gt;, or &lt;a href=&quot;https://renkulab.io/&quot;&gt;renkulab.io&lt;/a&gt;), and video walkthroughs (e.g. demonstrating how to use a graphical interface to accomplish a given task). Naturally, creating such additional materials requires an extra effort, sometimes considerably so, but good entry level documentation can be really valuable in attracting users.&lt;/p&gt;
&lt;p&gt;By designing the product pages in this way, we feel that the findability of software is reasonably well covered. Next, let’s take a look at citability.&lt;/p&gt;
&lt;h2 id=&quot;citability&quot;&gt;Citability&lt;/h2&gt;
&lt;p&gt;We chose to make the &lt;em&gt;Cite this software&lt;/em&gt; element (Figure 3) quite a prominent part of the product page. We did so because it emphasizes that software is something that you can, and &lt;a href=&quot;https://cite.research-software.org/&quot;&gt;indeed should&lt;/a&gt;, cite. Furthermore, we wanted to make citing as easy as possible. The importance of the latter reason should not be underestimated: Citing research software is intrinsically more difficult than citing, say, research papers, because relevant information is often a lot less obvious. For example, a person wanting to cite software may face questions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the name of the software (given that it’s probably not&lt;br&gt;
&lt;code&gt;my_scripts/run.m&lt;/code&gt; or &lt;code&gt;analysis.py&lt;/code&gt;)?&lt;/li&gt;
&lt;li&gt;What label should I use to uniquely identify the version of the software?&lt;/li&gt;
&lt;li&gt;What is the appropriate set of people that should be identified as authors?
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1230&quot; height=&quot;259&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1G6Z9_KIZo4PN40y1nBQQw-f66fef60.DINVwLoj_Z1izI6P.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Figure 3. ‘Cite this software’ element.&lt;/p&gt;
&lt;p&gt;The burden of answering these questions typically lies with the person who wants to cite, even though we, as the developers of the software, are in a much better position to answer those questions accurately and consistently. The &lt;em&gt;Cite this software&lt;/em&gt; element therefore provides the information necessary for citation. The element is constructed as follows. Firstly, we keep our source code in public repositories on &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;. For our repositories, we have enabled the &lt;a href=&quot;https://guides.github.com/activities/citable-code/&quot;&gt;GitHub-Zenodo integration&lt;/a&gt;. Thanks to this integration, &lt;a href=&quot;https://zenodo.org/&quot;&gt;Zenodo&lt;/a&gt; stores a snapshot of our code whenever we make a release on GitHub. The snapshot is stored for long term archiving, and Zenodo sticks a persistent identifier (a &lt;a href=&quot;https://en.wikipedia.org/wiki/Digital_object_identifier&quot;&gt;Digital Object Identifier&lt;/a&gt; or DOI, to be exact) on it, so that the specific version of the software may be referenced. Of course this doesn’t guarantee full reproducibility, but at least it is a step in the right direction. Zenodo further provides another DOI that serves as an identifier for the software project as a whole (i.e., all versions together). Zenodo refers to this version-agnostic type of identifier as a &lt;em&gt;conceptDOI&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This simple workflow provides basic citability, meaning that without doing anything else, we can already adorn the product page with DOIs for each version of the software. That’s nice, but of course we want to facilitate automated generation of reference manager files (specifically, BibTeX, EndNote and RIS files), for each version of the software. To this end, we ask our engineers to add a &lt;code&gt;CITATION.cff&lt;/code&gt; file to their source code repositories. In short, such files constitute an instruction to users of the software on how it should be cited [&lt;a href=&quot;https://citation-file-format.github.io/&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://www.software.ac.uk/blog/2017-12-12-standard-format-citation-files&quot;&gt;2&lt;/a&gt;]. Because &lt;code&gt;CITATION.cff&lt;/code&gt; files are formatted according to the Citation File Format specification, they are machine readable, which in turn allowed us to write the &lt;code&gt;cffconvert&lt;/code&gt; Python package that can read citation metadata and convert it to various reference manager formats.&lt;/p&gt;
&lt;h2 id=&quot;the-backend&quot;&gt;The backend&lt;/h2&gt;
&lt;p&gt;After designing and prototyping the frontend, we started work on the backend so we could feed the frontend with the necessary data. We realized that much of the data that we needed was already available from sources such as Zenodo, GitHub, &lt;a href=&quot;https://www.zotero.org/&quot;&gt;Zotero&lt;/a&gt; (the reference manager we use to keep track of our organization’s output) and so forth. Some of these data sources provide access to their data via an API, but for some others, the data were available, but not in a very structured way. As an example, we wanted to include the contents of [our blog]( which uses the Medium publishing platform. As far as we could determine, the blog posts could not be retrieved via the API, so we ended up writing a simple Python script using the &lt;a href=&quot;https://www.crummy.com/software/BeautifulSoup/&quot;&gt;BeautifulSoup&lt;/a&gt; library to harvest this data. Similarly, we wanted to include project descriptions from &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;esciencecenter.nl/projects&lt;/a&gt; which were not accessible via an API, so again we used BeautifulSoup to harvest what we needed.&lt;/p&gt;
&lt;p&gt;With the data harvesting mechanisms in place, we were left with designing a system that would allow our engineers to create, edit, and delete product pages. To make life as easy as possible for them, we chose to use a web form for this. For lack of a better name, we refer to the web form simply as the &lt;em&gt;Admin interface&lt;/em&gt; (Figure 4).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;978&quot; height=&quot;976&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WDAeUR0xu0MLK9OY0b9KDQ-88f363a9.BW9oEunm_Z70vIw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Figure 4. Admin interface to a product page.&lt;/p&gt;
&lt;p&gt;For each input field, the Admin interface provides brief instructions on what to enter, so our engineers know what is expected of them. The Admin interface also performs formal form validation against the &lt;a href=&quot;https://github.com/research-software-directory/backend/tree/fb586b3bde46f3b067f6bdbb98c54d65cc9b88b3/schemas&quot;&gt;schema&lt;/a&gt;, such that the data that ends up being fed to the frontend is predictable, which in turn leads to cleaner code in the frontend.&lt;/p&gt;
&lt;p&gt;Most of the required fields need to be filled in only once; for example, the &lt;code&gt;conceptDOI&lt;/code&gt;, repository URLs, the name of the package, and the descriptions will not change very often. Some other fields however are changeable, for example the list of contributors may grow or there may be additional mentions. Generally speaking, our engineers revisit their pages every couple of months or so, to see if anything needs to be added.&lt;/p&gt;
&lt;h2 id=&quot;final-remarks&quot;&gt;Final remarks&lt;/h2&gt;
&lt;p&gt;At the Netherlands eScience Center we have created the Research Software Directory to improve the findability, citability, and reproducibility of the software that we create in our projects. We use it to show our software to the world, and to illustrate the impact our software has had in research. You can find our Research Software Directory at &lt;a href=&quot;https://www.research-software.nl/&quot;&gt;research-software.nl&lt;/a&gt;. Like all our software, it is open source and completely free to use and adapt. So if you’re interested, feel free to &lt;a href=&quot;https://github.com/research-software-directory/research-software-directory&quot;&gt;set up your own instance&lt;/a&gt;!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_UEjKIiw6kEXX6s8BQYp6BQ-c5d469cc.d2Am_0Kk.png" medium="image"/><author>Jurriaan H. Spaaks</author></item><item><title>how do we evaluate research software to meet different requirements</title><link>https://blog2.esciencecenter.nl/posts/2018-12-03---how-do-we-evaluate-research-software-to-meet-different-requirements</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-12-03---how-do-we-evaluate-research-software-to-meet-different-requirements</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mOfFxGkE0FP-eQ30xoYxlQ-533fe1a4.jnvZJbN7_Z9rGex.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software written to solve research questions gains more recognition as a research result of its own and requires evaluation in terms of usability as well as its potential to facilitate high-impact and reproducible research. Indeed, in recent times there has been increased emphasis on the importance of reproducibility in science — particularly of results where software is involved. In order to tackle this problem, there have been efforts to evaluate reproducibility of research results. For instance, one could use different metrics to evaluate important aspects for software such as quality, findability, and, of course, reproducibility.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;evaluation-requirements-from-different-perspectives&quot;&gt;Evaluation requirements from different perspectives&lt;/h2&gt;
&lt;p&gt;The evaluation of Research Software should consist of several perspectives and the use of tools or application of a framework heavily depends on these perspectives. (see “ &lt;a href=&quot;https://figshare.com/articles/Setting_up_a_Software_Seal_of_Approval/4737178/1&quot;&gt;Setting Up a Software Seal Approval&lt;/a&gt; ”, slide 3)&lt;/p&gt;
&lt;p&gt;There is the funder’s perspective where it is most interesting how funding has changed how people do software-based science. The following aspects play a role:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Number of people or research projects using it. This could be measured by letting the software “phone home” or crawl the web for active installations. The number of citations to the software itself (e.g. using &lt;a href=&quot;https://doi.org/10.25504/FAIRsharing.m2NU20&quot;&gt;Citation File Format (CFF)&lt;/a&gt;) or citations to articles mentioning the software could be used as an approximation. Social media mentions also indicate impact to a certain degree.&lt;/li&gt;
&lt;li&gt;Funders may encourage &lt;a href=&quot;http://repeatability.cs.arizona.edu/index.html&quot;&gt;repeatability studies&lt;/a&gt; and positive outcome for some software-related experiments may satisfy funding agencies.&lt;/li&gt;
&lt;li&gt;The funder’s perspective definitely needs some future work which starts at making software a ”First class citizen of research’’ in terms of recognition and management. It will be challenging for funders to develop fair recognition framework to treat or review all the virgin or mature projects according to their expected milestones. &lt;a href=&quot;https://www.software.ac.uk/resources/online-sustainability-evaluation&quot;&gt;Sustainability&lt;/a&gt; of software may play a major role here. Availability, usability, maintainability, portability are all aspects of software which determine its sustainability (see “ &lt;a href=&quot;https://figshare.com/articles/Setting_up_a_Software_Seal_of_Approval/4737178/1&quot;&gt;Setting Up a Software Seal Approval&lt;/a&gt; ”, slide 4). Funders may also want to &lt;a href=&quot;http://www.orfg.org/incentivization-blueprint&quot;&gt;incentivise the sharing of code&lt;/a&gt; for better evaluation options.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The developer’s perspective for evaluating their code will probably include quality measures like test coverage or code coverage and to follow certain development process standards. The output of a code linter may contain flags indicating the (lack of) quality for a piece of code (which may influence career perspectives for e.g. coding PostDocs).&lt;/p&gt;
&lt;p&gt;There is the user’s perspective where possible reuse of existing research software may be the main focus during evaluation. Users may want to run the code with their own data in executable environments (e.g. in &lt;a href=&quot;https://help.codeocean.com/?q=Capsule&quot;&gt;Code Ocean “Capsules”&lt;/a&gt;). And users will probably also investigate how a version control system is used and how the community looks like. Much more detailed “ &lt;a href=&quot;http://software.ac.uk/sites/default/files/SSI-SoftwareEvaluationCriteria.pdf&quot;&gt;criteria-based software evaluation&lt;/a&gt; ” guides are available at the &lt;a href=&quot;https://software.ac.uk/resources/guides-everything/software-evaluation-guide&quot;&gt;Software Sustainability Institute&lt;/a&gt;. &lt;a href=&quot;https://www.questionpro.com/survey-templates/software-evaluation/&quot;&gt;Other survey resources&lt;/a&gt; shall inspire individual software evaluation.&lt;/p&gt;
&lt;h2 id=&quot;ideas-on-how-to-evaluate-research-software-quantitatively&quot;&gt;Ideas on how to evaluate research software quantitatively&lt;/h2&gt;
&lt;p&gt;We have discussed key aspects related to helping others to select research software to meet different requirements. For example, a scientist would like to solve a particular problem in their domain and seeks a tool for solving this problem. How would this researchers select their tools and based on what criteria would they make this decision. Some ideas for such criteria and for making such decisions are presented below.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Identification of key important metrics that are useful and easy to generate. This may include the identification of pre-existing that compute metrics.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;1 — When creating a metric framework one should consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What am I measuring?&lt;/li&gt;
&lt;li&gt;Why am I measuring it?&lt;/li&gt;
&lt;li&gt;How am I measuring it?&lt;br&gt;
a) What are the inputs?&lt;br&gt;
b) What are the outputs?&lt;br&gt;
c) What is a pass / fail / how are we giving a score?&lt;/li&gt;
&lt;li&gt;Who should define the metrics?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2 — Examples of metrics for assessing software quality and reusability are linters, code coverage, and code evaluation tools.&lt;/p&gt;
&lt;p&gt;3 — Examples of research impact metrics are downloads, contributors, citations, and publications/impact factors derived from software.&lt;/p&gt;
&lt;p&gt;4 — Examples of metrics for assessing transparency of software, e.g. documentation (high level description of what the software does as well as inline code documentation), references to papers describing the algorithms used, and communication of software development and maintenance processes.&lt;/p&gt;
&lt;p&gt;5 — Another set of metrics that could be useful would be metrics for understanding how easy it is to install and manage dependencies. For example, it is installable via popular package management systems or via a single container.&lt;/p&gt;
&lt;p&gt;6 — A metric of replicability and provenance of the results generated by the software: the software should be able to encapsulate the data with the associated configuration, parameters and related context (version control of software, system it was built on, number of processes used, runtime telemetry).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Badge systems — combine metrics through standards to develop a software quality rating system.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It is our hope that the sum total of the criteria in Section C could be used to develop a more formal, but easy-to-use system of evaluation such as the aforementioned badge system. In addition, we hope that by presenting to the community key goals for development of research software that we will incentivise best practices.&lt;/p&gt;
&lt;p&gt;We should ideally agree on what metrics are important to evaluate some of these aspects. Different communities might come with different agreements. For instance, &lt;a href=&quot;https://elixir-europe.org/&quot;&gt;ELIXIR&lt;/a&gt; and &lt;a href=&quot;https://www.egi.eu/&quot;&gt;EGI&lt;/a&gt; might have different ideas about what to evaluate and how to evaluate, for instance quality. Different agreements are fine as far as each community defines what are the important metrics to evaluate something (e.g. quality) and they wrap them up into a badge that people (the community) can identify and understand. This way so people will be able to say I am compliant with that badge tailored to measure one specific aspect. Software could be compliant with more than one badge.&lt;/p&gt;
&lt;p&gt;For every badge, it would important to identify and describe the metrics part of the badge. For the description of metrics it would be helpful to agree on how we describe metrics. A citation metric, for instance, might mean different things to different people and there might be different methodologies to collect the data that makes the metric mean different things. So for the badge to work, each metric part of the badge needs to be very well described in a consistent manner.&lt;/p&gt;
&lt;h2 id=&quot;the-need-to-develop-and-adopt-a-framework-for-community-metrics&quot;&gt;The need to develop and adopt a framework for community metrics&lt;/h2&gt;
&lt;p&gt;At the moment what we miss is a metadata standard to consistently describe metrics and a framework to be able to group metrics into badges. A framework to discover badges that also helps users, organisations and funders to say what badges they support. This framework is not a metrics framework to collect data but a framework to define and describe badges and their metrics. Different metrics frameworks collecting metrics data like &lt;a href=&quot;https://fairshake.cloud/&quot;&gt;FAIRshake&lt;/a&gt;, &lt;a href=&quot;http://dx.doi.org/10.1101/418376&quot;&gt;FAIR evaluator&lt;/a&gt;, &lt;a href=&quot;https://elixir.bsc.es/&quot;&gt;OpenEbench&lt;/a&gt; could be used to evaluate the metrics defined by a badge.&lt;/p&gt;
&lt;p&gt;In summary, it becomes clear that metrics and badges for research software are urgently needed, but are still a long way off.The roadmap may look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Evaluate pre-existing badge systems. Starting points are:&lt;/li&gt;
&lt;li&gt;Badges related to software development practices&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://figshare.com/articles/Setting_up_a_Software_Seal_of_Approval/4737178/1&quot;&gt;Software Seal of Approval&lt;/a&gt; (inherited from DSoA)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://libraries.io/&quot;&gt;Libraries.io&lt;/a&gt;, to manage software projects and dependencies on other packages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ropensci.org/&quot;&gt;ropensci.org&lt;/a&gt; — to peer review of packages, resulting in accession to a curated register.&lt;/li&gt;
&lt;li&gt;Create a badge for 4OSS&lt;/li&gt;
&lt;li&gt;Create a badge for FAIR software metrics&lt;/li&gt;
&lt;li&gt;Collaborate with funders on “interesting” metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It would be nice if volunteers from the RSE community could be found to make progress here.&lt;/p&gt;
&lt;p&gt;Relevant contacts can be found at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;The Software Sustainability Institute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://urssi.us/&quot;&gt;URSSI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.de-rse.org/en&quot;&gt;RSE groups in UK, NL, DE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.allianzinitiative.de/fields-of-action-projects/digital-tools-software-and-services/?lang=en&quot;&gt;Alliance of Science Organisations in Germany, i.e. Digital tools — software and services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Collaborate with developers in a community to identify “interesting” metrics&lt;/li&gt;
&lt;li&gt;Collaborate with users in a community to identify “interesting” metrics&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Mon, 03 Dec 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mOfFxGkE0FP-eQ30xoYxlQ-533fe1a4.jnvZJbN7_Z9rGex.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Software written to solve research questions gains more recognition as a research result of its own and requires evaluation in terms of usability as well as its potential to facilitate high-impact and reproducible research. Indeed, in recent times there has been increased emphasis on the importance of reproducibility in science — particularly of results where software is involved. In order to tackle this problem, there have been efforts to evaluate reproducibility of research results. For instance, one could use different metrics to evaluate important aspects for software such as quality, findability, and, of course, reproducibility.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;evaluation-requirements-from-different-perspectives&quot;&gt;Evaluation requirements from different perspectives&lt;/h2&gt;
&lt;p&gt;The evaluation of Research Software should consist of several perspectives and the use of tools or application of a framework heavily depends on these perspectives. (see “ &lt;a href=&quot;https://figshare.com/articles/Setting_up_a_Software_Seal_of_Approval/4737178/1&quot;&gt;Setting Up a Software Seal Approval&lt;/a&gt; ”, slide 3)&lt;/p&gt;
&lt;p&gt;There is the funder’s perspective where it is most interesting how funding has changed how people do software-based science. The following aspects play a role:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Number of people or research projects using it. This could be measured by letting the software “phone home” or crawl the web for active installations. The number of citations to the software itself (e.g. using &lt;a href=&quot;https://doi.org/10.25504/FAIRsharing.m2NU20&quot;&gt;Citation File Format (CFF)&lt;/a&gt;) or citations to articles mentioning the software could be used as an approximation. Social media mentions also indicate impact to a certain degree.&lt;/li&gt;
&lt;li&gt;Funders may encourage &lt;a href=&quot;http://repeatability.cs.arizona.edu/index.html&quot;&gt;repeatability studies&lt;/a&gt; and positive outcome for some software-related experiments may satisfy funding agencies.&lt;/li&gt;
&lt;li&gt;The funder’s perspective definitely needs some future work which starts at making software a ”First class citizen of research’’ in terms of recognition and management. It will be challenging for funders to develop fair recognition framework to treat or review all the virgin or mature projects according to their expected milestones. &lt;a href=&quot;https://www.software.ac.uk/resources/online-sustainability-evaluation&quot;&gt;Sustainability&lt;/a&gt; of software may play a major role here. Availability, usability, maintainability, portability are all aspects of software which determine its sustainability (see “ &lt;a href=&quot;https://figshare.com/articles/Setting_up_a_Software_Seal_of_Approval/4737178/1&quot;&gt;Setting Up a Software Seal Approval&lt;/a&gt; ”, slide 4). Funders may also want to &lt;a href=&quot;http://www.orfg.org/incentivization-blueprint&quot;&gt;incentivise the sharing of code&lt;/a&gt; for better evaluation options.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The developer’s perspective for evaluating their code will probably include quality measures like test coverage or code coverage and to follow certain development process standards. The output of a code linter may contain flags indicating the (lack of) quality for a piece of code (which may influence career perspectives for e.g. coding PostDocs).&lt;/p&gt;
&lt;p&gt;There is the user’s perspective where possible reuse of existing research software may be the main focus during evaluation. Users may want to run the code with their own data in executable environments (e.g. in &lt;a href=&quot;https://help.codeocean.com/?q=Capsule&quot;&gt;Code Ocean “Capsules”&lt;/a&gt;). And users will probably also investigate how a version control system is used and how the community looks like. Much more detailed “ &lt;a href=&quot;http://software.ac.uk/sites/default/files/SSI-SoftwareEvaluationCriteria.pdf&quot;&gt;criteria-based software evaluation&lt;/a&gt; ” guides are available at the &lt;a href=&quot;https://software.ac.uk/resources/guides-everything/software-evaluation-guide&quot;&gt;Software Sustainability Institute&lt;/a&gt;. &lt;a href=&quot;https://www.questionpro.com/survey-templates/software-evaluation/&quot;&gt;Other survey resources&lt;/a&gt; shall inspire individual software evaluation.&lt;/p&gt;
&lt;h2 id=&quot;ideas-on-how-to-evaluate-research-software-quantitatively&quot;&gt;Ideas on how to evaluate research software quantitatively&lt;/h2&gt;
&lt;p&gt;We have discussed key aspects related to helping others to select research software to meet different requirements. For example, a scientist would like to solve a particular problem in their domain and seeks a tool for solving this problem. How would this researchers select their tools and based on what criteria would they make this decision. Some ideas for such criteria and for making such decisions are presented below.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Identification of key important metrics that are useful and easy to generate. This may include the identification of pre-existing that compute metrics.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;1 — When creating a metric framework one should consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What am I measuring?&lt;/li&gt;
&lt;li&gt;Why am I measuring it?&lt;/li&gt;
&lt;li&gt;How am I measuring it?&lt;br&gt;
a) What are the inputs?&lt;br&gt;
b) What are the outputs?&lt;br&gt;
c) What is a pass / fail / how are we giving a score?&lt;/li&gt;
&lt;li&gt;Who should define the metrics?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2 — Examples of metrics for assessing software quality and reusability are linters, code coverage, and code evaluation tools.&lt;/p&gt;
&lt;p&gt;3 — Examples of research impact metrics are downloads, contributors, citations, and publications/impact factors derived from software.&lt;/p&gt;
&lt;p&gt;4 — Examples of metrics for assessing transparency of software, e.g. documentation (high level description of what the software does as well as inline code documentation), references to papers describing the algorithms used, and communication of software development and maintenance processes.&lt;/p&gt;
&lt;p&gt;5 — Another set of metrics that could be useful would be metrics for understanding how easy it is to install and manage dependencies. For example, it is installable via popular package management systems or via a single container.&lt;/p&gt;
&lt;p&gt;6 — A metric of replicability and provenance of the results generated by the software: the software should be able to encapsulate the data with the associated configuration, parameters and related context (version control of software, system it was built on, number of processes used, runtime telemetry).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Badge systems — combine metrics through standards to develop a software quality rating system.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It is our hope that the sum total of the criteria in Section C could be used to develop a more formal, but easy-to-use system of evaluation such as the aforementioned badge system. In addition, we hope that by presenting to the community key goals for development of research software that we will incentivise best practices.&lt;/p&gt;
&lt;p&gt;We should ideally agree on what metrics are important to evaluate some of these aspects. Different communities might come with different agreements. For instance, &lt;a href=&quot;https://elixir-europe.org/&quot;&gt;ELIXIR&lt;/a&gt; and &lt;a href=&quot;https://www.egi.eu/&quot;&gt;EGI&lt;/a&gt; might have different ideas about what to evaluate and how to evaluate, for instance quality. Different agreements are fine as far as each community defines what are the important metrics to evaluate something (e.g. quality) and they wrap them up into a badge that people (the community) can identify and understand. This way so people will be able to say I am compliant with that badge tailored to measure one specific aspect. Software could be compliant with more than one badge.&lt;/p&gt;
&lt;p&gt;For every badge, it would important to identify and describe the metrics part of the badge. For the description of metrics it would be helpful to agree on how we describe metrics. A citation metric, for instance, might mean different things to different people and there might be different methodologies to collect the data that makes the metric mean different things. So for the badge to work, each metric part of the badge needs to be very well described in a consistent manner.&lt;/p&gt;
&lt;h2 id=&quot;the-need-to-develop-and-adopt-a-framework-for-community-metrics&quot;&gt;The need to develop and adopt a framework for community metrics&lt;/h2&gt;
&lt;p&gt;At the moment what we miss is a metadata standard to consistently describe metrics and a framework to be able to group metrics into badges. A framework to discover badges that also helps users, organisations and funders to say what badges they support. This framework is not a metrics framework to collect data but a framework to define and describe badges and their metrics. Different metrics frameworks collecting metrics data like &lt;a href=&quot;https://fairshake.cloud/&quot;&gt;FAIRshake&lt;/a&gt;, &lt;a href=&quot;http://dx.doi.org/10.1101/418376&quot;&gt;FAIR evaluator&lt;/a&gt;, &lt;a href=&quot;https://elixir.bsc.es/&quot;&gt;OpenEbench&lt;/a&gt; could be used to evaluate the metrics defined by a badge.&lt;/p&gt;
&lt;p&gt;In summary, it becomes clear that metrics and badges for research software are urgently needed, but are still a long way off.The roadmap may look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Evaluate pre-existing badge systems. Starting points are:&lt;/li&gt;
&lt;li&gt;Badges related to software development practices&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://figshare.com/articles/Setting_up_a_Software_Seal_of_Approval/4737178/1&quot;&gt;Software Seal of Approval&lt;/a&gt; (inherited from DSoA)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://libraries.io/&quot;&gt;Libraries.io&lt;/a&gt;, to manage software projects and dependencies on other packages.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ropensci.org/&quot;&gt;ropensci.org&lt;/a&gt; — to peer review of packages, resulting in accession to a curated register.&lt;/li&gt;
&lt;li&gt;Create a badge for 4OSS&lt;/li&gt;
&lt;li&gt;Create a badge for FAIR software metrics&lt;/li&gt;
&lt;li&gt;Collaborate with funders on “interesting” metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It would be nice if volunteers from the RSE community could be found to make progress here.&lt;/p&gt;
&lt;p&gt;Relevant contacts can be found at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.software.ac.uk/&quot;&gt;The Software Sustainability Institute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://urssi.us/&quot;&gt;URSSI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.de-rse.org/en&quot;&gt;RSE groups in UK, NL, DE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.allianzinitiative.de/fields-of-action-projects/digital-tools-software-and-services/?lang=en&quot;&gt;Alliance of Science Organisations in Germany, i.e. Digital tools — software and services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Collaborate with developers in a community to identify “interesting” metrics&lt;/li&gt;
&lt;li&gt;Collaborate with users in a community to identify “interesting” metrics&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_mOfFxGkE0FP-eQ30xoYxlQ-533fe1a4.jnvZJbN7.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>nice hydrographs for everyone from everyone</title><link>https://blog2.esciencecenter.nl/posts/2018-11-29---nice-hydrographs-for-everyone-from-everyone</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-11-29---nice-hydrographs-for-everyone-from-everyone</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1335&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_N3tLDW1E26SIaXiq52OOiA-043872bb.BYmwTlLr_Z1LczmW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;nice-hydrographs-can-you-now-compare-your-model-to-that-other-hydrology-groups-model&quot;&gt;“Nice hydrographs! Can you now compare your model to ‘that other hydrology groups model’?”&lt;/h2&gt;
&lt;p&gt;The phd student suppresses the urge to roll her eyes. Her supervisor is asking her to go back into code-hell. That other model is written in Fortran and she works in Python. It took her two months to get the Python model used in her group running in the first place. Realizing she needed to install an obtuse library on her computer needed by a hidden part of the hydrological model that the post-doc who left science four months ago had added took her two weeks alone. She doesn’t look forward to installing an other institutes favorite model just to compare its output to hers. It will mean getting back behind the computer working on getting someone else’s code to run and not on using her hydrology skills for a few more weeks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;2037&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tWlNAgC9-9vdCsZ0TLo_oA-6b031d8b.DTzhv_Vh_Z1gvD5s.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Most computational hydrology is not reproducible, so is it really science?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Scientifically her supervisor is right, of course. If a hydrologist improves an existing model ideally one would not only like to compare the model output to observations, but also to other models. However, running someone else’s model is often a pain. It is no coincidence that model comparison papers often involve all the groups responsible for the different models being run in the study.&lt;/p&gt;
&lt;p&gt;As Chris Hutton et. al. said in an opinion paper: “Most computational hydrology is not reproducible, so is it really science?”(*1). In the ensuing discussion Nick van de Giesen (Delft University of Technology), Niels Drost (Netherlands eScience Center) and I argued that to increase the reproducibility, but also the reusability, of hydrologic models we should present them in such a way that they can be run independent of a local computer, ie. in virtual machines or the lightweight equivalent: containers. In the &lt;a href=&quot;https://www.ewatercycle.org/&quot;&gt;eWaterCycle II project&lt;/a&gt; we are putting our money(*2) where our mouths are and are building a system that easily lets hydrologist do just that.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jf64V268zNb931xeV3rJFA-ea9780e5.GTjFRhvU_Z22W6Ku.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The goal we have for the eWaterCycle II project is to provide the hydrological community with tools that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allow the use of a wide variety of models, written in different programming languages, without having to learn those languages.&lt;/li&gt;
&lt;li&gt;Run models needing large amounts of memory and CPUs.&lt;/li&gt;
&lt;li&gt;Have access to all the relevant datasets from the community (forcing, observations).&lt;/li&gt;
&lt;li&gt;Allow advanced use cases such as data assimilation and model coupling studies.&lt;/li&gt;
&lt;li&gt;Allow the sharing of models with the entire community, both for citing (DOIs) and re-use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately providing hydrologists with a toolset that allows them to run each other models, but also adept, couple, and in general tinker with models without the headache of having to delve into each others detailed code.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Q9Doww3A-kIupuUuzH099Q-34d746b1.BTIWs3ki_paSsD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;633&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_BSs-A7UD4LvwfBWG-6c9dabfc.BzIjOyqx_Z1ldiIy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;minimum-viable-product&quot;&gt;Minimum Viable Product&lt;/h2&gt;
&lt;p&gt;Currently six months into this three year project, we have created a “minimal viable product (MVP)(*3)”, a first, duck-taped version of what we intend to build. To gauge in the hydrological community if we’re moving in the right direction. In our MVP scientists can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get started with modelling without installing a single piece of software(*4).&lt;/li&gt;
&lt;li&gt;Run any of the available models within minutes.&lt;/li&gt;
&lt;li&gt;Develop code quickly in a notebook environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DEyuHeBBPaQ7-nncEKRm1g-96d0192c.DuCUI8TO_2774yl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The MVP currently runs on a cloud computer with limited compute and is far from production ready, so access is restricted to project members. Medio 2019 we intend to deploy the system on more robust infrastructure and open up the environment for the entire hydrological community to try out. The video below shows a screencast of the MVP in action. In it we select a model from our experiment finder. We automatically generate a jupyter notebook with python code that runs the model and plots a hydrograph. The model is not part of the notebook: it is a process in a separate container that talks to the notebook.&lt;/p&gt;
&lt;p&gt;“Minimum Viable Product” demo.&lt;/p&gt;
&lt;h2 id=&quot;a-future-where-hydrologist-can-produce-reproducible-results&quot;&gt;A future where hydrologist can produce reproducible results&lt;/h2&gt;
&lt;p&gt;Had the model of ‘that other hydrology group’ be in our system, than the phd student from the start of this blog wouldn’t have to despair: three clicks and she could have looked at a hydrograph. Our MVP allows hydrologist to quickly run pre-existing models, compare outputs of different models and change the model state during the run to do experiments. We hope that our project contributes to a future where hydrologist can produce reproducible results and thus can build on each others work more easily. If you would like to be amongst the first to work with the our system, if you want to add your model to it, or if you just want to provide us feedback please let us know in a comment below!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3204&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_oihdbRG9rcIx6DBuXdm1gA-4a0e2f89.CNBmN0T3_ok7BJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The eWaterCycle project team, from left to right: Jerom Aerts (Delft University of Technology), Maarten van Meersbergen (eScience Center), Rolf Hut (Delft University of Technology), Yifat Dzigan, Inti Pelupessy, Berend Weel and Martine de Vos (eScience Center), Toju Babalola ( Federal University Oye-Ekiti, Nigeria), Niels Drost, Gijs van den Oord and Ben van Werkhoven (eScience Center)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;**About eWaterCycle II&lt;br&gt;
**Understanding water movement on a global scale is essential for society to predict floods, droughts and the effect of land use on water balance. However, large scale hydrology is difficult because, from a hydrological point of view, every field, every street, and every part of the world is unique. We are able to understand and describe how water moves in these locations at a local scale, but due to the extreme spatial variability it is difficult to capture such processes at a global scale. We call this the curse of locality.&lt;/p&gt;
&lt;p&gt;On top of this, existing hydrological models exist in a huge variety of programming languages, standards etc. which limits their re-usability and reproducibility. In the eWaterCycle II project, we are developing a framework in which hydrological modellers can work together in a collaborative environment.&lt;br&gt;
&lt;a href=&quot;https://www.ewatercycle.org/&quot;&gt;www.ewatercycle.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Hutton, C., T. Wagener, J. Freer, D. Han, C. Duffy, and B. Arheimer (2016), Most computational hydrology is not reproducible, so is it really science?, Water Resour. Res., 52, 7548–7555, doi: 10.1002/2016WR019285.&lt;/li&gt;
&lt;li&gt;Well, our funders money, but you get the point.&lt;/li&gt;
&lt;li&gt;A method of developing copied from start-up culture and software development. One of the benefits of working with a multidisciplinary team of experts is that they provide one with new ways of approaching a project.&lt;/li&gt;
&lt;li&gt;Well, ok, a web browser.&lt;/li&gt;
&lt;/ol&gt;</description><pubDate>Thu, 29 Nov 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1335&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_N3tLDW1E26SIaXiq52OOiA-043872bb.BYmwTlLr_Z1LczmW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;nice-hydrographs-can-you-now-compare-your-model-to-that-other-hydrology-groups-model&quot;&gt;“Nice hydrographs! Can you now compare your model to ‘that other hydrology groups model’?”&lt;/h2&gt;
&lt;p&gt;The phd student suppresses the urge to roll her eyes. Her supervisor is asking her to go back into code-hell. That other model is written in Fortran and she works in Python. It took her two months to get the Python model used in her group running in the first place. Realizing she needed to install an obtuse library on her computer needed by a hidden part of the hydrological model that the post-doc who left science four months ago had added took her two weeks alone. She doesn’t look forward to installing an other institutes favorite model just to compare its output to hers. It will mean getting back behind the computer working on getting someone else’s code to run and not on using her hydrology skills for a few more weeks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;2037&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tWlNAgC9-9vdCsZ0TLo_oA-6b031d8b.DTzhv_Vh_Z1gvD5s.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Most computational hydrology is not reproducible, so is it really science?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Scientifically her supervisor is right, of course. If a hydrologist improves an existing model ideally one would not only like to compare the model output to observations, but also to other models. However, running someone else’s model is often a pain. It is no coincidence that model comparison papers often involve all the groups responsible for the different models being run in the study.&lt;/p&gt;
&lt;p&gt;As Chris Hutton et. al. said in an opinion paper: “Most computational hydrology is not reproducible, so is it really science?”(*1). In the ensuing discussion Nick van de Giesen (Delft University of Technology), Niels Drost (Netherlands eScience Center) and I argued that to increase the reproducibility, but also the reusability, of hydrologic models we should present them in such a way that they can be run independent of a local computer, ie. in virtual machines or the lightweight equivalent: containers. In the &lt;a href=&quot;https://www.ewatercycle.org/&quot;&gt;eWaterCycle II project&lt;/a&gt; we are putting our money(*2) where our mouths are and are building a system that easily lets hydrologist do just that.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jf64V268zNb931xeV3rJFA-ea9780e5.GTjFRhvU_Z22W6Ku.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The goal we have for the eWaterCycle II project is to provide the hydrological community with tools that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allow the use of a wide variety of models, written in different programming languages, without having to learn those languages.&lt;/li&gt;
&lt;li&gt;Run models needing large amounts of memory and CPUs.&lt;/li&gt;
&lt;li&gt;Have access to all the relevant datasets from the community (forcing, observations).&lt;/li&gt;
&lt;li&gt;Allow advanced use cases such as data assimilation and model coupling studies.&lt;/li&gt;
&lt;li&gt;Allow the sharing of models with the entire community, both for citing (DOIs) and re-use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately providing hydrologists with a toolset that allows them to run each other models, but also adept, couple, and in general tinker with models without the headache of having to delve into each others detailed code.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Q9Doww3A-kIupuUuzH099Q-34d746b1.BTIWs3ki_paSsD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;633&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_BSs-A7UD4LvwfBWG-6c9dabfc.BzIjOyqx_Z1ldiIy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;minimum-viable-product&quot;&gt;Minimum Viable Product&lt;/h2&gt;
&lt;p&gt;Currently six months into this three year project, we have created a “minimal viable product (MVP)(*3)”, a first, duck-taped version of what we intend to build. To gauge in the hydrological community if we’re moving in the right direction. In our MVP scientists can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get started with modelling without installing a single piece of software(*4).&lt;/li&gt;
&lt;li&gt;Run any of the available models within minutes.&lt;/li&gt;
&lt;li&gt;Develop code quickly in a notebook environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DEyuHeBBPaQ7-nncEKRm1g-96d0192c.DuCUI8TO_2774yl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The MVP currently runs on a cloud computer with limited compute and is far from production ready, so access is restricted to project members. Medio 2019 we intend to deploy the system on more robust infrastructure and open up the environment for the entire hydrological community to try out. The video below shows a screencast of the MVP in action. In it we select a model from our experiment finder. We automatically generate a jupyter notebook with python code that runs the model and plots a hydrograph. The model is not part of the notebook: it is a process in a separate container that talks to the notebook.&lt;/p&gt;
&lt;p&gt;“Minimum Viable Product” demo.&lt;/p&gt;
&lt;h2 id=&quot;a-future-where-hydrologist-can-produce-reproducible-results&quot;&gt;A future where hydrologist can produce reproducible results&lt;/h2&gt;
&lt;p&gt;Had the model of ‘that other hydrology group’ be in our system, than the phd student from the start of this blog wouldn’t have to despair: three clicks and she could have looked at a hydrograph. Our MVP allows hydrologist to quickly run pre-existing models, compare outputs of different models and change the model state during the run to do experiments. We hope that our project contributes to a future where hydrologist can produce reproducible results and thus can build on each others work more easily. If you would like to be amongst the first to work with the our system, if you want to add your model to it, or if you just want to provide us feedback please let us know in a comment below!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3204&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_oihdbRG9rcIx6DBuXdm1gA-4a0e2f89.CNBmN0T3_ok7BJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The eWaterCycle project team, from left to right: Jerom Aerts (Delft University of Technology), Maarten van Meersbergen (eScience Center), Rolf Hut (Delft University of Technology), Yifat Dzigan, Inti Pelupessy, Berend Weel and Martine de Vos (eScience Center), Toju Babalola ( Federal University Oye-Ekiti, Nigeria), Niels Drost, Gijs van den Oord and Ben van Werkhoven (eScience Center)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;**About eWaterCycle II&lt;br&gt;
**Understanding water movement on a global scale is essential for society to predict floods, droughts and the effect of land use on water balance. However, large scale hydrology is difficult because, from a hydrological point of view, every field, every street, and every part of the world is unique. We are able to understand and describe how water moves in these locations at a local scale, but due to the extreme spatial variability it is difficult to capture such processes at a global scale. We call this the curse of locality.&lt;/p&gt;
&lt;p&gt;On top of this, existing hydrological models exist in a huge variety of programming languages, standards etc. which limits their re-usability and reproducibility. In the eWaterCycle II project, we are developing a framework in which hydrological modellers can work together in a collaborative environment.&lt;br&gt;
&lt;a href=&quot;https://www.ewatercycle.org/&quot;&gt;www.ewatercycle.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Hutton, C., T. Wagener, J. Freer, D. Han, C. Duffy, and B. Arheimer (2016), Most computational hydrology is not reproducible, so is it really science?, Water Resour. Res., 52, 7548–7555, doi: 10.1002/2016WR019285.&lt;/li&gt;
&lt;li&gt;Well, our funders money, but you get the point.&lt;/li&gt;
&lt;li&gt;A method of developing copied from start-up culture and software development. One of the benefits of working with a multidisciplinary team of experts is that they provide one with new ways of approaching a project.&lt;/li&gt;
&lt;li&gt;Well, ok, a web browser.&lt;/li&gt;
&lt;/ol&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_tWlNAgC9-9vdCsZ0TLo_oA-6b031d8b.DTzhv_Vh.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Why more scientists should attend SIGGGRAPH for inspiration!</title><link>https://blog2.esciencecenter.nl/posts/2018-09-27---why-more-scientists-should-attend-sigggraph-for-inspiration</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-09-27---why-more-scientists-should-attend-sigggraph-for-inspiration</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4000&quot; height=&quot;603&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_bhrYc7NjpacyJ64gwFACSQ-aa6a14d8.CBQshmHM_Z2gx6TA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This year I was lucky enough to be able to travel to the city of Vancouver to attend the SIGGRAPH 2018 conference, the annual conference on computer graphics convened by the ACM SIGGRAPH organization. What I learned there was most of all that I want to go every year! What a great source of knowledge and inspiration!&lt;/p&gt;
&lt;p&gt;In this blog post I will summarize my experiences along the following themes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Courses&lt;/li&gt;
&lt;li&gt;Papers and posters&lt;/li&gt;
&lt;li&gt;Production sessions&lt;/li&gt;
&lt;li&gt;Birds of a Feather and Khronos-specific events&lt;/li&gt;
&lt;li&gt;Keynote talks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope this will give you some insight into the SIGGRAPH conference and what it can offer.&lt;/p&gt;
&lt;h2 id=&quot;courses&quot;&gt;Courses&lt;/h2&gt;
&lt;p&gt;Many courses were offered at the conference, with a wide range of topics related to computer graphics, machine learning, animation and more. The full list can be found &lt;a href=&quot;https://s2018.siggraph.org/conference/conference-overview/courses/&quot;&gt;here&lt;/a&gt;. I’ve attended two of these; &lt;em&gt;Introduction to the Vulkan Graphics API&lt;/em&gt; and &lt;a href=&quot;http://intro-to-dxr.cwyman.org/&quot;&gt;&lt;em&gt;Introduction to DirectX Raytracing&lt;/em&gt;&lt;/a&gt;. The website of the second is quite comprehensive so in the interest of not making this blog &lt;em&gt;too&lt;/em&gt; extensive, I’ll leave that to you to explore if you want.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;611&quot; height=&quot;814&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_g8BdoXVRbTApuzEOjUYKRQ-edf396b8.DXBs_O6g_2exRht.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;introduction-to-the-vulkan-graphics-api&quot;&gt;Introduction to the Vulkan Graphics API&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;(material&lt;/strong&gt; &lt;a href=&quot;http://web.engr.oregonstate.edu/~mjb/vulkan/Handouts/ABRIDGED.1pp.pdf&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vulkan goals:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;much less driver complexity and overhead than OpenGL has&lt;/li&gt;
&lt;li&gt;much less user hand-holding&lt;/li&gt;
&lt;li&gt;higher single-threaded performance than OpenGL can deliver&lt;/li&gt;
&lt;li&gt;able to do multithreaded graphics&lt;/li&gt;
&lt;li&gt;able to handle tiled rendering&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;main-takeaways&quot;&gt;Main takeaways:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Screen coordinate system is Y-down (internally LEFT-handed)&lt;/li&gt;
&lt;li&gt;No “current state”, at least not one maintained by the driver (Synchronization is the responsibility of the application)&lt;/li&gt;
&lt;li&gt;All transformation, color, texture functionality must be done in shaders&lt;/li&gt;
&lt;li&gt;Shaders are pre-”half-compiled” outside of your application. The compilation process is then finished during the pipeline-building process (Your shaders get turned into an intermediate form known as SPIR-V )&lt;/li&gt;
&lt;li&gt;Data Buffers for everything!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;technical-papers-and-posters&quot;&gt;Technical papers and posters&lt;/h2&gt;
&lt;p&gt;Now we get to the meat of the conference and the main reason I was there. The technical papers tracks were excellent, and the way SIGGRAPH introduces the talks there is equally good. The Sunday evening programme included a 2-hour fast-forward session in which the presenters each had 30 seconds to introduce their talk and try to get people to attend. With the conference App in hand, it was easy to register the talks that you peaked your interest, and assemble your personal schedule.&lt;/p&gt;
&lt;p&gt;Here’s a selection of the fast-forwards to the talks I attended, please let me know if you want to know more!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=1805&amp;#x26;end=1839&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Synthetic depth-of-field with a single camera mobile phone&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=1839&amp;#x26;end=1874&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Stereo magnification&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=2017&amp;#x26;end=2049&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;FaceVR&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(VR conference without VR headsets)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=2049&amp;#x26;end=2084&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Deep appearance models for face rendering&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=2510&amp;#x26;end=2540&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Natural boundary conditions for smoothing&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=3459&amp;#x26;end=3490&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Water surface wavelets&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=3490&amp;#x26;end=3525&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;TempoGAN&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Deep learning smoke)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;750&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1hJampYm5dmZzf0_O8hRRQ-eb31375d.DtWmG5Id_2ekYgg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;some of the posters at the siggraph 2018 conference&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5595&amp;#x26;end=5629&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;High performace software rendering pipeline&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5595&amp;#x26;end=5664&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Slang&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5773&amp;#x26;end=5804&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Mode-adaptive neural networks for quadruped motion control&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5843&amp;#x26;end=5876&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Physical simulation of environmentally induced thin shell deformation&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5876&amp;#x26;end=5911&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;A material point method for thin shells with frictional contact&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5951&amp;#x26;end=5983&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Animating fluid sediment mixture&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=6443&amp;#x26;end=6475&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Skaterbots&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=6549&amp;#x26;end=6581&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Deep video portraits&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=6581&amp;#x26;end=6615&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Headon, real time reenactment of human portrait videos&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main takeaway here for me are that Computer Graphics(CG) nowadays is heavily dependent on Neural Networks and much of the latest research in Neural networks has direct implications in this bleeding-edge field.&lt;br&gt;
Attending also reaffirmed my belief that many scientists can benefit from knowing the latest and greatest in Computer Graphics.&lt;/p&gt;
&lt;p&gt;Not only because physics simulations and animation are rapidly approaching realism or that the latest techniques in CG can have significant impact in other fields, but also because it is very important to show to the public what science is all about. The more enthusiastic we can get the public about science, the better!&lt;/p&gt;
&lt;h2 id=&quot;birds-of-a-feather-sessions&quot;&gt;Birds of a Feather sessions&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1849&quot; height=&quot;462&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r5jZBdvOEhy10nH2Pqyg2Q-2bdc044a.Bc1pWFR9_1uIQ6p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;These sessions focus on bringing communities together and stimulate the sharing of knowledge. This is (mostly) done by showing applications that make use of certain libraries, as well as presenting the updates to said libraries and planned future work and attempting to involve the audience in discussions on the future direction of the library or field.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/embed/r-5ADuoFNws?start=338&amp;#x26;end=861&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;CesiumJS: 3D globes on the web&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please check the link for many exciting talks about the new capabilities of CesiumJS as well as applications and future directions. I especially liked the new point cloud options in Cesium as well as the procedural terrain shading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scaling up 3D Medical Applications for people everywhere&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Talks on medical domain applications of 3D. Here’s some links to excellent examples I picked up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/VolumeRC/MIRROR4all&quot;&gt;https://github.com/VolumeRC/MIRROR4all&lt;/a&gt; (Medical Image Rendering Online for Real people)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://metagrid2.sv.vt.edu/~chris526/zbb/&quot;&gt;Zebrafish browser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://vnhm.de/VNHM/index.php&quot;&gt;Virtual Natural History Museum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://3dprint.nih.gov/&quot;&gt;3dprint.nih.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;khronos-events&quot;&gt;Khronos events&lt;/h2&gt;
&lt;p&gt;The consortium for open standards in 3d graphics and much more, the Khronos Group organized its own sessions which were filled with discussions and presentations on the current state of OpenGL and Vulkan, WebGL (2.0) and more. I managed to catch a few of these, most notably:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1218&quot; height=&quot;289&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sk5bXLmgG-2jhtLBDgkHzQ-a4e828ba.Dk9t5yQD_5PHpj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/FCAM-3aAzXg?start=7335&amp;#x26;end=7553&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;WebGL: Latest techniques&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/FCAM-3aAzXg?start=8677&amp;#x26;end=9009&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Uber&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;’s&lt;/strong&gt; &lt;a href=&quot;http://vis.gl/&quot;&gt;&lt;strong&gt;Vis.gl&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;http://deck.gl/&quot;&gt;&lt;strong&gt;Deck.gl&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;http://kepler.gl/&quot;&gt;&lt;strong&gt;Kepler.gl&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;https://neb.gl/&quot;&gt;&lt;strong&gt;Nebula.gl&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/%20FCAM-3aAzXg?start=10087&amp;#x26;end=10416&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Sub-centimeter pointclouds in Cesium&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/FCAM-3aAzXg?start=10442&amp;#x26;end=11129&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Ricardo Cabello, THREE.js founder, discussing the state of the art&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;production-sessions&quot;&gt;“Production sessions”&lt;/h2&gt;
&lt;p&gt;These are not really my core business so I couldn’t attend a lot of these, but oh my what a source of inspiration. The production sessions at SIGGRAPH are all about implementing visual effects techniques, mostly in movies and games. These are the ones I attended:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DNEG, Framestore, and MPC Present: The Visual Effects of “Blade Runner 2049”&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Making the Kessel Run in Less Than 12 Parsecs — The VFX of “Solo: A Star Wars Story”&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Making of Marvel Studios’ “Avengers: Infinity War”&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;talks&quot;&gt;Talks&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;370&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_p77ONGFKyvZKJjbVGRWGlQ-b4e7c46e.Byq7MFjb_Zz61am.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Not necessarily scientific talks, these elaborate on the full range of computer graphics and interactive techniques, including case studies, academic research, technical developments, improved pipeline tools, education and curriculum, professional development, or social commentary.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;StarWars: The Last Jedi — Effects Simulation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Collocated Spatially Adaptive Approach to Smoke Simulation in Bifrost&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rampage: A Pipelined Approach to Managing Large Scale Character Driven Effects&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SimpleBullet: Collaborating on a Modular Destruction Toolkit&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;last-but-not-least-keynotes&quot;&gt;Last but not least: Keynotes&lt;/h2&gt;
&lt;p&gt;Of course there were keynotes!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=kUoIbP1l9yA&quot;&gt;&lt;strong&gt;Rob Bredow: Star Wars: Solo&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An inspiring presentation by the executive creative director of Industrial Light and Magic (ILM) about the philosophy behind the making of Star Wars: Solo, as well as an inspirational talk for the upcoming generation in VFX.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Mrixi27G9yM&quot;&gt;&lt;strong&gt;Jen-Hsun Huang: Gforce RTX&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;launch&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It was amazing to be present at this monumental moment for 3D graphics. Real-time ray tracing was always “the future” and even though a lot of deep learning trickery is still needed for denoising the images, being able to have a working implementation of this already is an astounding achievement. The links below bring you directly to the most inspiring and interesting moments in the presentation on YouTube:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;944&quot; height=&quot;527&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XWFlmYkdpAQ-hLKcMXZ3TQ-0ed1d48f.CGlvDm_s_NJL6f.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;and-then-there-was-computer-animation-festival&quot;&gt;And then there was… computer animation festival&lt;/h2&gt;
&lt;p&gt;Another recurring feature of SIGGRAPH, the computer animation festival is a celebration of computer graphics and visual effects used for storytelling. Some trailers to the short films shown are here:&lt;/p&gt;</description><pubDate>Thu, 27 Sep 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4000&quot; height=&quot;603&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_bhrYc7NjpacyJ64gwFACSQ-aa6a14d8.CBQshmHM_Z2gx6TA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This year I was lucky enough to be able to travel to the city of Vancouver to attend the SIGGRAPH 2018 conference, the annual conference on computer graphics convened by the ACM SIGGRAPH organization. What I learned there was most of all that I want to go every year! What a great source of knowledge and inspiration!&lt;/p&gt;
&lt;p&gt;In this blog post I will summarize my experiences along the following themes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Courses&lt;/li&gt;
&lt;li&gt;Papers and posters&lt;/li&gt;
&lt;li&gt;Production sessions&lt;/li&gt;
&lt;li&gt;Birds of a Feather and Khronos-specific events&lt;/li&gt;
&lt;li&gt;Keynote talks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope this will give you some insight into the SIGGRAPH conference and what it can offer.&lt;/p&gt;
&lt;h2 id=&quot;courses&quot;&gt;Courses&lt;/h2&gt;
&lt;p&gt;Many courses were offered at the conference, with a wide range of topics related to computer graphics, machine learning, animation and more. The full list can be found &lt;a href=&quot;https://s2018.siggraph.org/conference/conference-overview/courses/&quot;&gt;here&lt;/a&gt;. I’ve attended two of these; &lt;em&gt;Introduction to the Vulkan Graphics API&lt;/em&gt; and &lt;a href=&quot;http://intro-to-dxr.cwyman.org/&quot;&gt;&lt;em&gt;Introduction to DirectX Raytracing&lt;/em&gt;&lt;/a&gt;. The website of the second is quite comprehensive so in the interest of not making this blog &lt;em&gt;too&lt;/em&gt; extensive, I’ll leave that to you to explore if you want.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;611&quot; height=&quot;814&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_g8BdoXVRbTApuzEOjUYKRQ-edf396b8.DXBs_O6g_2exRht.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;introduction-to-the-vulkan-graphics-api&quot;&gt;Introduction to the Vulkan Graphics API&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;(material&lt;/strong&gt; &lt;a href=&quot;http://web.engr.oregonstate.edu/~mjb/vulkan/Handouts/ABRIDGED.1pp.pdf&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vulkan goals:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;much less driver complexity and overhead than OpenGL has&lt;/li&gt;
&lt;li&gt;much less user hand-holding&lt;/li&gt;
&lt;li&gt;higher single-threaded performance than OpenGL can deliver&lt;/li&gt;
&lt;li&gt;able to do multithreaded graphics&lt;/li&gt;
&lt;li&gt;able to handle tiled rendering&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;main-takeaways&quot;&gt;Main takeaways:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Screen coordinate system is Y-down (internally LEFT-handed)&lt;/li&gt;
&lt;li&gt;No “current state”, at least not one maintained by the driver (Synchronization is the responsibility of the application)&lt;/li&gt;
&lt;li&gt;All transformation, color, texture functionality must be done in shaders&lt;/li&gt;
&lt;li&gt;Shaders are pre-”half-compiled” outside of your application. The compilation process is then finished during the pipeline-building process (Your shaders get turned into an intermediate form known as SPIR-V )&lt;/li&gt;
&lt;li&gt;Data Buffers for everything!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;technical-papers-and-posters&quot;&gt;Technical papers and posters&lt;/h2&gt;
&lt;p&gt;Now we get to the meat of the conference and the main reason I was there. The technical papers tracks were excellent, and the way SIGGRAPH introduces the talks there is equally good. The Sunday evening programme included a 2-hour fast-forward session in which the presenters each had 30 seconds to introduce their talk and try to get people to attend. With the conference App in hand, it was easy to register the talks that you peaked your interest, and assemble your personal schedule.&lt;/p&gt;
&lt;p&gt;Here’s a selection of the fast-forwards to the talks I attended, please let me know if you want to know more!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=1805&amp;#x26;end=1839&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Synthetic depth-of-field with a single camera mobile phone&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=1839&amp;#x26;end=1874&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Stereo magnification&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=2017&amp;#x26;end=2049&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;FaceVR&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(VR conference without VR headsets)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=2049&amp;#x26;end=2084&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Deep appearance models for face rendering&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=2510&amp;#x26;end=2540&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Natural boundary conditions for smoothing&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=3459&amp;#x26;end=3490&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Water surface wavelets&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=3490&amp;#x26;end=3525&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;TempoGAN&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Deep learning smoke)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;750&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1hJampYm5dmZzf0_O8hRRQ-eb31375d.DtWmG5Id_2ekYgg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;some of the posters at the siggraph 2018 conference&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5595&amp;#x26;end=5629&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;High performace software rendering pipeline&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5595&amp;#x26;end=5664&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Slang&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5773&amp;#x26;end=5804&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Mode-adaptive neural networks for quadruped motion control&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5843&amp;#x26;end=5876&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Physical simulation of environmentally induced thin shell deformation&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5876&amp;#x26;end=5911&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;A material point method for thin shells with frictional contact&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=5951&amp;#x26;end=5983&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Animating fluid sediment mixture&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=6443&amp;#x26;end=6475&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Skaterbots&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=6549&amp;#x26;end=6581&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Deep video portraits&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/CV_14aUBxsI?start=6581&amp;#x26;end=6615&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Headon, real time reenactment of human portrait videos&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main takeaway here for me are that Computer Graphics(CG) nowadays is heavily dependent on Neural Networks and much of the latest research in Neural networks has direct implications in this bleeding-edge field.&lt;br&gt;
Attending also reaffirmed my belief that many scientists can benefit from knowing the latest and greatest in Computer Graphics.&lt;/p&gt;
&lt;p&gt;Not only because physics simulations and animation are rapidly approaching realism or that the latest techniques in CG can have significant impact in other fields, but also because it is very important to show to the public what science is all about. The more enthusiastic we can get the public about science, the better!&lt;/p&gt;
&lt;h2 id=&quot;birds-of-a-feather-sessions&quot;&gt;Birds of a Feather sessions&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1849&quot; height=&quot;462&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r5jZBdvOEhy10nH2Pqyg2Q-2bdc044a.Bc1pWFR9_1uIQ6p.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;These sessions focus on bringing communities together and stimulate the sharing of knowledge. This is (mostly) done by showing applications that make use of certain libraries, as well as presenting the updates to said libraries and planned future work and attempting to involve the audience in discussions on the future direction of the library or field.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/embed/r-5ADuoFNws?start=338&amp;#x26;end=861&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;CesiumJS: 3D globes on the web&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please check the link for many exciting talks about the new capabilities of CesiumJS as well as applications and future directions. I especially liked the new point cloud options in Cesium as well as the procedural terrain shading.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scaling up 3D Medical Applications for people everywhere&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Talks on medical domain applications of 3D. Here’s some links to excellent examples I picked up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/VolumeRC/MIRROR4all&quot;&gt;https://github.com/VolumeRC/MIRROR4all&lt;/a&gt; (Medical Image Rendering Online for Real people)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://metagrid2.sv.vt.edu/~chris526/zbb/&quot;&gt;Zebrafish browser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://vnhm.de/VNHM/index.php&quot;&gt;Virtual Natural History Museum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://3dprint.nih.gov/&quot;&gt;3dprint.nih.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;khronos-events&quot;&gt;Khronos events&lt;/h2&gt;
&lt;p&gt;The consortium for open standards in 3d graphics and much more, the Khronos Group organized its own sessions which were filled with discussions and presentations on the current state of OpenGL and Vulkan, WebGL (2.0) and more. I managed to catch a few of these, most notably:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1218&quot; height=&quot;289&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sk5bXLmgG-2jhtLBDgkHzQ-a4e828ba.Dk9t5yQD_5PHpj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/FCAM-3aAzXg?start=7335&amp;#x26;end=7553&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;WebGL: Latest techniques&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/FCAM-3aAzXg?start=8677&amp;#x26;end=9009&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Uber&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;’s&lt;/strong&gt; &lt;a href=&quot;http://vis.gl/&quot;&gt;&lt;strong&gt;Vis.gl&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;http://deck.gl/&quot;&gt;&lt;strong&gt;Deck.gl&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;http://kepler.gl/&quot;&gt;&lt;strong&gt;Kepler.gl&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;https://neb.gl/&quot;&gt;&lt;strong&gt;Nebula.gl&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/%20FCAM-3aAzXg?start=10087&amp;#x26;end=10416&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Sub-centimeter pointclouds in Cesium&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/embed/FCAM-3aAzXg?start=10442&amp;#x26;end=11129&amp;#x26;autoplay=1&quot;&gt;&lt;strong&gt;Ricardo Cabello, THREE.js founder, discussing the state of the art&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;production-sessions&quot;&gt;“Production sessions”&lt;/h2&gt;
&lt;p&gt;These are not really my core business so I couldn’t attend a lot of these, but oh my what a source of inspiration. The production sessions at SIGGRAPH are all about implementing visual effects techniques, mostly in movies and games. These are the ones I attended:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DNEG, Framestore, and MPC Present: The Visual Effects of “Blade Runner 2049”&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Making the Kessel Run in Less Than 12 Parsecs — The VFX of “Solo: A Star Wars Story”&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Making of Marvel Studios’ “Avengers: Infinity War”&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;talks&quot;&gt;Talks&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;370&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_p77ONGFKyvZKJjbVGRWGlQ-b4e7c46e.Byq7MFjb_Zz61am.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Not necessarily scientific talks, these elaborate on the full range of computer graphics and interactive techniques, including case studies, academic research, technical developments, improved pipeline tools, education and curriculum, professional development, or social commentary.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;StarWars: The Last Jedi — Effects Simulation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Collocated Spatially Adaptive Approach to Smoke Simulation in Bifrost&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rampage: A Pipelined Approach to Managing Large Scale Character Driven Effects&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SimpleBullet: Collaborating on a Modular Destruction Toolkit&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;last-but-not-least-keynotes&quot;&gt;Last but not least: Keynotes&lt;/h2&gt;
&lt;p&gt;Of course there were keynotes!&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=kUoIbP1l9yA&quot;&gt;&lt;strong&gt;Rob Bredow: Star Wars: Solo&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An inspiring presentation by the executive creative director of Industrial Light and Magic (ILM) about the philosophy behind the making of Star Wars: Solo, as well as an inspirational talk for the upcoming generation in VFX.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Mrixi27G9yM&quot;&gt;&lt;strong&gt;Jen-Hsun Huang: Gforce RTX&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;launch&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It was amazing to be present at this monumental moment for 3D graphics. Real-time ray tracing was always “the future” and even though a lot of deep learning trickery is still needed for denoising the images, being able to have a working implementation of this already is an astounding achievement. The links below bring you directly to the most inspiring and interesting moments in the presentation on YouTube:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;944&quot; height=&quot;527&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XWFlmYkdpAQ-hLKcMXZ3TQ-0ed1d48f.CGlvDm_s_NJL6f.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;and-then-there-was-computer-animation-festival&quot;&gt;And then there was… computer animation festival&lt;/h2&gt;
&lt;p&gt;Another recurring feature of SIGGRAPH, the computer animation festival is a celebration of computer graphics and visual effects used for storytelling. Some trailers to the short films shown are here:&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_g8BdoXVRbTApuzEOjUYKRQ-edf396b8.DXBs_O6g.png" medium="image"/><author>Maarten van Meersbergen</author></item><item><title>analyzing the ‘life’ of newspapers with machine learning</title><link>https://blog2.esciencecenter.nl/posts/2018-09-26---analyzing-the-life-of-newspapers-with-machine-learning</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-09-26---analyzing-the-life-of-newspapers-with-machine-learning</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vCZPyakBoyLx5EKtnc1Xvw-fd410d83.NoPW9ZIH_4T9hB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Marcel Broersma, professor of Media and Journalism Studies and Director of the Research Centre for Media and Journalism Studies (CMJS) at the University of Groningen&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon |&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;journalism-offers-citizens-a-window-on-the-world&quot;&gt;Journalism offers citizens a window on the world&lt;/h2&gt;
&lt;p&gt;“What is the role and function of news and journalism in, and for, society? And how does this role change over time? These are questions that fascinate me. This includes a focus on long-term historical shifts, but also on very current changes in journalism, for example related to the rise of social media and changing patterns of news use. I study journalism as a cultural form with specific stylistic and textual conventions that have an impact on how citizens obtain and experience knowledge about society, and act upon this. For most citizens journalism offers a window on the world. The views we get from that window have a huge impact on our daily lives.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_JKyvk3tQw5WkkDg1NPhwGg-bebbadbd.BGF2bDVV_Z1hhPXj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is the role and function of news and journalism in, and for, society? And how does this role change over time?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Marcel Broersma is Principal Investigator of the collaborative research project &lt;a href=&quot;https://www.esciencecenter.nl/project/newsgac&quot;&gt;NEWSGAC&lt;/a&gt; which studies how genres in newspapers and television news can be detected automatically using Machine Learning technology. The project brings together expertise from journalism history scholars, specialists in data modelling, integration and analysis, digital collection experts and eScience Research Engineers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The views we get from journalism have a huge impact on our daily lives&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MxOWNWxfOP0WxBqouXtV2A-e163d1e1.Dwn1sQxZ_241daC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;exploring-new-territories&quot;&gt;Exploring new territories&lt;/h3&gt;
&lt;p&gt;“What I particularly like in research is exploring new territories. My research has always been on the interface of different disciplines, trying to shed new light on journalism as a research object. In addition, I value and enjoy multi- and interdisciplinary collaboration — in Groningen I founded the Centre for Digital Humanities to foster such work. These interests converge in digital humanities projects in which we push the boundaries by using computational methods to analyze questions that are key in journalism studies.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_hdvI0HdGi2VTns4wS5JKVw-15e2bbbe.q_ctM7Q9_yAhqR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;understanding-the-changing-nature-of-journalism&quot;&gt;Understanding the changing nature of journalism&lt;/h3&gt;
&lt;p&gt;“In this project we are interested in two complicated issues. First, we want to analyze on a large scale how journalism has changed in the twentieth century from a practice centered around views and opinions to fact-centered reporting. We do so by analyzing the “life” of genres in newspapers. Throughout history, genres such as the interview and the reportage were “invented” as part of a shift towards active reporting in which on-site observation is important and sources are critically assessed. Other genres such as the report and the opinionated essay have either disappeared or decreased in volume and importance.”&lt;/p&gt;
&lt;p&gt;“In my previous NWO-VIDI project (Reporting at the Boundaries of the Public Sphere. Form, Style and Strategy of European Journalism, 1880–2005) we did a manual content analysis of about 125.000 historical newspaper articles. We use this annotated dataset as a training set to train algorithms that can identify the genre of historical news articles. Ideally, this will allow us to study the shift from opinion-oriented journalism to event-centered reporting on a large scale.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r-bR1qVmmMdMDdwr9F6uQg-66f83ac0.e4UfH2oF_GkN5y.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This project will open the black box of Machine Learning&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“In addition, the project will open the black box of Machine Learning by comparing, assessing and visualizing the effects of applying various algorithms on heterogeneous historical data with genre features that shift over time. This will enable scholars to critically evaluate the methodological effects of various machine learning approaches, while developing an approach that can deal with the overabundance of available historical newspaper material.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0_ClYZ5CuKiIMz9bBqsEyQ-3d832724.Vwv35WRU_1mFjDi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-difficult-task-for-computers&quot;&gt;A difficult task for computers&lt;/h3&gt;
&lt;p&gt;“The biggest challenge is the fact that the genre of a newspaper article is not straightforward; labeling the genre of a historical newspaper text demands a lot of interpretation. Even for human coders it is hard to code for this category, for which they also take contextual factors into account in addition to textual features. This makes it a very difficult task for the computer. But when we could do this, we gain a lot — which is why we decided to focus on this category.”&lt;/p&gt;
&lt;h3 id=&quot;fascinating-conversations&quot;&gt;Fascinating conversations&lt;/h3&gt;
&lt;p&gt;“Collaboration between us as domain specialists, computer scientists, eScience Research Engineers and the collection specialists at the archives ( who provide access to, and knowledge about, their digital collections) is crucial for a project like this. To solve the challenges that are ahead of us, we need the knowledge and expertise of every one of these stakeholders. This also raises issues because we do not always speak each other’s language. This results in fascinating conversations and discussions from which we all learn. I think it is fun to explore this new shared terrain, also because we all see what we can gain from it.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iJh3PNg1hna2Nf-CfPAGtg-da14ce6b.D1d-NZCu_Z1qsdyE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is fun to explore this new shared terrain, also because we all see what we can gain from it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“Prior to the current project on genre, I worked with the eScience Center on a &lt;a href=&quot;https://www.esciencecenter.nl/project/automated-analysis-of-online-behaviour-on-social-media&quot;&gt;project&lt;/a&gt; that focused on mapping the online behavior from politicians on Twitter. This project also centered around a very complex content category, which we tried to classify automatically by applying machine learning as well.”&lt;/p&gt;
&lt;p&gt;“On both projects I have worked and work with Erik Tjong Kim Sang, who I already knew a little bit from his work on Twitter in computational linguistics. Our collaboration has been very smooth and enjoyable. Together with our computer scientist and postdoc Aysenur Bilgin (CWI), Erik offers crucial knowledge and skills that I and other domain specialists in the team don’t have, and Aysenur and Erik both come up with new ideas and solutions based on our discussions. It’s exactly the kind of collaboration you need in a project like this.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KloC8MChSA1G2Uo6tR103w-24541b09.DEZK2nnR_Z1gFW9S.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;sharing-knowledge-and-tools-with-other-researchers&quot;&gt;Sharing knowledge and tools with other researchers&lt;/h3&gt;
&lt;p&gt;“Internally, we have open discussions in the team in which we share knowledge, ideas and expertise. We learn a lot from each other. Externally, we discuss our findings and approach with the scholarly community through papers and (conference) presentations. The archives profit from the knowledge and tools created in this project to make their collections better available. But most importantly, we are working on a virtual workspace in which researchers can upload their own annotated dataset, experiment with different machine learning algorithms, and tweak features to ultimately assess the output and make an informed choice about the best performing algorithm. This is important because certain machine learning algorithms can score high on overall accuracy, but might still underperform on validity. We think this is a useful tool for other researchers that could make an impact in the &lt;a href=&quot;https://clariah.nl/&quot;&gt;CLARIAH&lt;/a&gt; framework — which also supports this project.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yERr26olxSlvTAMvmM_eTg-19ea07d6.DCeumMTo_iw9l6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;digitization-can-have-a-major-impact-on-how-we-study-journalism&quot;&gt;Digitization can have a major impact on how we study journalism&lt;/h3&gt;
&lt;p&gt;“I hope that, in the longer term, we will be able to answer research questions that have only be tested on smaller datasets by analyzing research material on a much larger scale. Content analyses of news texts has also been a very labor intensive method, also because collections were hard to access. The size of our manually annotated dataset of 125.000 articles in our previous project is unprecedented, but it is still only very little compared to the news texts that have been produced in the long twentieth century. The digitization of newspaper collections and the use of computational methods can thus have a major impact in my field. We can pose new questions and answer existing questions based on more data.”&lt;/p&gt;
&lt;p&gt;“Moreover, we work with latent categories and “fuzzy” data. If we manage to develop a classifier that does the job, this might also have an impact on developing algorithms that can classify other “complex” categories. Last but not least, algorithmic transparency is becoming an increasingly bigger issue for society. How do we know what algorithms do what they should do? How can we assess their performance? Hopefully, our workspace can offer some insights in how machine algorithms work and open the black box.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SmL5ovpWl2kkNoNFDAQ9ew-95df676d.ClQY4Tzy_1SKwbu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Erik Tjong Kim Sang, Lotte Wilms, Marcel Broersma, Frank Harbers, Kim Smeenk, Aysenur Bilgin, Tom Klaver and Jacco van Ossenbruggen.&lt;/p&gt;
&lt;h3 id=&quot;much-to-gain-from-interdisciplinary-collaborations&quot;&gt;Much to gain from interdisciplinary collaborations&lt;/h3&gt;
&lt;p&gt;I hope this type of research on the interface of specific domains and computer science will then be more common. There is much to gain! The road towards it will for sure be bumpy, but I also hope that we will by then have solved many issues and have developed solid classifiers to label latent categories. These are the most interesting ones in the humanities.&lt;/p&gt;
&lt;h3 id=&quot;about-the-newsgac-project&quot;&gt;About the NEWSGAC project&lt;/h3&gt;
&lt;p&gt;The NEWSGAC project was initiated by Marcel and his colleague Frank Harbers (both from &lt;a href=&quot;https://www.rug.nl/&quot;&gt;University of Groningen&lt;/a&gt;), together with Jacco van Ossenbruggen and Laura Hollink (both from &lt;a href=&quot;https://www.cwi.nl/&quot;&gt;CWI&lt;/a&gt;), and in cooperation with the National Library (&lt;a href=&quot;https://www.kb.nl/&quot;&gt;KB&lt;/a&gt;) and the Netherlands Institute for Sound and Vision (&lt;a href=&quot;https://beeldengeluid.nl/en&quot;&gt;NISV&lt;/a&gt;). Aysenur Bilgin works on it as a postdoctoral researcher at CWI and Kim Smeenk as a junior researcher at CMJS. Two eScience Research Engineers from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; are part of the NEWSGAC team: Erik Tjong Kim Sang and Tom Klaver.&lt;/p&gt;</description><pubDate>Wed, 26 Sep 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vCZPyakBoyLx5EKtnc1Xvw-fd410d83.NoPW9ZIH_4T9hB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Marcel Broersma, professor of Media and Journalism Studies and Director of the Research Centre for Media and Journalism Studies (CMJS) at the University of Groningen&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon |&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;journalism-offers-citizens-a-window-on-the-world&quot;&gt;Journalism offers citizens a window on the world&lt;/h2&gt;
&lt;p&gt;“What is the role and function of news and journalism in, and for, society? And how does this role change over time? These are questions that fascinate me. This includes a focus on long-term historical shifts, but also on very current changes in journalism, for example related to the rise of social media and changing patterns of news use. I study journalism as a cultural form with specific stylistic and textual conventions that have an impact on how citizens obtain and experience knowledge about society, and act upon this. For most citizens journalism offers a window on the world. The views we get from that window have a huge impact on our daily lives.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_JKyvk3tQw5WkkDg1NPhwGg-bebbadbd.BGF2bDVV_Z1hhPXj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is the role and function of news and journalism in, and for, society? And how does this role change over time?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Marcel Broersma is Principal Investigator of the collaborative research project &lt;a href=&quot;https://www.esciencecenter.nl/project/newsgac&quot;&gt;NEWSGAC&lt;/a&gt; which studies how genres in newspapers and television news can be detected automatically using Machine Learning technology. The project brings together expertise from journalism history scholars, specialists in data modelling, integration and analysis, digital collection experts and eScience Research Engineers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The views we get from journalism have a huge impact on our daily lives&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MxOWNWxfOP0WxBqouXtV2A-e163d1e1.Dwn1sQxZ_241daC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;exploring-new-territories&quot;&gt;Exploring new territories&lt;/h3&gt;
&lt;p&gt;“What I particularly like in research is exploring new territories. My research has always been on the interface of different disciplines, trying to shed new light on journalism as a research object. In addition, I value and enjoy multi- and interdisciplinary collaboration — in Groningen I founded the Centre for Digital Humanities to foster such work. These interests converge in digital humanities projects in which we push the boundaries by using computational methods to analyze questions that are key in journalism studies.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_hdvI0HdGi2VTns4wS5JKVw-15e2bbbe.q_ctM7Q9_yAhqR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;understanding-the-changing-nature-of-journalism&quot;&gt;Understanding the changing nature of journalism&lt;/h3&gt;
&lt;p&gt;“In this project we are interested in two complicated issues. First, we want to analyze on a large scale how journalism has changed in the twentieth century from a practice centered around views and opinions to fact-centered reporting. We do so by analyzing the “life” of genres in newspapers. Throughout history, genres such as the interview and the reportage were “invented” as part of a shift towards active reporting in which on-site observation is important and sources are critically assessed. Other genres such as the report and the opinionated essay have either disappeared or decreased in volume and importance.”&lt;/p&gt;
&lt;p&gt;“In my previous NWO-VIDI project (Reporting at the Boundaries of the Public Sphere. Form, Style and Strategy of European Journalism, 1880–2005) we did a manual content analysis of about 125.000 historical newspaper articles. We use this annotated dataset as a training set to train algorithms that can identify the genre of historical news articles. Ideally, this will allow us to study the shift from opinion-oriented journalism to event-centered reporting on a large scale.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r-bR1qVmmMdMDdwr9F6uQg-66f83ac0.e4UfH2oF_GkN5y.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This project will open the black box of Machine Learning&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“In addition, the project will open the black box of Machine Learning by comparing, assessing and visualizing the effects of applying various algorithms on heterogeneous historical data with genre features that shift over time. This will enable scholars to critically evaluate the methodological effects of various machine learning approaches, while developing an approach that can deal with the overabundance of available historical newspaper material.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0_ClYZ5CuKiIMz9bBqsEyQ-3d832724.Vwv35WRU_1mFjDi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-difficult-task-for-computers&quot;&gt;A difficult task for computers&lt;/h3&gt;
&lt;p&gt;“The biggest challenge is the fact that the genre of a newspaper article is not straightforward; labeling the genre of a historical newspaper text demands a lot of interpretation. Even for human coders it is hard to code for this category, for which they also take contextual factors into account in addition to textual features. This makes it a very difficult task for the computer. But when we could do this, we gain a lot — which is why we decided to focus on this category.”&lt;/p&gt;
&lt;h3 id=&quot;fascinating-conversations&quot;&gt;Fascinating conversations&lt;/h3&gt;
&lt;p&gt;“Collaboration between us as domain specialists, computer scientists, eScience Research Engineers and the collection specialists at the archives ( who provide access to, and knowledge about, their digital collections) is crucial for a project like this. To solve the challenges that are ahead of us, we need the knowledge and expertise of every one of these stakeholders. This also raises issues because we do not always speak each other’s language. This results in fascinating conversations and discussions from which we all learn. I think it is fun to explore this new shared terrain, also because we all see what we can gain from it.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iJh3PNg1hna2Nf-CfPAGtg-da14ce6b.D1d-NZCu_Z1qsdyE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is fun to explore this new shared terrain, also because we all see what we can gain from it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“Prior to the current project on genre, I worked with the eScience Center on a &lt;a href=&quot;https://www.esciencecenter.nl/project/automated-analysis-of-online-behaviour-on-social-media&quot;&gt;project&lt;/a&gt; that focused on mapping the online behavior from politicians on Twitter. This project also centered around a very complex content category, which we tried to classify automatically by applying machine learning as well.”&lt;/p&gt;
&lt;p&gt;“On both projects I have worked and work with Erik Tjong Kim Sang, who I already knew a little bit from his work on Twitter in computational linguistics. Our collaboration has been very smooth and enjoyable. Together with our computer scientist and postdoc Aysenur Bilgin (CWI), Erik offers crucial knowledge and skills that I and other domain specialists in the team don’t have, and Aysenur and Erik both come up with new ideas and solutions based on our discussions. It’s exactly the kind of collaboration you need in a project like this.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KloC8MChSA1G2Uo6tR103w-24541b09.DEZK2nnR_Z1gFW9S.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;sharing-knowledge-and-tools-with-other-researchers&quot;&gt;Sharing knowledge and tools with other researchers&lt;/h3&gt;
&lt;p&gt;“Internally, we have open discussions in the team in which we share knowledge, ideas and expertise. We learn a lot from each other. Externally, we discuss our findings and approach with the scholarly community through papers and (conference) presentations. The archives profit from the knowledge and tools created in this project to make their collections better available. But most importantly, we are working on a virtual workspace in which researchers can upload their own annotated dataset, experiment with different machine learning algorithms, and tweak features to ultimately assess the output and make an informed choice about the best performing algorithm. This is important because certain machine learning algorithms can score high on overall accuracy, but might still underperform on validity. We think this is a useful tool for other researchers that could make an impact in the &lt;a href=&quot;https://clariah.nl/&quot;&gt;CLARIAH&lt;/a&gt; framework — which also supports this project.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yERr26olxSlvTAMvmM_eTg-19ea07d6.DCeumMTo_iw9l6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;digitization-can-have-a-major-impact-on-how-we-study-journalism&quot;&gt;Digitization can have a major impact on how we study journalism&lt;/h3&gt;
&lt;p&gt;“I hope that, in the longer term, we will be able to answer research questions that have only be tested on smaller datasets by analyzing research material on a much larger scale. Content analyses of news texts has also been a very labor intensive method, also because collections were hard to access. The size of our manually annotated dataset of 125.000 articles in our previous project is unprecedented, but it is still only very little compared to the news texts that have been produced in the long twentieth century. The digitization of newspaper collections and the use of computational methods can thus have a major impact in my field. We can pose new questions and answer existing questions based on more data.”&lt;/p&gt;
&lt;p&gt;“Moreover, we work with latent categories and “fuzzy” data. If we manage to develop a classifier that does the job, this might also have an impact on developing algorithms that can classify other “complex” categories. Last but not least, algorithmic transparency is becoming an increasingly bigger issue for society. How do we know what algorithms do what they should do? How can we assess their performance? Hopefully, our workspace can offer some insights in how machine algorithms work and open the black box.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SmL5ovpWl2kkNoNFDAQ9ew-95df676d.ClQY4Tzy_1SKwbu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Erik Tjong Kim Sang, Lotte Wilms, Marcel Broersma, Frank Harbers, Kim Smeenk, Aysenur Bilgin, Tom Klaver and Jacco van Ossenbruggen.&lt;/p&gt;
&lt;h3 id=&quot;much-to-gain-from-interdisciplinary-collaborations&quot;&gt;Much to gain from interdisciplinary collaborations&lt;/h3&gt;
&lt;p&gt;I hope this type of research on the interface of specific domains and computer science will then be more common. There is much to gain! The road towards it will for sure be bumpy, but I also hope that we will by then have solved many issues and have developed solid classifiers to label latent categories. These are the most interesting ones in the humanities.&lt;/p&gt;
&lt;h3 id=&quot;about-the-newsgac-project&quot;&gt;About the NEWSGAC project&lt;/h3&gt;
&lt;p&gt;The NEWSGAC project was initiated by Marcel and his colleague Frank Harbers (both from &lt;a href=&quot;https://www.rug.nl/&quot;&gt;University of Groningen&lt;/a&gt;), together with Jacco van Ossenbruggen and Laura Hollink (both from &lt;a href=&quot;https://www.cwi.nl/&quot;&gt;CWI&lt;/a&gt;), and in cooperation with the National Library (&lt;a href=&quot;https://www.kb.nl/&quot;&gt;KB&lt;/a&gt;) and the Netherlands Institute for Sound and Vision (&lt;a href=&quot;https://beeldengeluid.nl/en&quot;&gt;NISV&lt;/a&gt;). Aysenur Bilgin works on it as a postdoctoral researcher at CWI and Kim Smeenk as a junior researcher at CMJS. Two eScience Research Engineers from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; are part of the NEWSGAC team: Erik Tjong Kim Sang and Tom Klaver.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_JKyvk3tQw5WkkDg1NPhwGg-bebbadbd.BGF2bDVV.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Want to organize a workshop on image processing</title><link>https://blog2.esciencecenter.nl/posts/2018-09-17---want-to-organize-a-workshop-on-image-processing</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-09-17---want-to-organize-a-workshop-on-image-processing</guid><description>&lt;h2 id=&quot;a-list-of-resources-to-kick-start-your-workshop&quot;&gt;A list of resources to kick-start your workshop&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1152&quot; height=&quot;288&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_p95hvrDkUook7FWGAp57cA-03f1cda9.CJLqdrnt_jxMxC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I wanted to organize a workshop on image processing for PhDs in the medical domain. I usually use &lt;a href=&quot;https://software-carpentry.org/lessons/&quot;&gt;Software Carpentry lessons&lt;/a&gt; in my workshops, but there are no lessons on image processing. Before starting to re-invent the wheel, I thought I should ask the Software Carpentry community if anybody had given a workshop like that recently.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey guys, image processing lesson anyone?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was hit by a wave of suggestions and existing materials — and although not everything fitted in the scope of my workshop, it sure made my life a lot easier! Here is a summary of some of the useful links which were shared.&lt;/p&gt;
&lt;h2 id=&quot;list-of-resources&quot;&gt;List of resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://python-102.readthedocs.io/en/latest/&quot;&gt;Python tutorial focused on packaging, testing, and&lt;br&gt;
performance using very simple image analysis&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomwright01/imp-parallel&quot;&gt;Example worked through with a group,&lt;/a&gt; cone counting using scipy.&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href=&quot;https://www.scipy-lectures.org/&quot;&gt;scipy lecture notes&lt;/a&gt; (in the end this is mostly what I did).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git.embl.de/grp-bio-it/python-workshop-image-processing&quot;&gt;Two-day workshop&lt;/a&gt; on image processing with Python. This course teaches the basics of bio-image processing, segmentation and analysis in python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bi1x.caltech.edu/2016/handouts/image_processing_1.html&quot;&gt;Image Processing I&lt;/a&gt;, basic techniques for image processing using scikit-image with Python&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mmeysenburg.github.io/image-processing/&quot;&gt;Digital Imaging and Vision Applications in Science&lt;/a&gt; (DIVAS) Image Processing, using Python and OpenCV to do basic image processing — I really liked this lesson, because OpenCV is super powerful, but was a bit afraid it wouldn’t work in some people’s laptop.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bic-berkeley.github.io/psych-214-fall-2016/arrays_and_images.html&quot;&gt;PSYCH 214&lt;/a&gt;, arrays as images, images as arrays.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/luispedro/python-image-tutorial&quot;&gt;Playing with images &amp;#x26; filters&lt;/a&gt;, use numpy and &lt;a href=&quot;https://mahotas.readthedocs.io/en/latest/&quot;&gt;mahotas&lt;/a&gt; to manipulate images.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/scikit-image/skimage-tutorials/tree/master/lectures&quot;&gt;Lots of materials at scikit-image&lt;/a&gt;, The numbered ones are the most complete/polished.&lt;/li&gt;
&lt;li&gt;Developing &lt;a href=&quot;https://github.com/DataLucence/images&quot;&gt;image processing lessons at Stanford&lt;/a&gt;, for graduate students in neuroscience.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;in-the-end&quot;&gt;In the end&lt;/h2&gt;
&lt;p&gt;In the end, I had all the material that I wanted for &lt;a href=&quot;https://escience-academy.github.io/2018-08-29-BQMinded/material/ImageProcessing.pdf&quot;&gt;my workshop&lt;/a&gt;, which went quite well — with the usual issues one encounters in a workshop: too basic for some, a bit confusing for others. One day I will find the perfect balance.&lt;/p&gt;
&lt;p&gt;Do you have any valuable resources to include in the list? Let me know in a comment below!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also posted&lt;/em&gt; &lt;a href=&quot;https://carpentries.org/blog/2018/09/image_processing_resources/&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 17 Sep 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;a-list-of-resources-to-kick-start-your-workshop&quot;&gt;A list of resources to kick-start your workshop&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1152&quot; height=&quot;288&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_p95hvrDkUook7FWGAp57cA-03f1cda9.CJLqdrnt_jxMxC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I wanted to organize a workshop on image processing for PhDs in the medical domain. I usually use &lt;a href=&quot;https://software-carpentry.org/lessons/&quot;&gt;Software Carpentry lessons&lt;/a&gt; in my workshops, but there are no lessons on image processing. Before starting to re-invent the wheel, I thought I should ask the Software Carpentry community if anybody had given a workshop like that recently.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey guys, image processing lesson anyone?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was hit by a wave of suggestions and existing materials — and although not everything fitted in the scope of my workshop, it sure made my life a lot easier! Here is a summary of some of the useful links which were shared.&lt;/p&gt;
&lt;h2 id=&quot;list-of-resources&quot;&gt;List of resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://python-102.readthedocs.io/en/latest/&quot;&gt;Python tutorial focused on packaging, testing, and&lt;br&gt;
performance using very simple image analysis&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tomwright01/imp-parallel&quot;&gt;Example worked through with a group,&lt;/a&gt; cone counting using scipy.&lt;/li&gt;
&lt;li&gt;Check out the &lt;a href=&quot;https://www.scipy-lectures.org/&quot;&gt;scipy lecture notes&lt;/a&gt; (in the end this is mostly what I did).&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git.embl.de/grp-bio-it/python-workshop-image-processing&quot;&gt;Two-day workshop&lt;/a&gt; on image processing with Python. This course teaches the basics of bio-image processing, segmentation and analysis in python.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bi1x.caltech.edu/2016/handouts/image_processing_1.html&quot;&gt;Image Processing I&lt;/a&gt;, basic techniques for image processing using scikit-image with Python&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mmeysenburg.github.io/image-processing/&quot;&gt;Digital Imaging and Vision Applications in Science&lt;/a&gt; (DIVAS) Image Processing, using Python and OpenCV to do basic image processing — I really liked this lesson, because OpenCV is super powerful, but was a bit afraid it wouldn’t work in some people’s laptop.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bic-berkeley.github.io/psych-214-fall-2016/arrays_and_images.html&quot;&gt;PSYCH 214&lt;/a&gt;, arrays as images, images as arrays.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/luispedro/python-image-tutorial&quot;&gt;Playing with images &amp;#x26; filters&lt;/a&gt;, use numpy and &lt;a href=&quot;https://mahotas.readthedocs.io/en/latest/&quot;&gt;mahotas&lt;/a&gt; to manipulate images.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/scikit-image/skimage-tutorials/tree/master/lectures&quot;&gt;Lots of materials at scikit-image&lt;/a&gt;, The numbered ones are the most complete/polished.&lt;/li&gt;
&lt;li&gt;Developing &lt;a href=&quot;https://github.com/DataLucence/images&quot;&gt;image processing lessons at Stanford&lt;/a&gt;, for graduate students in neuroscience.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;in-the-end&quot;&gt;In the end&lt;/h2&gt;
&lt;p&gt;In the end, I had all the material that I wanted for &lt;a href=&quot;https://escience-academy.github.io/2018-08-29-BQMinded/material/ImageProcessing.pdf&quot;&gt;my workshop&lt;/a&gt;, which went quite well — with the usual issues one encounters in a workshop: too basic for some, a bit confusing for others. One day I will find the perfect balance.&lt;/p&gt;
&lt;p&gt;Do you have any valuable resources to include in the list? Let me know in a comment below!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also posted&lt;/em&gt; &lt;a href=&quot;https://carpentries.org/blog/2018/09/image_processing_resources/&quot;&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_p95hvrDkUook7FWGAp57cA-03f1cda9.CJLqdrnt.png" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>is an escience research engineer simply a computer scientist in disguise</title><link>https://blog2.esciencecenter.nl/posts/2018-09-06---is-an-escience-research-engineer-simply-a-computer-scientist-in-disguise</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-09-06---is-an-escience-research-engineer-simply-a-computer-scientist-in-disguise</guid><description>&lt;h2 id=&quot;my-personal-view-on-the-differences-between-computer-scientists-and-escience-research-engineers&quot;&gt;My personal view on the differences between Computer Scientists and eScience Research Engineers&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RPecqNsPMcKZ8I_tj16VCA-67637b30.D6dF4Puy_ZzHQi8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;can-a-wolf-change-its-mind-by-changing-its-coat&quot;&gt;Can a wolf change its mind by changing its coat?&lt;/h2&gt;
&lt;p&gt;The origin of this proverbial question comes from the Latin motto:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lupus pilum mutat, non mentem.&lt;/p&gt;
&lt;p&gt;The wolf can change its coat, but not its mind (character/disposition).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Querying the ability of any person to change its innate being is a just question. Can a computer scientist change his mind by changing his title? Is an eScience Research Engineer simply a computer scientist in disguise?&lt;/p&gt;
&lt;p&gt;I fell in love with computer science and engineering in high school and I have been in love since. The master degrees and a doctorate which followed were a mere formal manifestation and consequence of how I felt. In my career path, I had applied my knowledge in different ways reflected by different job titles: post-doctoral researcher, innovator, R&amp;#x26;D engineer. I consider myself a computer scientist and engineer and I currently work as an eScience Research Engineer (eSRE) and eScience coordinator. Many of my colleagues at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; have similar careers.&lt;/p&gt;
&lt;h3 id=&quot;six-aspects-explaining-my-personal-identity-change&quot;&gt;Six aspects explaining my personal identity change&lt;/h3&gt;
&lt;p&gt;Working with many partners — other researchers, experts in their scientific domain — inevitably raises the question of who we are. Especially by partners who are computer scientists themselves! Being a “convert” myself, I see similarities but also differences between working as a computer scientist and as an eScience Research Engineer.&lt;/p&gt;
&lt;p&gt;In this blog post I will explain my personal view on 6 aspects of this mysterious “identity change”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Science:&lt;/strong&gt; Is the focus on computer science, or on domain science?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software:&lt;/strong&gt; Is the focus on the software itself, or on the impact of the software?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research:&lt;/strong&gt; How much freedom do you have in developing your expertise area?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publication:&lt;/strong&gt; Is publishing a main goal or not?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; Is collaboration an option or a requirement for doing research?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Funding:&lt;/strong&gt; Is applying for funding an option or a requirement for doing research?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will illustrate these six aspects in two stories: one about myself collaborating as a Computer Scientist, and one about myself collaborating as an eScience Research Engineer.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;427&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iSf90cSRNy2SrF_I8hr7PA-540047fe.A68z8t7b_Z2ctwlM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Principal Investigators day in 2017. The eScience Research Engineers wear blue badges (contrasting nicely my red cardigan) and the various domain scientists wear white badges. Blue and white, the colors of the Netherlands eScience center, match nicely and the bearers of the different badges work nicely together!&lt;/p&gt;
&lt;h2 id=&quot;collaborative-science&quot;&gt;Collaborative science&lt;/h2&gt;
&lt;p&gt;Modern science is a multidisciplinary effort. Computer science nowadays is often inspired by the needs and challenges of other sciences, which need computer science achievements in order to progress in the big data era. The keyword for a computer scientist and especially for an eSRE is &lt;em&gt;collaboration&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;collaborating-as-a-computer-scientist&quot;&gt;Collaborating as a computer scientist&lt;/h3&gt;
&lt;p&gt;Not all computer scientists work with other domain scientists, but many do. While working as a computer scientist (computer vision researcher to be precise) I worked within &lt;a href=&quot;https://cordis.europa.eu/project/rcn/58425_en.html&quot;&gt;Europhlukes&lt;/a&gt;, a joint project with marine biologists. They needed a tool for automated identification of individual humpback whales from images of their unique spots and patterns of the underside of their flukes. These spots and patterns are used for automated individual identification of these endangered mammals from large photo catalogs. The problem in biology gave me inspiration for computer vision research which would solve that problem. I have developed and published an &lt;a href=&quot;http://muscle.ercim.eu/images/DocumentPDF/MP_260_Ranguelova_GVIP05_ext.pdf&quot;&gt;algorithm for automatically identifying salient regions in an image&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;741&quot; height=&quot;139&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_hzrWj-0ARNUFPPyQ4HmqAw-1b354da3.DcLPlqpH_1i77Gf.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;751&quot; height=&quot;142&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8-asBtFELsEPiR0NjQmY4A-9de1805a.yJmtRHbL_Z2usjBR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Two pairs of images of two humpback whales. Each pair corresponds to the same individual. Every image is processed independently: after automatic segmentation of the flukes from the background, salient regions are detected automatically. The regions are then matched between a new image of a whale and all other images of known whales in a catalog. The matching regions in each pair of images are displayed using the same color.&lt;/p&gt;
&lt;p&gt;Automating this step allowed the biologists to process faster their large image catalogs and spend their time and efforts on studying the population dynamics of the endangered species. I have met with the biologists a few times to discuss their problem, get feedback and train them on my software.&lt;/p&gt;
&lt;p&gt;The same generic algorithm was later applied not only for identifying individual dolphins, newts, leather-back turtles and determining the wood type from microscopy images, but for identifying whether any digital photos subject to different distortions have captured the same object or scene.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;710&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6cC32D_Xp6hKcWr9YYFKWg-7bdd2c83.BhF3uj8T_1ONgpU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Regions detected independently on four images of the same scene. The first image is the original and the other three are being distorted by blur, decreased light and different camera angle respectively.&lt;/p&gt;
&lt;p&gt;As a computer science researcher my aim was to publish my algorithm as a first author in a large computer vision conference or journal. Applying the algorithm to real images for real applications served as proof of the usability and increased the acceptance chances of my publications. I was the only developer of the software. I used a proprietary software (MATLAB) to create the tool and delivered an executable to my users.&lt;/p&gt;
&lt;h3 id=&quot;collaborating-as-an-escience-research-engineer&quot;&gt;Collaborating as an eScience Research Engineer&lt;/h3&gt;
&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, I have worked on many projects requiring computer vision expertise. My first project in collaboration with neuroscientists from four medical centers, was &lt;a href=&quot;https://www.esciencecenter.nl/project/biomarker-boosting&quot;&gt;Biomarker Boosting&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;244&quot; height=&quot;159&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7ltJ6xYnoF6BQdJ9DlntAA-36a82e5b.D4ubW4Ub_Z1JXTpm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;biomarker&lt;/em&gt; is a measurable indicator of some biological state or condition. For example, the volume of the &lt;em&gt;hippocampus&lt;/em&gt; in the brain is a marker for Alzheimer’s disease. Smaller volume is strongly correlated with both age and cognitive impairment diseases. The larger the sample size, the better the predictive value of the biomarker, which can be achieved by combining data sets obtained by different medical centers. The aim of the Biomarker Boosting project was to build a reusable platform for sharing patient imaging data among medical centers to run a common analysis pipeline. I have worked on the core of the processing pipeline - automatic segmentation of the hippocampus.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;899&quot; height=&quot;454&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Fla0k1Hl4j7Szpl0nEEnbQ-4fb4060e.yVBOVyZg_X8iz2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Visualizing the segmentation result of the hippocampus. The volume can be obtained by simple voxel count.&lt;/p&gt;
&lt;p&gt;The developed algorithm was generic and could be used to segment any brain structure, but it was used with atlas data for the hippocampus. The pipeline was applied to four different cohorts collected to study dementia and mild cognitive impairment as that was the focus of the neurological researchers. I have worked together with the scientists in the same office on a regular basis (a day every week) during the project and we have kept in touch closely. We have presented and published the results of the project in neuroscience conferences and journals and I was often a co-author. I attended neurological conferences and made links with that community. We have worked together in the same software repository, the development was adhering to high code quality, testing and documentation standards. The goal was to deliver an open source software in order to increase the chances of community adoption and to serve as many neuroscientists as possible and even reach other domains.&lt;/p&gt;
&lt;h2 id=&quot;similarities-and-differences&quot;&gt;Similarities and Differences&lt;/h2&gt;
&lt;p&gt;The above examples from my career illustrate the &lt;em&gt;similarities&lt;/em&gt; and &lt;em&gt;differences&lt;/em&gt; between working as a computer scientist and as an eScience Research Engineer asI experienced them.&lt;/p&gt;
&lt;p&gt;On a first glance, the work of a computer scientist and an eSRE is the same, only the job title differs. But the main difference between the work of a computer scientist and an eSRE stem from their different &lt;strong&gt;focus.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Science:&lt;/strong&gt; Both a computer scientist and an eSRE work in scientific projects. Computer science is the science of interest of a computer scientist. Other scientific domains might present inspiration, challenge or serve as application domains, but are not the focus. eScience stands for enhanced science, an eSRE’s applies ICT expertise to facilitate breakthroughs in another science. The focus is on the domain research question.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software:&lt;/strong&gt; Both aim to produce working software. Computer scientists write software implementing new research ideas and producing correct publishable results is sufficient. eRSE write software to solve a domain question. eRSEs take care of the usability and within (or even cross-) domain applicability of the software. While the computer scientists do not necessarily open their code (e.g. to have a competitive advantage), eSREs do this as main principle. The impact of the research software they produce should be as large as possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research:&lt;/strong&gt; Computer scientists and eSRE are researchers. eSRE can do (applied) research in their expertise area if it fits the project, but always engineer research software. The main research in the project is the one aimed at answering the domain research question.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publication:&lt;/strong&gt; Both publish their work. Publishing as a first author (at the beginning of the career) is the main goal of a computer scientist. eSRE also publish either as a first author about the eScience or often as a co-author in a domain publication, but that is not their major goal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; Some computer scientists collaborate with other scientific domains researchers, but not all. For an eSRE this is one of the core job competencies — collaboration is much more intense and crucial for the success of the collaborative projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Funding:&lt;/strong&gt; Computer scientists (especially to progress in their career) apply as PI for research projects funding as their core task. Sometimes also eSREs apply for funding, although usually together with a domain scientist as a PI. The Netherlands eScience center is a funding organization, hence many of the (junior) eSREs do not need to worry about acquiring funds. Although by doing their job excellently, the happy PIs are investing money for further future work together.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-about-the-wolf&quot;&gt;What about the wolf?&lt;/h2&gt;
&lt;p&gt;It is not so important what the job title is, what is important is the &lt;strong&gt;mission&lt;/strong&gt; behind it. I have enjoyed working as a computer scientist, but looking back — Europhlukes, my favorite project, could be considered an eScience project. Working closely with domain scientists can be very challenging, but also very rewarding.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using ICT expertise to enable breakthroughs in science for the good of society is very rewarding.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It seems that I haven’t changed my disposition, but I have changed into much more of a team player. If you are inspired by the possibilities to work &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;with&lt;/a&gt; the eScience Research Engineers or want to be &lt;a href=&quot;https://www.esciencecenter.nl/about/careers&quot;&gt;part of the team&lt;/a&gt;, come to work with us!&lt;/p&gt;</description><pubDate>Thu, 06 Sep 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;my-personal-view-on-the-differences-between-computer-scientists-and-escience-research-engineers&quot;&gt;My personal view on the differences between Computer Scientists and eScience Research Engineers&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RPecqNsPMcKZ8I_tj16VCA-67637b30.D6dF4Puy_ZzHQi8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;can-a-wolf-change-its-mind-by-changing-its-coat&quot;&gt;Can a wolf change its mind by changing its coat?&lt;/h2&gt;
&lt;p&gt;The origin of this proverbial question comes from the Latin motto:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lupus pilum mutat, non mentem.&lt;/p&gt;
&lt;p&gt;The wolf can change its coat, but not its mind (character/disposition).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Querying the ability of any person to change its innate being is a just question. Can a computer scientist change his mind by changing his title? Is an eScience Research Engineer simply a computer scientist in disguise?&lt;/p&gt;
&lt;p&gt;I fell in love with computer science and engineering in high school and I have been in love since. The master degrees and a doctorate which followed were a mere formal manifestation and consequence of how I felt. In my career path, I had applied my knowledge in different ways reflected by different job titles: post-doctoral researcher, innovator, R&amp;#x26;D engineer. I consider myself a computer scientist and engineer and I currently work as an eScience Research Engineer (eSRE) and eScience coordinator. Many of my colleagues at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; have similar careers.&lt;/p&gt;
&lt;h3 id=&quot;six-aspects-explaining-my-personal-identity-change&quot;&gt;Six aspects explaining my personal identity change&lt;/h3&gt;
&lt;p&gt;Working with many partners — other researchers, experts in their scientific domain — inevitably raises the question of who we are. Especially by partners who are computer scientists themselves! Being a “convert” myself, I see similarities but also differences between working as a computer scientist and as an eScience Research Engineer.&lt;/p&gt;
&lt;p&gt;In this blog post I will explain my personal view on 6 aspects of this mysterious “identity change”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Science:&lt;/strong&gt; Is the focus on computer science, or on domain science?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software:&lt;/strong&gt; Is the focus on the software itself, or on the impact of the software?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research:&lt;/strong&gt; How much freedom do you have in developing your expertise area?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publication:&lt;/strong&gt; Is publishing a main goal or not?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; Is collaboration an option or a requirement for doing research?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Funding:&lt;/strong&gt; Is applying for funding an option or a requirement for doing research?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will illustrate these six aspects in two stories: one about myself collaborating as a Computer Scientist, and one about myself collaborating as an eScience Research Engineer.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;427&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iSf90cSRNy2SrF_I8hr7PA-540047fe.A68z8t7b_Z2ctwlM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Principal Investigators day in 2017. The eScience Research Engineers wear blue badges (contrasting nicely my red cardigan) and the various domain scientists wear white badges. Blue and white, the colors of the Netherlands eScience center, match nicely and the bearers of the different badges work nicely together!&lt;/p&gt;
&lt;h2 id=&quot;collaborative-science&quot;&gt;Collaborative science&lt;/h2&gt;
&lt;p&gt;Modern science is a multidisciplinary effort. Computer science nowadays is often inspired by the needs and challenges of other sciences, which need computer science achievements in order to progress in the big data era. The keyword for a computer scientist and especially for an eSRE is &lt;em&gt;collaboration&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;collaborating-as-a-computer-scientist&quot;&gt;Collaborating as a computer scientist&lt;/h3&gt;
&lt;p&gt;Not all computer scientists work with other domain scientists, but many do. While working as a computer scientist (computer vision researcher to be precise) I worked within &lt;a href=&quot;https://cordis.europa.eu/project/rcn/58425_en.html&quot;&gt;Europhlukes&lt;/a&gt;, a joint project with marine biologists. They needed a tool for automated identification of individual humpback whales from images of their unique spots and patterns of the underside of their flukes. These spots and patterns are used for automated individual identification of these endangered mammals from large photo catalogs. The problem in biology gave me inspiration for computer vision research which would solve that problem. I have developed and published an &lt;a href=&quot;http://muscle.ercim.eu/images/DocumentPDF/MP_260_Ranguelova_GVIP05_ext.pdf&quot;&gt;algorithm for automatically identifying salient regions in an image&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;741&quot; height=&quot;139&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_hzrWj-0ARNUFPPyQ4HmqAw-1b354da3.DcLPlqpH_1i77Gf.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;751&quot; height=&quot;142&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8-asBtFELsEPiR0NjQmY4A-9de1805a.yJmtRHbL_Z2usjBR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Two pairs of images of two humpback whales. Each pair corresponds to the same individual. Every image is processed independently: after automatic segmentation of the flukes from the background, salient regions are detected automatically. The regions are then matched between a new image of a whale and all other images of known whales in a catalog. The matching regions in each pair of images are displayed using the same color.&lt;/p&gt;
&lt;p&gt;Automating this step allowed the biologists to process faster their large image catalogs and spend their time and efforts on studying the population dynamics of the endangered species. I have met with the biologists a few times to discuss their problem, get feedback and train them on my software.&lt;/p&gt;
&lt;p&gt;The same generic algorithm was later applied not only for identifying individual dolphins, newts, leather-back turtles and determining the wood type from microscopy images, but for identifying whether any digital photos subject to different distortions have captured the same object or scene.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;710&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6cC32D_Xp6hKcWr9YYFKWg-7bdd2c83.BhF3uj8T_1ONgpU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Regions detected independently on four images of the same scene. The first image is the original and the other three are being distorted by blur, decreased light and different camera angle respectively.&lt;/p&gt;
&lt;p&gt;As a computer science researcher my aim was to publish my algorithm as a first author in a large computer vision conference or journal. Applying the algorithm to real images for real applications served as proof of the usability and increased the acceptance chances of my publications. I was the only developer of the software. I used a proprietary software (MATLAB) to create the tool and delivered an executable to my users.&lt;/p&gt;
&lt;h3 id=&quot;collaborating-as-an-escience-research-engineer&quot;&gt;Collaborating as an eScience Research Engineer&lt;/h3&gt;
&lt;p&gt;At the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, I have worked on many projects requiring computer vision expertise. My first project in collaboration with neuroscientists from four medical centers, was &lt;a href=&quot;https://www.esciencecenter.nl/project/biomarker-boosting&quot;&gt;Biomarker Boosting&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;244&quot; height=&quot;159&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_7ltJ6xYnoF6BQdJ9DlntAA-36a82e5b.D4ubW4Ub_Z1JXTpm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;biomarker&lt;/em&gt; is a measurable indicator of some biological state or condition. For example, the volume of the &lt;em&gt;hippocampus&lt;/em&gt; in the brain is a marker for Alzheimer’s disease. Smaller volume is strongly correlated with both age and cognitive impairment diseases. The larger the sample size, the better the predictive value of the biomarker, which can be achieved by combining data sets obtained by different medical centers. The aim of the Biomarker Boosting project was to build a reusable platform for sharing patient imaging data among medical centers to run a common analysis pipeline. I have worked on the core of the processing pipeline - automatic segmentation of the hippocampus.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;899&quot; height=&quot;454&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Fla0k1Hl4j7Szpl0nEEnbQ-4fb4060e.yVBOVyZg_X8iz2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Visualizing the segmentation result of the hippocampus. The volume can be obtained by simple voxel count.&lt;/p&gt;
&lt;p&gt;The developed algorithm was generic and could be used to segment any brain structure, but it was used with atlas data for the hippocampus. The pipeline was applied to four different cohorts collected to study dementia and mild cognitive impairment as that was the focus of the neurological researchers. I have worked together with the scientists in the same office on a regular basis (a day every week) during the project and we have kept in touch closely. We have presented and published the results of the project in neuroscience conferences and journals and I was often a co-author. I attended neurological conferences and made links with that community. We have worked together in the same software repository, the development was adhering to high code quality, testing and documentation standards. The goal was to deliver an open source software in order to increase the chances of community adoption and to serve as many neuroscientists as possible and even reach other domains.&lt;/p&gt;
&lt;h2 id=&quot;similarities-and-differences&quot;&gt;Similarities and Differences&lt;/h2&gt;
&lt;p&gt;The above examples from my career illustrate the &lt;em&gt;similarities&lt;/em&gt; and &lt;em&gt;differences&lt;/em&gt; between working as a computer scientist and as an eScience Research Engineer asI experienced them.&lt;/p&gt;
&lt;p&gt;On a first glance, the work of a computer scientist and an eSRE is the same, only the job title differs. But the main difference between the work of a computer scientist and an eSRE stem from their different &lt;strong&gt;focus.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Science:&lt;/strong&gt; Both a computer scientist and an eSRE work in scientific projects. Computer science is the science of interest of a computer scientist. Other scientific domains might present inspiration, challenge or serve as application domains, but are not the focus. eScience stands for enhanced science, an eSRE’s applies ICT expertise to facilitate breakthroughs in another science. The focus is on the domain research question.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Software:&lt;/strong&gt; Both aim to produce working software. Computer scientists write software implementing new research ideas and producing correct publishable results is sufficient. eRSE write software to solve a domain question. eRSEs take care of the usability and within (or even cross-) domain applicability of the software. While the computer scientists do not necessarily open their code (e.g. to have a competitive advantage), eSREs do this as main principle. The impact of the research software they produce should be as large as possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research:&lt;/strong&gt; Computer scientists and eSRE are researchers. eSRE can do (applied) research in their expertise area if it fits the project, but always engineer research software. The main research in the project is the one aimed at answering the domain research question.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Publication:&lt;/strong&gt; Both publish their work. Publishing as a first author (at the beginning of the career) is the main goal of a computer scientist. eSRE also publish either as a first author about the eScience or often as a co-author in a domain publication, but that is not their major goal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; Some computer scientists collaborate with other scientific domains researchers, but not all. For an eSRE this is one of the core job competencies — collaboration is much more intense and crucial for the success of the collaborative projects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Funding:&lt;/strong&gt; Computer scientists (especially to progress in their career) apply as PI for research projects funding as their core task. Sometimes also eSREs apply for funding, although usually together with a domain scientist as a PI. The Netherlands eScience center is a funding organization, hence many of the (junior) eSREs do not need to worry about acquiring funds. Although by doing their job excellently, the happy PIs are investing money for further future work together.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-about-the-wolf&quot;&gt;What about the wolf?&lt;/h2&gt;
&lt;p&gt;It is not so important what the job title is, what is important is the &lt;strong&gt;mission&lt;/strong&gt; behind it. I have enjoyed working as a computer scientist, but looking back — Europhlukes, my favorite project, could be considered an eScience project. Working closely with domain scientists can be very challenging, but also very rewarding.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using ICT expertise to enable breakthroughs in science for the good of society is very rewarding.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It seems that I haven’t changed my disposition, but I have changed into much more of a team player. If you are inspired by the possibilities to work &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;with&lt;/a&gt; the eScience Research Engineers or want to be &lt;a href=&quot;https://www.esciencecenter.nl/about/careers&quot;&gt;part of the team&lt;/a&gt;, come to work with us!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_iSf90cSRNy2SrF_I8hr7PA-540047fe.A68z8t7b.jpeg" medium="image"/><author>Elena Ranguelova</author></item><item><title>50 times faster data loading for pandas no problem</title><link>https://blog2.esciencecenter.nl/posts/2018-09-03---50-times-faster-data-loading-for-pandas-no-problem</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-09-03---50-times-faster-data-loading-for-pandas-no-problem</guid><description>&lt;h2 id=&quot;loading-irregular-data-into-pandas-using-c&quot;&gt;Loading irregular data into Pandas using C++&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3386&quot; height=&quot;2373&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__VtPjK42c2ZgoCVQPR2Hbw-eb27275d.B5vopWX__1kFW4c.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Irregular pandas&lt;/p&gt;
&lt;p&gt;If &lt;a href=&quot;https://twitter.com/egpbos/status/1034709099945054208&quot;&gt;Python is the reigning king of data science&lt;/a&gt;, Pandas is the kingdom’s bureaucracy. &lt;a href=&quot;http://wesmckinney.com/blog/apache-arrow-pandas-internals/&quot;&gt;As recognized by Pandas creator Wes McKinney himself&lt;/a&gt;, it is slow, heavy and using it can be dreadful… But it fulfills many dire needs and the country would collapse without it.&lt;/p&gt;
&lt;p&gt;Especially when your data source is slightly non-standard (and, in science, that’s almost every source) loading your data &lt;strong&gt;fast&lt;/strong&gt; can be a great struggle. In this post I’ll share two methods for making Pandas faster when loading irregular data:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;From within Python itself&lt;/li&gt;
&lt;li&gt;By whipping up your own C++ Python module &lt;strong&gt;in less time than it would take Pandas to load the data&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;pandas-so-pretty-but-so-slow&quot;&gt;Pandas: so pretty, but so slow&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;800&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_alCOYhk4upBAls2ne9vLOA-1ede877d.CoK_2CoU_29ojDp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data is my middle name&lt;/p&gt;
&lt;p&gt;The “slow and heavy” mostly goes for &lt;strong&gt;idiomatic&lt;/strong&gt; Pandas, or at least what I would expect to be idiomatic, i.e. using the package’s built-in features.&lt;/p&gt;
&lt;p&gt;For instance, say I have a simple dataframe: one column has words, another has counts (of those words in a set of documents). The table could look something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;the           &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1028012&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            128102&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;what            &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;38012&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;whoops          &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12800&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scallywag   &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, there’s an artifact in the counts: some of them had an artificial frequency of 100000000 added to them. We want to get rid of this artifact, so for the numbers higher than 100000000 we subtract 100000000. I would say idiomatic Python/Pandas would be to use a one-liner using &lt;code&gt;apply&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# THIS IS SOOOO SLOOOOW!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; df.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;lambda&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; x:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;word&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;counts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;counts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;counts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;               axis&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;               broadcast&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I love compact one-liners, it’s one of the reasons I love using Python. This one is, however, slower than watching paint dry. The following is orders of magnitude quicker:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# better:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; df[[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;word&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;counts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;copy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df2.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[websites.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;clean_no_artifrq&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;counts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100000000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;counts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100000000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes use of the fact that Pandas columns are actually NumPy arrays.&lt;/p&gt;
&lt;h3 id=&quot;numpy-&quot;&gt;NumPy ❤&lt;/h3&gt;
&lt;p&gt;Now, if Pandas is bureaucracy, NumPy is like iron, or plastics, or wheels, or roads, or computers, or the internet… It’s a great piece of technology that makes the whole Python world run more efficiently.&lt;/p&gt;
&lt;p&gt;However, it is really its own sub-language, and it has its own idiomatic uses.&lt;br&gt;
It is a language for vectorized numerical mathematics. It beautifully expresses mathematical operations on arrays of numbers in a way that comes very close to the expressiveness of mathematics used to model scientific problems in many fields, especially natural sciences and engineering. For computational scientists in such fields, loops are mental overhead. Vector/matrix/tensor operations clear this overhead.&lt;/p&gt;
&lt;p&gt;I am happy to use this language when I’m working with raw numerical data, but it annoys me to no end that I have to resort to using it when working with Pandas. I do not want to have to build my own roads in order to make the bureaucracy work more smoothly…&lt;/p&gt;
&lt;p&gt;Also, it is not the language I expect of a tabular data handling tool. Why should it make sense that column-wise operations are orders of magnitude faster than row-wise operations? It’s a table, it should work either way.&lt;/p&gt;
&lt;p&gt;Nevertheless, even though it pains my soul, it seems that in order to get some performance and still use the Pandas ecosystem (which has a lot of great features), we must often work around Pandas’ limitations by applying NumPy logic, rather than being able to constantly stay in a tabular mindset.&lt;/p&gt;
&lt;p&gt;However, if we’re going to get out of the Pandas mindset anyway, we could go one step further. If we’re going to build our own roads, why not go for high speed train connections instead?&lt;/p&gt;
&lt;h2 id=&quot;loading-irregular-data-into-pandas&quot;&gt;Loading irregular data into Pandas&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gQlglop8uC1KVY9WN-ZfbA-06a24d5e.z_dEew4L_Z2jSjW0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pandas ingesting messy data&lt;/p&gt;
&lt;p&gt;The problem I want to discuss here was one I ran into while working on the &lt;a href=&quot;https://www.esciencecenter.nl/project/ticclat&quot;&gt;TICCLAT project&lt;/a&gt; using the &lt;a href=&quot;https://github.com/LanguageMachines/PICCL&quot;&gt;TICCL spelling / OCR correction tool&lt;/a&gt;. I wanted to load the following type of text file into Pandas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1190068&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#67676465299&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1391727&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#85478414561,86121676092,86741116243,88625929516,89990773818&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1638659&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#71938173924,72490106635,72511962205,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1806002&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#105558929611,106429736524,120455253831&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without going into too much detail, the longer numbers represent words in a text and the short ones at the front represent possible errors (e.g. an &lt;strong&gt;o&lt;/strong&gt; that should have been an &lt;strong&gt;e&lt;/strong&gt;). Essentially this is a key-value store: the keys are the first integers, then comes a &lt;code&gt;#&lt;/code&gt; separator, and the corresponding value is a list of integers separated by commas. The list lengths range between one and hundreds of integer numbers and are completely irregular.&lt;/p&gt;
&lt;p&gt;One could naively load the file as a key value table, for instance like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;read_csv&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;filename.txt&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 names&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 sep&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 index_col&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# we can use the key as index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 converters&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;                             lambda&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; w:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; tuple&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(w.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;,&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, I wanted to load it in a way that I could do efficient statistics with it. Doing statistics on an array of lists is again horribly slow.&lt;/p&gt;
&lt;p&gt;Transforming it to a regular table seems like a good bet, because then we can again make use of the magic (and speed) of NumPy. This can be done by transforming &lt;code&gt;df&lt;/code&gt; as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; df[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(pd.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Series&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stack&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_frame&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;list_index&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], inplace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, axis&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;columns&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, inplace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works, albeit slowly. Just loading a 23MB file took over 3 minutes on my laptop. When I encountered a file of 1.8GB that was structured this way, it was time to bring out the big guns. Not only because it would take at least 4 hours to load (probably more, I don’t expect this to scale linearly), but also because it might need too much RAM. Pandas is not known for its efficient use of memory and in this case it can hardly be blamed, because loading irregular data makes it hard to predict what resources are necessary, making dynamic allocation necessary. That means copying data around the memory banks, which will slow things down a lot.&lt;/p&gt;
&lt;h2 id=&quot;building-a-python-c-module-in-under-10-minutes&quot;&gt;Building a Python C++ module in under 10 minutes&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jjXJIgBEdZ6RPApXojBX5Q-313e9b21.Cv16ErdC_B2UDl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ok, let’s say 15 minutes…&lt;/p&gt;
&lt;p&gt;… I guess if you don’t know any C++ it may take a bit longer, but not that much. Just start out with programming like you would in Python, but declare variables with types, put semicolons at the end of lines, put loop and branching conditions in parentheses, put curly braces around indented blocks and forget about the colons that start Python indented blocks… that should get you about 80% of the way there. Oh and avoid pointers for the time being. Oh and use references whenever possible. They’re kinda like pointers but… Well maybe avoid those as well for now.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anyway&lt;/em&gt;, let’s see how to get this done in 10 minutes.&lt;/p&gt;
&lt;h3 id=&quot;setup-the-environment&quot;&gt;Setup the environment&lt;/h3&gt;
&lt;p&gt;The requirements are to have &lt;a href=&quot;https://conda.io/miniconda.html&quot;&gt;Miniconda&lt;/a&gt; installed and to create a &lt;code&gt;conda&lt;/code&gt; virtual environment with the &lt;code&gt;xtensor-python&lt;/code&gt; Python bindings for the C++ &lt;a href=&quot;http://quantstack.net/xtensor&quot;&gt;xtensor&lt;/a&gt; package:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;conda create &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n build_a_python_cpp_module xtensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c conda&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;forge&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Activate the environment to run the commands in the rest of this article:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source activate build_a_python_cpp_module&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also install a C++ compiler in this environment using &lt;code&gt;conda&lt;/code&gt;, but you probably already have one of those.&lt;/p&gt;
&lt;h3 id=&quot;start-your-project-with-cookiecutter&quot;&gt;Start your project with Cookiecutter&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;172&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1Ur9MmksUtYJHs_EbtxIqg-cee5f8b8.AI8_rkI7_Z2fEMvS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We then start out our new Python module project with the &lt;code&gt;xtensor-python&lt;/code&gt; &lt;a href=&quot;https://cookiecutter.readthedocs.io/en/latest/&quot;&gt;Cookiecutter&lt;/a&gt; template (see [my colleague’s blog post]( for a great Python project template). Install Cookiecutter with &lt;code&gt;pip&lt;/code&gt; (if you don’t have it yet) and begin your project:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pip install cookiecutter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cookiecutter &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;https:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;github.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;QuantStack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;xtensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cookiecutter.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cookiecutter will now ask you some questions about your project, like its name, your name, etcetera. The answers will be used to generate the project’s initial files and even some initial documentation.&lt;/p&gt;
&lt;p&gt;After this, you’ll have a directory named after your project, containing all the files you need to build and install your C++ Python module.&lt;/p&gt;
&lt;p&gt;The file you’ll want to look at first is &lt;code&gt;src/main.cpp&lt;/code&gt;. This contains a number of example functions and the boilerplate of converting them into Python module functions.&lt;/p&gt;
&lt;h3 id=&quot;loading-irregular-data-into-pandas-via-c&quot;&gt;Loading irregular data into Pandas… via C++&lt;/h3&gt;
&lt;p&gt;In our case, we want to build an efficient way of loading our irregular key-value file. Since Pandas columns are in fact NumPy arrays, we’re going to use C++ to fill up the necessary NumPy arrays. Once that is done, we can easily convert those to a Pandas dataframe in Python itself. This way we optimized the most costly part of loading the data and still keep the C++ to a minimum (also, I have no idea how to load it directly into a Pandas dataframe from C++, but never mind that).&lt;/p&gt;
&lt;p&gt;So we will need to build three arrays of unsigned integers: two with 32 bit integers (the keys and the list_indices) and one with 64 bit integers (the list values). As the Cookiecutter template examples show, NumPy arrays can be defined using the &lt;code&gt;pyarray&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;To avoid costly resizing of our arrays, it would be nice if we can calculate the total size we will need for these three arrays. Luckily, we can do that by realizing that every list value will generate a row in the table. The easiest way I can think of to do this is to count all the commas and new-lines in the file, for instance like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ifstream&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; file&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;filename.txt&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;char c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;size_t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array_size &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(file.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(c)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (c &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;,&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   ++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array_size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This scans the entire file, which we’ll have to do again to read the actual numbers, so this is costly in terms of disk I/O. Almost certainly, resizing arrays dynamically many times while reading the file only once would be far more costly, so it is worth it.&lt;/p&gt;
&lt;p&gt;Now that we know the sizes of the arrays we need, we can generate them:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;auto first_array &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xt::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pyarray&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unsigned&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;from_shape&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({array_size});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... etc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we start going through the file, reading in the numbers and separators and putting them in our arrays as we go. You’ll find &lt;a href=&quot;https://github.com/TICCLAT/ticcl-output-reader&quot;&gt;a finished example on GitHub&lt;/a&gt; which I’m using in the &lt;a href=&quot;https://www.esciencecenter.nl/project/ticclat&quot;&gt;TICCLAT project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, compiling and installing happens from the command line using setup.py:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python setup.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;py&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or you can use &lt;code&gt;pip&lt;/code&gt;, as I found out by reading the &lt;code&gt;README.md&lt;/code&gt; … that Cookiecutter automatically generated for me!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pip install .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, inside your virtual environment, you can start your Python session, import your freshly baked module and start crunching numbers at maximum speed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TICCLAT/ticcl-output-reader/blob/8d2d5886be48c3e9ad401e49c6a48e497b359f1b/src/main.cpp#L22&quot;&gt;The function in the example on GitHub&lt;/a&gt; returns a tuple of three arrays. In Python, you can directly convert these into a Pandas dataframe:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;cpp_arrays&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; my_module.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fast_reader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;filename.txt&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DataFrame&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;from_records&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: cpp_arrays[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;list_index&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: cpp_arrays[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;value&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: cpp_arrays[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;       index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;list_index&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result looks exactly like the dataframe loaded using the Pandas example above. The only difference is that it loads over 50 times as fast.&lt;/p&gt;
&lt;p&gt;So there you have it. Perhaps this wasn’t really 10 minutes of work, I actually spent two hours creating and debugging the entire thing, but that’s still less than the four hours I’d have to wait on Pandas to load the data, and I will now save hours of loading time in the future. I even had time to spare to write this blog post (well, a first version at least)!&lt;/p&gt;
&lt;p&gt;An added bonus of this setup I didn’t even touch upon is that the C++ &lt;code&gt;pyarray&lt;/code&gt; objects are actually &lt;code&gt;xtensor&lt;/code&gt; arrays. These &lt;a href=&quot;https://xtensor.readthedocs.io/en/latest/numpy.html&quot;&gt;can be used the same way as NumPy arrays&lt;/a&gt;, with essentially the same syntax, but a lot faster. Moreover, there are Julia and R bindings that should work just as easy as the Python bindings I used here. In fact, the function I wrote for this module could be directly reused in packages for R and Julia. Pretty cool!&lt;/p&gt;
&lt;h2 id=&quot;c-dont-be-scared&quot;&gt;C++: don’t be scared!&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;563&quot; height=&quot;682&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XQ0EU5XYtzGfXcycU8ZdGQ-b41233ff.BiC0yhCi_Z1aQS0d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Learning a bit of C++ has big advantages.&lt;/p&gt;
&lt;p&gt;Maximum performance is the obvious one. You’ll get this not just by whipping up your own libraries or number crunching extensions, but also by making use of the ecosystem of high performance C++ libraries already out there.&lt;/p&gt;
&lt;p&gt;The other big advantage is that it is the language on which most of our high performance data science (Python, R, Julia) modules are (or should be) based. If you want to add to that ecosystem, C++ will be your best bet.&lt;/p&gt;
&lt;p&gt;Yes, C++ can be pretty tough to debug, but it has a huge community to lend you a hand when you get stuck. And in fact, a current trend in the C++ world is that more and more user friendly libraries are popping up.&lt;/p&gt;
&lt;p&gt;Already, dataframe solutions for C++ are being worked on. The xtensor universe has &lt;a href=&quot;https://github.com/QuantStack/xframe&quot;&gt;xframe&lt;/a&gt;. The ROOT particle physics analysis suite from CERN has &lt;a href=&quot;https://root.cern/doc/master/classROOT_1_1RDataFrame.html&quot;&gt;RDataFrame&lt;/a&gt;. We can even do interactive C++ now with &lt;a href=&quot;https://root.cern.ch/cling&quot;&gt;cling&lt;/a&gt;, also &lt;a href=&quot;http://jupyter.org/try&quot;&gt;from a Jupyter notebook (try it!)&lt;/a&gt;. Perhaps one day soon, we won’t have to choose between user friendliness and performance any more.&lt;/p&gt;</description><pubDate>Mon, 03 Sep 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;loading-irregular-data-into-pandas-using-c&quot;&gt;Loading irregular data into Pandas using C++&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3386&quot; height=&quot;2373&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__VtPjK42c2ZgoCVQPR2Hbw-eb27275d.B5vopWX__1kFW4c.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Irregular pandas&lt;/p&gt;
&lt;p&gt;If &lt;a href=&quot;https://twitter.com/egpbos/status/1034709099945054208&quot;&gt;Python is the reigning king of data science&lt;/a&gt;, Pandas is the kingdom’s bureaucracy. &lt;a href=&quot;http://wesmckinney.com/blog/apache-arrow-pandas-internals/&quot;&gt;As recognized by Pandas creator Wes McKinney himself&lt;/a&gt;, it is slow, heavy and using it can be dreadful… But it fulfills many dire needs and the country would collapse without it.&lt;/p&gt;
&lt;p&gt;Especially when your data source is slightly non-standard (and, in science, that’s almost every source) loading your data &lt;strong&gt;fast&lt;/strong&gt; can be a great struggle. In this post I’ll share two methods for making Pandas faster when loading irregular data:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;From within Python itself&lt;/li&gt;
&lt;li&gt;By whipping up your own C++ Python module &lt;strong&gt;in less time than it would take Pandas to load the data&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;pandas-so-pretty-but-so-slow&quot;&gt;Pandas: so pretty, but so slow&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;800&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_alCOYhk4upBAls2ne9vLOA-1ede877d.CoK_2CoU_29ojDp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data is my middle name&lt;/p&gt;
&lt;p&gt;The “slow and heavy” mostly goes for &lt;strong&gt;idiomatic&lt;/strong&gt; Pandas, or at least what I would expect to be idiomatic, i.e. using the package’s built-in features.&lt;/p&gt;
&lt;p&gt;For instance, say I have a simple dataframe: one column has words, another has counts (of those words in a set of documents). The table could look something like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;the           &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1028012&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;and&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;            128102&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;what            &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;38012&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;whoops          &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;12800&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;scallywag   &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000001&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, there’s an artifact in the counts: some of them had an artificial frequency of 100000000 added to them. We want to get rid of this artifact, so for the numbers higher than 100000000 we subtract 100000000. I would say idiomatic Python/Pandas would be to use a one-liner using &lt;code&gt;apply&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# THIS IS SOOOO SLOOOOW!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; df.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;lambda&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; x:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;word&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;counts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;counts&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;100000000&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; else&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; x.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;counts&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;               axis&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;               broadcast&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I love compact one-liners, it’s one of the reasons I love using Python. This one is, however, slower than watching paint dry. The following is orders of magnitude quicker:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# better:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; df[[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;word&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;counts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;copy&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df2.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;loc&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[websites.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;clean_no_artifrq&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;counts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100000000&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;counts&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 100000000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes use of the fact that Pandas columns are actually NumPy arrays.&lt;/p&gt;
&lt;h3 id=&quot;numpy-&quot;&gt;NumPy ❤&lt;/h3&gt;
&lt;p&gt;Now, if Pandas is bureaucracy, NumPy is like iron, or plastics, or wheels, or roads, or computers, or the internet… It’s a great piece of technology that makes the whole Python world run more efficiently.&lt;/p&gt;
&lt;p&gt;However, it is really its own sub-language, and it has its own idiomatic uses.&lt;br&gt;
It is a language for vectorized numerical mathematics. It beautifully expresses mathematical operations on arrays of numbers in a way that comes very close to the expressiveness of mathematics used to model scientific problems in many fields, especially natural sciences and engineering. For computational scientists in such fields, loops are mental overhead. Vector/matrix/tensor operations clear this overhead.&lt;/p&gt;
&lt;p&gt;I am happy to use this language when I’m working with raw numerical data, but it annoys me to no end that I have to resort to using it when working with Pandas. I do not want to have to build my own roads in order to make the bureaucracy work more smoothly…&lt;/p&gt;
&lt;p&gt;Also, it is not the language I expect of a tabular data handling tool. Why should it make sense that column-wise operations are orders of magnitude faster than row-wise operations? It’s a table, it should work either way.&lt;/p&gt;
&lt;p&gt;Nevertheless, even though it pains my soul, it seems that in order to get some performance and still use the Pandas ecosystem (which has a lot of great features), we must often work around Pandas’ limitations by applying NumPy logic, rather than being able to constantly stay in a tabular mindset.&lt;/p&gt;
&lt;p&gt;However, if we’re going to get out of the Pandas mindset anyway, we could go one step further. If we’re going to build our own roads, why not go for high speed train connections instead?&lt;/p&gt;
&lt;h2 id=&quot;loading-irregular-data-into-pandas&quot;&gt;Loading irregular data into Pandas&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gQlglop8uC1KVY9WN-ZfbA-06a24d5e.z_dEew4L_Z2jSjW0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Pandas ingesting messy data&lt;/p&gt;
&lt;p&gt;The problem I want to discuss here was one I ran into while working on the &lt;a href=&quot;https://www.esciencecenter.nl/project/ticclat&quot;&gt;TICCLAT project&lt;/a&gt; using the &lt;a href=&quot;https://github.com/LanguageMachines/PICCL&quot;&gt;TICCL spelling / OCR correction tool&lt;/a&gt;. I wanted to load the following type of text file into Pandas:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1190068&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#67676465299&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1391727&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#85478414561,86121676092,86741116243,88625929516,89990773818&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1638659&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#71938173924,72490106635,72511962205,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1806002&lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;#105558929611,106429736524,120455253831&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without going into too much detail, the longer numbers represent words in a text and the short ones at the front represent possible errors (e.g. an &lt;strong&gt;o&lt;/strong&gt; that should have been an &lt;strong&gt;e&lt;/strong&gt;). Essentially this is a key-value store: the keys are the first integers, then comes a &lt;code&gt;#&lt;/code&gt; separator, and the corresponding value is a list of integers separated by commas. The list lengths range between one and hundreds of integer numbers and are completely irregular.&lt;/p&gt;
&lt;p&gt;One could naively load the file as a key value table, for instance like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;read_csv&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;filename.txt&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 names&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 sep&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;#&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 index_col&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;# we can use the key as index&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;                 converters&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;                             lambda&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; w:&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; tuple&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(w.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;split&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;,&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, I wanted to load it in a way that I could do efficient statistics with it. Doing statistics on an array of lists is again horribly slow.&lt;/p&gt;
&lt;p&gt;Transforming it to a regular table seems like a good bet, because then we can again make use of the magic (and speed) of NumPy. This can be done by transforming &lt;code&gt;df&lt;/code&gt; as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; df[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(pd.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;Series&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;stack&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;to_frame&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;([&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;list_index&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;], inplace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;df.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;rename&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}, axis&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&apos;columns&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, inplace&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;True&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works, albeit slowly. Just loading a 23MB file took over 3 minutes on my laptop. When I encountered a file of 1.8GB that was structured this way, it was time to bring out the big guns. Not only because it would take at least 4 hours to load (probably more, I don’t expect this to scale linearly), but also because it might need too much RAM. Pandas is not known for its efficient use of memory and in this case it can hardly be blamed, because loading irregular data makes it hard to predict what resources are necessary, making dynamic allocation necessary. That means copying data around the memory banks, which will slow things down a lot.&lt;/p&gt;
&lt;h2 id=&quot;building-a-python-c-module-in-under-10-minutes&quot;&gt;Building a Python C++ module in under 10 minutes&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jjXJIgBEdZ6RPApXojBX5Q-313e9b21.Cv16ErdC_B2UDl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Ok, let’s say 15 minutes…&lt;/p&gt;
&lt;p&gt;… I guess if you don’t know any C++ it may take a bit longer, but not that much. Just start out with programming like you would in Python, but declare variables with types, put semicolons at the end of lines, put loop and branching conditions in parentheses, put curly braces around indented blocks and forget about the colons that start Python indented blocks… that should get you about 80% of the way there. Oh and avoid pointers for the time being. Oh and use references whenever possible. They’re kinda like pointers but… Well maybe avoid those as well for now.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anyway&lt;/em&gt;, let’s see how to get this done in 10 minutes.&lt;/p&gt;
&lt;h3 id=&quot;setup-the-environment&quot;&gt;Setup the environment&lt;/h3&gt;
&lt;p&gt;The requirements are to have &lt;a href=&quot;https://conda.io/miniconda.html&quot;&gt;Miniconda&lt;/a&gt; installed and to create a &lt;code&gt;conda&lt;/code&gt; virtual environment with the &lt;code&gt;xtensor-python&lt;/code&gt; Python bindings for the C++ &lt;a href=&quot;http://quantstack.net/xtensor&quot;&gt;xtensor&lt;/a&gt; package:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;conda create &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;n build_a_python_cpp_module xtensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c conda&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;forge&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Activate the environment to run the commands in the rest of this article:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;source activate build_a_python_cpp_module&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could also install a C++ compiler in this environment using &lt;code&gt;conda&lt;/code&gt;, but you probably already have one of those.&lt;/p&gt;
&lt;h3 id=&quot;start-your-project-with-cookiecutter&quot;&gt;Start your project with Cookiecutter&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;172&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1Ur9MmksUtYJHs_EbtxIqg-cee5f8b8.AI8_rkI7_Z2fEMvS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We then start out our new Python module project with the &lt;code&gt;xtensor-python&lt;/code&gt; &lt;a href=&quot;https://cookiecutter.readthedocs.io/en/latest/&quot;&gt;Cookiecutter&lt;/a&gt; template (see [my colleague’s blog post]( for a great Python project template). Install Cookiecutter with &lt;code&gt;pip&lt;/code&gt; (if you don’t have it yet) and begin your project:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pip install cookiecutter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cookiecutter &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;https:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;github.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;QuantStack&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;xtensor&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cookiecutter.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cookiecutter will now ask you some questions about your project, like its name, your name, etcetera. The answers will be used to generate the project’s initial files and even some initial documentation.&lt;/p&gt;
&lt;p&gt;After this, you’ll have a directory named after your project, containing all the files you need to build and install your C++ Python module.&lt;/p&gt;
&lt;p&gt;The file you’ll want to look at first is &lt;code&gt;src/main.cpp&lt;/code&gt;. This contains a number of example functions and the boilerplate of converting them into Python module functions.&lt;/p&gt;
&lt;h3 id=&quot;loading-irregular-data-into-pandas-via-c&quot;&gt;Loading irregular data into Pandas… via C++&lt;/h3&gt;
&lt;p&gt;In our case, we want to build an efficient way of loading our irregular key-value file. Since Pandas columns are in fact NumPy arrays, we’re going to use C++ to fill up the necessary NumPy arrays. Once that is done, we can easily convert those to a Pandas dataframe in Python itself. This way we optimized the most costly part of loading the data and still keep the C++ to a minimum (also, I have no idea how to load it directly into a Pandas dataframe from C++, but never mind that).&lt;/p&gt;
&lt;p&gt;So we will need to build three arrays of unsigned integers: two with 32 bit integers (the keys and the list_indices) and one with 64 bit integers (the list values). As the Cookiecutter template examples show, NumPy arrays can be defined using the &lt;code&gt;pyarray&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;To avoid costly resizing of our arrays, it would be nice if we can calculate the total size we will need for these three arrays. Luckily, we can do that by realizing that every list value will generate a row in the table. The easiest way I can think of to do this is to count all the commas and new-lines in the file, for instance like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;ifstream&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt; file&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;filename.txt&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;char c;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;std::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;size_t&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; array_size &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(file.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(c)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; (c &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;,&apos;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; ||&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; c &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &apos;\n&apos;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;   ++&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;array_size;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This scans the entire file, which we’ll have to do again to read the actual numbers, so this is costly in terms of disk I/O. Almost certainly, resizing arrays dynamically many times while reading the file only once would be far more costly, so it is worth it.&lt;/p&gt;
&lt;p&gt;Now that we know the sizes of the arrays we need, we can generate them:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;auto first_array &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; xt::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;pyarray&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;unsigned&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;from_shape&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;({array_size});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#DBEDFF&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; ... etc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we start going through the file, reading in the numbers and separators and putting them in our arrays as we go. You’ll find &lt;a href=&quot;https://github.com/TICCLAT/ticcl-output-reader&quot;&gt;a finished example on GitHub&lt;/a&gt; which I’m using in the &lt;a href=&quot;https://www.esciencecenter.nl/project/ticclat&quot;&gt;TICCLAT project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, compiling and installing happens from the command line using setup.py:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;python setup.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;py&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or you can use &lt;code&gt;pip&lt;/code&gt;, as I found out by reading the &lt;code&gt;README.md&lt;/code&gt; … that Cookiecutter automatically generated for me!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;pip install .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, inside your virtual environment, you can start your Python session, import your freshly baked module and start crunching numbers at maximum speed.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/TICCLAT/ticcl-output-reader/blob/8d2d5886be48c3e9ad401e49c6a48e497b359f1b/src/main.cpp#L22&quot;&gt;The function in the example on GitHub&lt;/a&gt; returns a tuple of three arrays. In Python, you can directly convert these into a Pandas dataframe:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rb&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;cpp_arrays&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; my_module.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;fast_reader&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;filename.txt&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; pd.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;DataFrame&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;from_records&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;       {&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: cpp_arrays[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;list_index&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: cpp_arrays[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;        &quot;value&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: cpp_arrays[&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;]},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#FFAB70&quot;&gt;       index&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;list_index&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result looks exactly like the dataframe loaded using the Pandas example above. The only difference is that it loads over 50 times as fast.&lt;/p&gt;
&lt;p&gt;So there you have it. Perhaps this wasn’t really 10 minutes of work, I actually spent two hours creating and debugging the entire thing, but that’s still less than the four hours I’d have to wait on Pandas to load the data, and I will now save hours of loading time in the future. I even had time to spare to write this blog post (well, a first version at least)!&lt;/p&gt;
&lt;p&gt;An added bonus of this setup I didn’t even touch upon is that the C++ &lt;code&gt;pyarray&lt;/code&gt; objects are actually &lt;code&gt;xtensor&lt;/code&gt; arrays. These &lt;a href=&quot;https://xtensor.readthedocs.io/en/latest/numpy.html&quot;&gt;can be used the same way as NumPy arrays&lt;/a&gt;, with essentially the same syntax, but a lot faster. Moreover, there are Julia and R bindings that should work just as easy as the Python bindings I used here. In fact, the function I wrote for this module could be directly reused in packages for R and Julia. Pretty cool!&lt;/p&gt;
&lt;h2 id=&quot;c-dont-be-scared&quot;&gt;C++: don’t be scared!&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;563&quot; height=&quot;682&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XQ0EU5XYtzGfXcycU8ZdGQ-b41233ff.BiC0yhCi_Z1aQS0d.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Learning a bit of C++ has big advantages.&lt;/p&gt;
&lt;p&gt;Maximum performance is the obvious one. You’ll get this not just by whipping up your own libraries or number crunching extensions, but also by making use of the ecosystem of high performance C++ libraries already out there.&lt;/p&gt;
&lt;p&gt;The other big advantage is that it is the language on which most of our high performance data science (Python, R, Julia) modules are (or should be) based. If you want to add to that ecosystem, C++ will be your best bet.&lt;/p&gt;
&lt;p&gt;Yes, C++ can be pretty tough to debug, but it has a huge community to lend you a hand when you get stuck. And in fact, a current trend in the C++ world is that more and more user friendly libraries are popping up.&lt;/p&gt;
&lt;p&gt;Already, dataframe solutions for C++ are being worked on. The xtensor universe has &lt;a href=&quot;https://github.com/QuantStack/xframe&quot;&gt;xframe&lt;/a&gt;. The ROOT particle physics analysis suite from CERN has &lt;a href=&quot;https://root.cern/doc/master/classROOT_1_1RDataFrame.html&quot;&gt;RDataFrame&lt;/a&gt;. We can even do interactive C++ now with &lt;a href=&quot;https://root.cern.ch/cling&quot;&gt;cling&lt;/a&gt;, also &lt;a href=&quot;http://jupyter.org/try&quot;&gt;from a Jupyter notebook (try it!)&lt;/a&gt;. Perhaps one day soon, we won’t have to choose between user friendliness and performance any more.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_alCOYhk4upBAls2ne9vLOA-1ede877d.CoK_2CoU.jpeg" medium="image"/><author>Patrick Bos</author></item><item><title>why use an fpga instead of a cpu or gpu</title><link>https://blog2.esciencecenter.nl/posts/2018-08-14---why-use-an-fpga-instead-of-a-cpu-or-gpu</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-08-14---why-use-an-fpga-instead-of-a-cpu-or-gpu</guid><description>&lt;h2 id=&quot;the-disadvantages-of-field-programmable-gate-arrays&quot;&gt;The (dis)advantages of Field Programmable Gate Arrays&lt;/h2&gt;
&lt;p&gt;Recently, &lt;a href=&quot;https://newsroom.intel.com/news-releases/intel-completes-acquisition-of-altera/&quot;&gt;Intel bought Altera&lt;/a&gt;, one of the largest producers of FPGAs. Intel paid a whopping $16.7 billion, making it their largest acquisition ever. In other news, &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2014/06/HC26.12.520-Recon-Fabric-Pulnam-Microsoft-Catapult.pdf&quot;&gt;Microsoft is using FPGAs in its data centers&lt;/a&gt;, and &lt;a href=&quot;https://aws.amazon.com/ec2/instance-types/f1/&quot;&gt;Amazon is offering&lt;/a&gt; them on their cloud services. Previously, these FPGAs were mainly used in &lt;em&gt;electronics&lt;/em&gt; engineering, but not so much in &lt;em&gt;software&lt;/em&gt; engineering. Are FPGAs about to take off and become serious alternatives to CPUs and GPUs?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;251&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_c54zfRSRF7i6MOSy04Pa6Q-521e8422.B0f-ikNG_ZJMljT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-an-fpga&quot;&gt;What is an FPGA?&lt;/h2&gt;
&lt;p&gt;If you want to compute something, the common approach is to write some software for an instruction based architecture, such as a CPU or GPU. Another, more arduous, route one could take is to design a special circuit for this specific computation — as opposed to writing instructions for a general purpose circuit such as a CPU or GPU.&lt;/p&gt;
&lt;p&gt;Once you have designed this circuit, you need some way to implement the design so that you can actually compute something. One way, which requires quite deep pockets, is to actually produce a circuit that implements this design (this is called an Application Specific Integrated Circuit or ASIC).&lt;/p&gt;
&lt;p&gt;An easier way, and the main topic of this blog, is to implement your circuit design is to use a &lt;em&gt;Field Programmable Gate Array&lt;/em&gt; (FPGA), a &lt;em&gt;reconfigurable integrated circuit&lt;/em&gt;. You can configure the FPGA to become any circuit you want to (as long as it fits on the FPGA). This is quite a bit different than the &lt;em&gt;instruction-based hardware&lt;/em&gt; most programmers are used to, such as CPUs and GPUs. Instruction-based hardware is configured via &lt;em&gt;software&lt;/em&gt;, whereas FPGAs are instead configured by specifying a &lt;em&gt;hardware&lt;/em&gt; circuit.&lt;/p&gt;
&lt;h2 id=&quot;disadvantages-of-fpgas&quot;&gt;(Dis)Advantages of FPGAs&lt;/h2&gt;
&lt;p&gt;Why would you prefer to use an FPGA for your computation over the more common CPU or GPU? The differences with GPUs and CPUs are in the following areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latency&lt;/strong&gt;: How long does it take to compute something?&lt;br&gt;
→ FPGAs are good at this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connectivity&lt;/strong&gt;: What input/output can we connect and with which bandwidth?&lt;br&gt;
→ FPGAs can directly be connected to inputs and can offer very high bandwith.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Engineering cost&lt;/strong&gt;: How much effort does it cost to express the computation?&lt;br&gt;
→ The engineering cost is typically much higher than for instruction based architectures, so the advantages must really be worth it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Energy efficiency&lt;/strong&gt;: How much energy does it cost to compute something?&lt;br&gt;
→ This is often listed as a large benefit of FPGAs, but whether FPGAs are better than CPUs or GPUs really depends on the application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s discuss each of these in more detail.&lt;/p&gt;
&lt;h2 id=&quot;low-latency&quot;&gt;Low latency&lt;/h2&gt;
&lt;p&gt;Low latency is what you need if you are programming the autopilot of a jet fighter or a high-frequency algorithmic trading engine: the time between an input and its response as short as possible. This is where FPGAs are much better than CPUs (or GPUs, which have to communicate via the CPU).&lt;/p&gt;
&lt;p&gt;With an FPGA it is feasible to get a latency around or below 1 microsecond, whereas with a CPU a latency smaller than 50 microseconds is already very good. Moreover, the latency of an FPGA is much more deterministic. One of the main reasons for this low latency is that FPGAs can be much more specialized: they do not depend on the generic operating system, and communication does not have to go via generic buses (such as USB or PCIe).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rIAJPMywpoe5q_RDLpV1uw-c989ae8b.Bk8eJQzJ_Z2sWVYc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A couple of FPGAs in mid-air (probably)&lt;/p&gt;
&lt;h2 id=&quot;connectivity&quot;&gt;Connectivity&lt;/h2&gt;
&lt;p&gt;On an FPGA, you can hook up any data source, such as a network interface or sensor, directly to the &lt;em&gt;pins of the chip&lt;/em&gt;. This in sharp contrast to GPUs and CPUs, where you have to connect your source via the standardized buses (such as USB or PCIe) — and depend on the operating system to deliver the data to your application. A direct connection to the pins of the chip gives very high bandwidth (as well as low latency).&lt;/p&gt;
&lt;p&gt;This high bandwidth is needed, for example, in radio-astronomy applications, such as &lt;a href=&quot;http://www.lofar.org/about-lofar/about-lofar&quot;&gt;LOFAR&lt;/a&gt; and &lt;a href=&quot;https://www.skatelescope.org/&quot;&gt;SKA&lt;/a&gt;. In these applications there are a lot of specialized sensors in the field, which generate an enormous amount of data. The volume of data needs to be reduced before being sent off, to make it more manageable. For this purpose, the Netherlands Institute for Radio Astronomy, &lt;a href=&quot;https://www.astron.nl/&quot;&gt;ASTRON&lt;/a&gt;, designed the &lt;a href=&quot;https://www.astron.nl/r-d-laboratory/uniboard/uniboard-i-and-ii&quot;&gt;&lt;em&gt;Uniboard²&lt;/em&gt;&lt;/a&gt;, a board with four FPGAs which can handle more data per second than the Amsterdam internet exchange.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;447&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bomy9uvjcoI5F8rALbwUFg-540a7a92.Dv4t6kiQ_JAeKH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;These small radio astronomy antennas generate a lot of data (image credit: Svenlafe at en.wikipedia )&lt;/p&gt;
&lt;h2 id=&quot;engineering-cost&quot;&gt;Engineering cost&lt;/h2&gt;
&lt;p&gt;Before turning to the subtle issue of energy efficiency, let’s discuss the main disadvantage of FPGAs: they are really &lt;em&gt;much&lt;/em&gt; harder to program/configure than instruction based architectures (i.e. CPUs and GPUs). Traditionally, these hardware circuits are described via &lt;em&gt;Hardware Description Languages&lt;/em&gt; (HDL), such as VHDL and Verilog, whereas software is programmed via one of a plethora of programming languages, such as Java, C and Python.&lt;/p&gt;
&lt;p&gt;From a theoretical perspective, both hardware description languages and programming languages can be use to express any computation (both are Turing complete), but the difference in engineering details is vast.&lt;/p&gt;
&lt;p&gt;An upcoming trend is High Level Synthesis (HLS): programming FPGAs using regular programming languages such as OpenCL or C++, allowing for a much higher level of abstraction. However, even when using such languages, programming FPGAs is still an order of magnitude more difficult than programming instruction based systems.&lt;/p&gt;
&lt;p&gt;==A large part of the difficulty of programming FPGAs are the== ==&lt;strong&gt;long&lt;/strong&gt;== ==compilation times. For example, when using Intel’s OpenCL compiler, it takes somewhere between 4 and 12== ==&lt;em&gt;hours&lt;/em&gt;== ==to compile a typical program for the FPGA. This is due to the== ==&lt;em&gt;place-and-route phase&lt;/em&gt;====: the custom circuit that we== ==&lt;em&gt;want&lt;/em&gt;== ==needs to be mapped to the FPGA resources that we== ==&lt;em&gt;have&lt;/em&gt;====, with paths as short as possible. This is a complex optimization problem which requires significant computation. Intel does offer an emulator, so testing for correctness does not require this long step, but determining and optimizing performance does require these overnight compile phases.==&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;413&quot; height=&quot;360&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_J-1MC3QGbIuwq4tb-yr-iA-c56003e3.DjPvFJEe_gOSCM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Programming FPGAs gives you a lot of time to slack off (image credit: XKCD )&lt;/p&gt;
&lt;h2 id=&quot;energy-efficiency&quot;&gt;Energy efficiency&lt;/h2&gt;
&lt;p&gt;In their communications, Intel is always touting energy efficiency as a clear benefit of FPGAs. However, the situation is really not that clear cut, especially when it comes to floating point computations, but let us first consider situations where FPGAs are clearly more energy efficient than a CPU or GPU.&lt;/p&gt;
&lt;p&gt;Where FPGAs shine in terms of energy efficiency is at logic and fixed precision (as opposed to floating point) computations. In crypto-currency (such as bitcoin) mining, it is exactly this property that makes FPGAs advantageous. In fact, everyone used to mine bitcoin on FPGAs.&lt;/p&gt;
&lt;p&gt;By the way, nowadays everybody is using ASICs (Application Specific Integrated Circuit) for bitcoin mining. Which are special integrated circuits built for just one purpose. ASICs are an even more energy efficient solution but require a very large upfront investment for the design and large number of chips produced to be cost effective. But back to FPGAs.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;541&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1oa05oiK6chWPsItd-QX_A-2eed82a9.-L9LKSpy_ZyCHeD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another benefit of FPGAs in terms of energy efficiency is that FPGA boards &lt;em&gt;do not require a host computer to run,&lt;/em&gt; since they have their own input/output — we can save energy and money on the host. This in contrast to GPUs, which communicate with a host system using PCIe or NVLink, and hence require a host to run. (An exception to the rule that GPUs require a host is the &lt;a href=&quot;https://developer.nvidia.com/embedded-computing&quot;&gt;NVidia Jetson&lt;/a&gt;, but this is not a high-end GPU.)&lt;/p&gt;
&lt;h2 id=&quot;energy-efficiency-for-floating-point--fpga-vs-gpu&quot;&gt;Energy efficiency for floating point — FPGA vs GPU&lt;/h2&gt;
&lt;p&gt;A lot of high performance computing use cases, such as deep learning, often depend on floating point arithmetic — something GPUs are very good at. In the past, FPGAs were pretty inefficient for floating point computations because a floating point unit had to be assembled from logic blocks, costing a lot of resources.&lt;/p&gt;
&lt;p&gt;Newer FPGAs such as the &lt;a href=&quot;https://www.altera.com/products/fpga/arria-series/arria-10/overview.html&quot;&gt;Arria 10&lt;/a&gt; and &lt;a href=&quot;https://www.altera.com/products/fpga/stratix-series/stratix-10/overview.html&quot;&gt;Stratix 10&lt;/a&gt; have &lt;em&gt;built-in&lt;/em&gt; floating point units on the FPGA fabric, making them much better at floating point computations. Does the addition of floating point units make FPGAs interesting for floating point computations in terms of energy efficiency? Are they more energy efficient than a GPU?&lt;/p&gt;
&lt;p&gt;Let’s compare a state-of-the-art GPU to a state-of-the-art FPGA. The fastest professional GPU that is available now is the &lt;a href=&quot;https://images.nvidia.com/content/technologies/volta/pdf/tesla-volta-v100-datasheet-letter-fnl-web.pdf&quot;&gt;Tesla V100&lt;/a&gt;, which has a theoretical maximum of 15 TFLOPS (Tera-floating-point-operations per second, a standard means of measuring floating point performance) and uses about 250 Watts of power. One of the best available FPGA boards now is the &lt;a href=&quot;http://www.nallatech.com/wp-content/uploads/Nallatech-520C-Product-Brief-V9.pdf&quot;&gt;Nallatech 520C&lt;/a&gt;, which uses the new &lt;a href=&quot;https://www.altera.com/products/fpga/stratix-series/stratix-10/overview.html#family-table&quot;&gt;Statix 10 Chip&lt;/a&gt; by Altera/Intel. This card has a theoretical maximum of 9.2 TFLOPS and uses about 225 Watts of power.&lt;/p&gt;
&lt;p&gt;If we compare these two devices on energy efficiency, the GPU appears to be more energy efficient, achieving 56 GFLOP/W (Giga-floating-point-operation per Watt, a standard means of measuring energy efficiency of float point performance) in theory, while the FPGA achieves only 40.9 GFLOP/W. So if you’re going to buy new floating point hardware right now, and you need a host computer, then it seems you’re better off with the GPU, at least in this crude comparison.&lt;/p&gt;
&lt;p&gt;However, the difference is small, and it is very possible that a new FPGA card, such as &lt;a href=&quot;https://www.bittware.com/fpga/intel/boards/s10vm4/&quot;&gt;this upcoming card&lt;/a&gt; based on the Stratix 10 FPGA, is more energy efficient than the Volta on floating point computations. Moreover, the above comparison is between apples and oranges in the sense that the Tesla V100 is produced at a12 nanometer process, whereas the Stratix 10 is produced at the older 14 nanometer process.&lt;/p&gt;
&lt;p&gt;While the comparison does show that if you want energy efficient floating point computations &lt;em&gt;now&lt;/em&gt; that it is better to stick with GPUs, it does &lt;em&gt;not&lt;/em&gt; show that GPUs are inherently more energy efficient for floating point computations. The battle for floating point energy efficiency is currently won by GPUs, but this may change in the near future.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;505&quot; height=&quot;304&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0jN3eROhFPE_g28k1lqg4Q-91b29b41.LKftcpnR_BtutB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Energy label for FPGAs: depends on the application (Image copyright: European Union)&lt;/p&gt;
&lt;p&gt;If the host is not required, then a comparison between a high end &lt;em&gt;GPU with a host&lt;/em&gt; and an high end &lt;em&gt;FPGA without a host&lt;/em&gt; is in order. If we use the same numbers as in the above comparison, then a GPU with a host and an FPGA without a host are exactly as energy efficient if the host takes 116.7 Watts (per GPU in the case of a multi-GPU setup). A modern host consumes somewhere in the 50–250 Watt range, making the FPGA much more competitive.&lt;/p&gt;
&lt;h2 id=&quot;overview-and-outlook&quot;&gt;Overview and outlook&lt;/h2&gt;
&lt;p&gt;In some areas, it is hard to get around FPGAs. In military applications, such as missile guidance systems, FPGAs are used for their low latency. In radio-astronomy applications, the specialized input/output of FPGAs is essential to process the huge amount of data. In crypto-currency mining the energy efficiency on fixed precision and logic operations of FPGAs can be advantageous.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BvBH7nToLZJ155CfsOey3Q-39d47064.B6W--pxz_N5nTc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Artist’s impression of the yet to be built SKA radio telescope (image credit: SKA Organisation/Swinburne Astronomy Productions)&lt;/p&gt;
&lt;p&gt;However, Intel did not spend $16.7 billion on Altera just for these somewhat niche-markets — they have bigger plans for it. The two markets they want to infiltrate are, as far as I can tell, high performance computing and cloud computing (i.e. use in amazon-like centers).&lt;/p&gt;
&lt;h3 id=&quot;fpgas-for-high-performance-computing&quot;&gt;FPGAs for High Performance Computing&lt;/h3&gt;
&lt;p&gt;Personally, I do not think FPGAs will make a big splash in the high performance computing market in the coming years. Even if they become slightly more energy efficient than GPUs, the development of software for FPGAs is still a lot more difficult than for GPUs. The HPC community is already used to GPUs — getting people to switch from GPUs to FPGAs requires larger benefits. In the longer run, i.e. more than 5 years, it might turn out that FPGAs do offer such large benefits, which is what Intel seems to be hoping.&lt;/p&gt;
&lt;h3 id=&quot;fpgas-for-cloud-providers&quot;&gt;FPGAs for Cloud providers&lt;/h3&gt;
&lt;p&gt;The other market is cloud providers. Intel envisions cloud servers to have an FPGA or to run on an CPU-FPGA hybrid. The idea is that certain parts of the computation can be offloaded to the FPGA and/or that FPGAs can be used to customize the network topology.&lt;/p&gt;
&lt;p&gt;Microsoft, no doubt in cooperation with Intel, &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2014/06/HC26.12.520-Recon-Fabric-Pulnam-Microsoft-Catapult.pdf&quot;&gt;has implemented using FPGAs in its datacenters&lt;/a&gt; and has a network of 100.000 FPGAs. Microsoft is touting big benefits in terms of performance of Bing search, which now is computed partially by FPGAs, and flexibility. Amazon is also offering FPGA nodes on its popular EC2 platform. Whether this trend continues remains to be seen.&lt;/p&gt;
&lt;h3 id=&quot;outlook&quot;&gt;Outlook&lt;/h3&gt;
&lt;p&gt;So are these previously esoteric FPGAs about to go mainstream? Personally, I’m skeptical. I think that for FPGAs to really take off two things are needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;==They should be much easier to== ==&lt;strong&gt;program&lt;/strong&gt;====,== especially by bringing down compile times.&lt;/li&gt;
&lt;li&gt;They should be more &lt;strong&gt;energy efficient&lt;/strong&gt; on floating point computations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Intel is working hard on these issues, but these are very large hurdles to take.&lt;/p&gt;
&lt;p&gt;Do you have comments or more information? Leave a note in the comments!&lt;/p&gt;
&lt;p&gt;Want to know more? A lot of information can be found here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nextplatform.com/tag/fpga/&quot;&gt;https://www.nextplatform.com/tag/fpga/&lt;/a&gt;&lt;/p&gt;</description><pubDate>Tue, 14 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-disadvantages-of-field-programmable-gate-arrays&quot;&gt;The (dis)advantages of Field Programmable Gate Arrays&lt;/h2&gt;
&lt;p&gt;Recently, &lt;a href=&quot;https://newsroom.intel.com/news-releases/intel-completes-acquisition-of-altera/&quot;&gt;Intel bought Altera&lt;/a&gt;, one of the largest producers of FPGAs. Intel paid a whopping $16.7 billion, making it their largest acquisition ever. In other news, &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2014/06/HC26.12.520-Recon-Fabric-Pulnam-Microsoft-Catapult.pdf&quot;&gt;Microsoft is using FPGAs in its data centers&lt;/a&gt;, and &lt;a href=&quot;https://aws.amazon.com/ec2/instance-types/f1/&quot;&gt;Amazon is offering&lt;/a&gt; them on their cloud services. Previously, these FPGAs were mainly used in &lt;em&gt;electronics&lt;/em&gt; engineering, but not so much in &lt;em&gt;software&lt;/em&gt; engineering. Are FPGAs about to take off and become serious alternatives to CPUs and GPUs?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;251&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_c54zfRSRF7i6MOSy04Pa6Q-521e8422.B0f-ikNG_ZJMljT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-an-fpga&quot;&gt;What is an FPGA?&lt;/h2&gt;
&lt;p&gt;If you want to compute something, the common approach is to write some software for an instruction based architecture, such as a CPU or GPU. Another, more arduous, route one could take is to design a special circuit for this specific computation — as opposed to writing instructions for a general purpose circuit such as a CPU or GPU.&lt;/p&gt;
&lt;p&gt;Once you have designed this circuit, you need some way to implement the design so that you can actually compute something. One way, which requires quite deep pockets, is to actually produce a circuit that implements this design (this is called an Application Specific Integrated Circuit or ASIC).&lt;/p&gt;
&lt;p&gt;An easier way, and the main topic of this blog, is to implement your circuit design is to use a &lt;em&gt;Field Programmable Gate Array&lt;/em&gt; (FPGA), a &lt;em&gt;reconfigurable integrated circuit&lt;/em&gt;. You can configure the FPGA to become any circuit you want to (as long as it fits on the FPGA). This is quite a bit different than the &lt;em&gt;instruction-based hardware&lt;/em&gt; most programmers are used to, such as CPUs and GPUs. Instruction-based hardware is configured via &lt;em&gt;software&lt;/em&gt;, whereas FPGAs are instead configured by specifying a &lt;em&gt;hardware&lt;/em&gt; circuit.&lt;/p&gt;
&lt;h2 id=&quot;disadvantages-of-fpgas&quot;&gt;(Dis)Advantages of FPGAs&lt;/h2&gt;
&lt;p&gt;Why would you prefer to use an FPGA for your computation over the more common CPU or GPU? The differences with GPUs and CPUs are in the following areas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latency&lt;/strong&gt;: How long does it take to compute something?&lt;br&gt;
→ FPGAs are good at this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connectivity&lt;/strong&gt;: What input/output can we connect and with which bandwidth?&lt;br&gt;
→ FPGAs can directly be connected to inputs and can offer very high bandwith.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Engineering cost&lt;/strong&gt;: How much effort does it cost to express the computation?&lt;br&gt;
→ The engineering cost is typically much higher than for instruction based architectures, so the advantages must really be worth it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Energy efficiency&lt;/strong&gt;: How much energy does it cost to compute something?&lt;br&gt;
→ This is often listed as a large benefit of FPGAs, but whether FPGAs are better than CPUs or GPUs really depends on the application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s discuss each of these in more detail.&lt;/p&gt;
&lt;h2 id=&quot;low-latency&quot;&gt;Low latency&lt;/h2&gt;
&lt;p&gt;Low latency is what you need if you are programming the autopilot of a jet fighter or a high-frequency algorithmic trading engine: the time between an input and its response as short as possible. This is where FPGAs are much better than CPUs (or GPUs, which have to communicate via the CPU).&lt;/p&gt;
&lt;p&gt;With an FPGA it is feasible to get a latency around or below 1 microsecond, whereas with a CPU a latency smaller than 50 microseconds is already very good. Moreover, the latency of an FPGA is much more deterministic. One of the main reasons for this low latency is that FPGAs can be much more specialized: they do not depend on the generic operating system, and communication does not have to go via generic buses (such as USB or PCIe).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_rIAJPMywpoe5q_RDLpV1uw-c989ae8b.Bk8eJQzJ_Z2sWVYc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A couple of FPGAs in mid-air (probably)&lt;/p&gt;
&lt;h2 id=&quot;connectivity&quot;&gt;Connectivity&lt;/h2&gt;
&lt;p&gt;On an FPGA, you can hook up any data source, such as a network interface or sensor, directly to the &lt;em&gt;pins of the chip&lt;/em&gt;. This in sharp contrast to GPUs and CPUs, where you have to connect your source via the standardized buses (such as USB or PCIe) — and depend on the operating system to deliver the data to your application. A direct connection to the pins of the chip gives very high bandwidth (as well as low latency).&lt;/p&gt;
&lt;p&gt;This high bandwidth is needed, for example, in radio-astronomy applications, such as &lt;a href=&quot;http://www.lofar.org/about-lofar/about-lofar&quot;&gt;LOFAR&lt;/a&gt; and &lt;a href=&quot;https://www.skatelescope.org/&quot;&gt;SKA&lt;/a&gt;. In these applications there are a lot of specialized sensors in the field, which generate an enormous amount of data. The volume of data needs to be reduced before being sent off, to make it more manageable. For this purpose, the Netherlands Institute for Radio Astronomy, &lt;a href=&quot;https://www.astron.nl/&quot;&gt;ASTRON&lt;/a&gt;, designed the &lt;a href=&quot;https://www.astron.nl/r-d-laboratory/uniboard/uniboard-i-and-ii&quot;&gt;&lt;em&gt;Uniboard²&lt;/em&gt;&lt;/a&gt;, a board with four FPGAs which can handle more data per second than the Amsterdam internet exchange.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;447&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bomy9uvjcoI5F8rALbwUFg-540a7a92.Dv4t6kiQ_JAeKH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;These small radio astronomy antennas generate a lot of data (image credit: Svenlafe at en.wikipedia )&lt;/p&gt;
&lt;h2 id=&quot;engineering-cost&quot;&gt;Engineering cost&lt;/h2&gt;
&lt;p&gt;Before turning to the subtle issue of energy efficiency, let’s discuss the main disadvantage of FPGAs: they are really &lt;em&gt;much&lt;/em&gt; harder to program/configure than instruction based architectures (i.e. CPUs and GPUs). Traditionally, these hardware circuits are described via &lt;em&gt;Hardware Description Languages&lt;/em&gt; (HDL), such as VHDL and Verilog, whereas software is programmed via one of a plethora of programming languages, such as Java, C and Python.&lt;/p&gt;
&lt;p&gt;From a theoretical perspective, both hardware description languages and programming languages can be use to express any computation (both are Turing complete), but the difference in engineering details is vast.&lt;/p&gt;
&lt;p&gt;An upcoming trend is High Level Synthesis (HLS): programming FPGAs using regular programming languages such as OpenCL or C++, allowing for a much higher level of abstraction. However, even when using such languages, programming FPGAs is still an order of magnitude more difficult than programming instruction based systems.&lt;/p&gt;
&lt;p&gt;==A large part of the difficulty of programming FPGAs are the== ==&lt;strong&gt;long&lt;/strong&gt;== ==compilation times. For example, when using Intel’s OpenCL compiler, it takes somewhere between 4 and 12== ==&lt;em&gt;hours&lt;/em&gt;== ==to compile a typical program for the FPGA. This is due to the== ==&lt;em&gt;place-and-route phase&lt;/em&gt;====: the custom circuit that we== ==&lt;em&gt;want&lt;/em&gt;== ==needs to be mapped to the FPGA resources that we== ==&lt;em&gt;have&lt;/em&gt;====, with paths as short as possible. This is a complex optimization problem which requires significant computation. Intel does offer an emulator, so testing for correctness does not require this long step, but determining and optimizing performance does require these overnight compile phases.==&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;413&quot; height=&quot;360&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_J-1MC3QGbIuwq4tb-yr-iA-c56003e3.DjPvFJEe_gOSCM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Programming FPGAs gives you a lot of time to slack off (image credit: XKCD )&lt;/p&gt;
&lt;h2 id=&quot;energy-efficiency&quot;&gt;Energy efficiency&lt;/h2&gt;
&lt;p&gt;In their communications, Intel is always touting energy efficiency as a clear benefit of FPGAs. However, the situation is really not that clear cut, especially when it comes to floating point computations, but let us first consider situations where FPGAs are clearly more energy efficient than a CPU or GPU.&lt;/p&gt;
&lt;p&gt;Where FPGAs shine in terms of energy efficiency is at logic and fixed precision (as opposed to floating point) computations. In crypto-currency (such as bitcoin) mining, it is exactly this property that makes FPGAs advantageous. In fact, everyone used to mine bitcoin on FPGAs.&lt;/p&gt;
&lt;p&gt;By the way, nowadays everybody is using ASICs (Application Specific Integrated Circuit) for bitcoin mining. Which are special integrated circuits built for just one purpose. ASICs are an even more energy efficient solution but require a very large upfront investment for the design and large number of chips produced to be cost effective. But back to FPGAs.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;541&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1oa05oiK6chWPsItd-QX_A-2eed82a9.-L9LKSpy_ZyCHeD.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Another benefit of FPGAs in terms of energy efficiency is that FPGA boards &lt;em&gt;do not require a host computer to run,&lt;/em&gt; since they have their own input/output — we can save energy and money on the host. This in contrast to GPUs, which communicate with a host system using PCIe or NVLink, and hence require a host to run. (An exception to the rule that GPUs require a host is the &lt;a href=&quot;https://developer.nvidia.com/embedded-computing&quot;&gt;NVidia Jetson&lt;/a&gt;, but this is not a high-end GPU.)&lt;/p&gt;
&lt;h2 id=&quot;energy-efficiency-for-floating-point--fpga-vs-gpu&quot;&gt;Energy efficiency for floating point — FPGA vs GPU&lt;/h2&gt;
&lt;p&gt;A lot of high performance computing use cases, such as deep learning, often depend on floating point arithmetic — something GPUs are very good at. In the past, FPGAs were pretty inefficient for floating point computations because a floating point unit had to be assembled from logic blocks, costing a lot of resources.&lt;/p&gt;
&lt;p&gt;Newer FPGAs such as the &lt;a href=&quot;https://www.altera.com/products/fpga/arria-series/arria-10/overview.html&quot;&gt;Arria 10&lt;/a&gt; and &lt;a href=&quot;https://www.altera.com/products/fpga/stratix-series/stratix-10/overview.html&quot;&gt;Stratix 10&lt;/a&gt; have &lt;em&gt;built-in&lt;/em&gt; floating point units on the FPGA fabric, making them much better at floating point computations. Does the addition of floating point units make FPGAs interesting for floating point computations in terms of energy efficiency? Are they more energy efficient than a GPU?&lt;/p&gt;
&lt;p&gt;Let’s compare a state-of-the-art GPU to a state-of-the-art FPGA. The fastest professional GPU that is available now is the &lt;a href=&quot;https://images.nvidia.com/content/technologies/volta/pdf/tesla-volta-v100-datasheet-letter-fnl-web.pdf&quot;&gt;Tesla V100&lt;/a&gt;, which has a theoretical maximum of 15 TFLOPS (Tera-floating-point-operations per second, a standard means of measuring floating point performance) and uses about 250 Watts of power. One of the best available FPGA boards now is the &lt;a href=&quot;http://www.nallatech.com/wp-content/uploads/Nallatech-520C-Product-Brief-V9.pdf&quot;&gt;Nallatech 520C&lt;/a&gt;, which uses the new &lt;a href=&quot;https://www.altera.com/products/fpga/stratix-series/stratix-10/overview.html#family-table&quot;&gt;Statix 10 Chip&lt;/a&gt; by Altera/Intel. This card has a theoretical maximum of 9.2 TFLOPS and uses about 225 Watts of power.&lt;/p&gt;
&lt;p&gt;If we compare these two devices on energy efficiency, the GPU appears to be more energy efficient, achieving 56 GFLOP/W (Giga-floating-point-operation per Watt, a standard means of measuring energy efficiency of float point performance) in theory, while the FPGA achieves only 40.9 GFLOP/W. So if you’re going to buy new floating point hardware right now, and you need a host computer, then it seems you’re better off with the GPU, at least in this crude comparison.&lt;/p&gt;
&lt;p&gt;However, the difference is small, and it is very possible that a new FPGA card, such as &lt;a href=&quot;https://www.bittware.com/fpga/intel/boards/s10vm4/&quot;&gt;this upcoming card&lt;/a&gt; based on the Stratix 10 FPGA, is more energy efficient than the Volta on floating point computations. Moreover, the above comparison is between apples and oranges in the sense that the Tesla V100 is produced at a12 nanometer process, whereas the Stratix 10 is produced at the older 14 nanometer process.&lt;/p&gt;
&lt;p&gt;While the comparison does show that if you want energy efficient floating point computations &lt;em&gt;now&lt;/em&gt; that it is better to stick with GPUs, it does &lt;em&gt;not&lt;/em&gt; show that GPUs are inherently more energy efficient for floating point computations. The battle for floating point energy efficiency is currently won by GPUs, but this may change in the near future.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;505&quot; height=&quot;304&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0jN3eROhFPE_g28k1lqg4Q-91b29b41.LKftcpnR_BtutB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Energy label for FPGAs: depends on the application (Image copyright: European Union)&lt;/p&gt;
&lt;p&gt;If the host is not required, then a comparison between a high end &lt;em&gt;GPU with a host&lt;/em&gt; and an high end &lt;em&gt;FPGA without a host&lt;/em&gt; is in order. If we use the same numbers as in the above comparison, then a GPU with a host and an FPGA without a host are exactly as energy efficient if the host takes 116.7 Watts (per GPU in the case of a multi-GPU setup). A modern host consumes somewhere in the 50–250 Watt range, making the FPGA much more competitive.&lt;/p&gt;
&lt;h2 id=&quot;overview-and-outlook&quot;&gt;Overview and outlook&lt;/h2&gt;
&lt;p&gt;In some areas, it is hard to get around FPGAs. In military applications, such as missile guidance systems, FPGAs are used for their low latency. In radio-astronomy applications, the specialized input/output of FPGAs is essential to process the huge amount of data. In crypto-currency mining the energy efficiency on fixed precision and logic operations of FPGAs can be advantageous.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;700&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BvBH7nToLZJ155CfsOey3Q-39d47064.B6W--pxz_N5nTc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Artist’s impression of the yet to be built SKA radio telescope (image credit: SKA Organisation/Swinburne Astronomy Productions)&lt;/p&gt;
&lt;p&gt;However, Intel did not spend $16.7 billion on Altera just for these somewhat niche-markets — they have bigger plans for it. The two markets they want to infiltrate are, as far as I can tell, high performance computing and cloud computing (i.e. use in amazon-like centers).&lt;/p&gt;
&lt;h3 id=&quot;fpgas-for-high-performance-computing&quot;&gt;FPGAs for High Performance Computing&lt;/h3&gt;
&lt;p&gt;Personally, I do not think FPGAs will make a big splash in the high performance computing market in the coming years. Even if they become slightly more energy efficient than GPUs, the development of software for FPGAs is still a lot more difficult than for GPUs. The HPC community is already used to GPUs — getting people to switch from GPUs to FPGAs requires larger benefits. In the longer run, i.e. more than 5 years, it might turn out that FPGAs do offer such large benefits, which is what Intel seems to be hoping.&lt;/p&gt;
&lt;h3 id=&quot;fpgas-for-cloud-providers&quot;&gt;FPGAs for Cloud providers&lt;/h3&gt;
&lt;p&gt;The other market is cloud providers. Intel envisions cloud servers to have an FPGA or to run on an CPU-FPGA hybrid. The idea is that certain parts of the computation can be offloaded to the FPGA and/or that FPGAs can be used to customize the network topology.&lt;/p&gt;
&lt;p&gt;Microsoft, no doubt in cooperation with Intel, &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2014/06/HC26.12.520-Recon-Fabric-Pulnam-Microsoft-Catapult.pdf&quot;&gt;has implemented using FPGAs in its datacenters&lt;/a&gt; and has a network of 100.000 FPGAs. Microsoft is touting big benefits in terms of performance of Bing search, which now is computed partially by FPGAs, and flexibility. Amazon is also offering FPGA nodes on its popular EC2 platform. Whether this trend continues remains to be seen.&lt;/p&gt;
&lt;h3 id=&quot;outlook&quot;&gt;Outlook&lt;/h3&gt;
&lt;p&gt;So are these previously esoteric FPGAs about to go mainstream? Personally, I’m skeptical. I think that for FPGAs to really take off two things are needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;==They should be much easier to== ==&lt;strong&gt;program&lt;/strong&gt;====,== especially by bringing down compile times.&lt;/li&gt;
&lt;li&gt;They should be more &lt;strong&gt;energy efficient&lt;/strong&gt; on floating point computations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Intel is working hard on these issues, but these are very large hurdles to take.&lt;/p&gt;
&lt;p&gt;Do you have comments or more information? Leave a note in the comments!&lt;/p&gt;
&lt;p&gt;Want to know more? A lot of information can be found here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nextplatform.com/tag/fpga/&quot;&gt;https://www.nextplatform.com/tag/fpga/&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_c54zfRSRF7i6MOSy04Pa6Q-521e8422.B0f-ikNG.jpeg" medium="image"/><author>Atze van der Ploeg</author></item><item><title>floating (point) butterfly effect</title><link>https://blog2.esciencecenter.nl/posts/2018-08-06---floating-point-butterfly-effect</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-08-06---floating-point-butterfly-effect</guid><description>&lt;h2 id=&quot;searching-for-tiny-bugs-that-cause-big-problems&quot;&gt;Searching for tiny bugs that cause big problems&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4592&quot; height=&quot;3056&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Qoq1_5fKSaZA65JyVWjfmg-1f26fc50.DfHTa5wQ_DKvB5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I know it’s a bug, but it’s so pretty… what harm could it do?&lt;/p&gt;
&lt;p&gt;Last year, I took a few weeks to look into floating point round-off errors in &lt;a href=&quot;http://roofit.sourceforge.net/&quot;&gt;RooFit&lt;/a&gt;, the particle physics model building and fitting code that’s used for many large experiments, like the Higgs boson searches at CERN’s LHC.&lt;/p&gt;
&lt;p&gt;My job was to make RooFit faster by parallelizing part of it, but without changing the outcome of calculations. However, I found that fitting a model to some data set (which is the basic purpose of the code) using my new method did not yield exactly the same result… uh-oh.&lt;/p&gt;
&lt;p&gt;Now, whenever I hear the &lt;em&gt;holy mantra of innocent round-off errors&lt;/em&gt;, I immediately jump up in my seat…&lt;/p&gt;
&lt;p&gt;I hope after reading this blog, you’ll feel the same way and help me to encourage people to chase after their butterflies. Below I shared some helpful tips for solving floating point precision issues. Be sure to add your tips and experiences in the comments!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9dKx8jvCN8reko75ydVE1w-f5f193c7.kV9w4pzq_1jqmkX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lorenz’s strange attractor, an icon of chaos theory and the butterfly effect. By Dschwen — Own work, CC BY 2.5&lt;/p&gt;
&lt;h2 id=&quot;round-and-round-and-round-it-goes-where-it-stops&quot;&gt;Round and round and round it goes, where it stops…&lt;/h2&gt;
&lt;p&gt;In numerical computing, it is quite common to encounter round-off errors due to floating point precision.&lt;/p&gt;
&lt;p&gt;A sum or difference of two innocent looking values like 1 and 2/3 (two-thirds) may take the first-time programmer by surprise. For instance, Python will tell you that &lt;code&gt;1 + 2/3&lt;/code&gt; equals &lt;code&gt;1.666666666666666***5***&lt;/code&gt;. To any student of basic math, a &lt;em&gt;seven&lt;/em&gt; at the end would have made sense, but a &lt;em&gt;five&lt;/em&gt; is just crazy talk.&lt;/p&gt;
&lt;p&gt;Cue the lesson about floating point numbers, and the student can sleep well again, knowing the world still makes approximate sense.&lt;/p&gt;
&lt;p&gt;For most computational scientists, pretty soon these errors will become a fact of life: no further thought is given when one encounters such errors. An anthropologist studying the tribe of computational scientists would certainly identify the phrase &lt;em&gt;“yeah, there’s always some inevitable round-off errors”&lt;/em&gt; as one of the community’s central chants in its prayers to its digital deity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Yeah, there’s always some inevitable round-off errors…&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my own experience, but also from talking to many people over the years, the floating point round-off is discarded as an integral part of doing numerical science, for instance when doing large simulations or data analysis.&lt;/p&gt;
&lt;p&gt;While this is a useful day-to-day reflex, it pays off to take a deeper look at your calculations and try to find out exactly why you did not get the result you expected.&lt;/p&gt;
&lt;p&gt;Better yet, try to find out whether you can get the result you were looking for after all and, if relevant, how much performance this will cost you versus how much you will gain by this. Even after years of experience (or perhaps especially then), going back to basics in this way can help you gain some new perspectives, as it did for me.&lt;/p&gt;
&lt;p&gt;Most of the time, these errors are not really an issue, but sometimes they can be, as they turned out to be in RooFit.&lt;/p&gt;
&lt;h2 id=&quot;a-swarm-of-butterflies-parallelizing-roofit&quot;&gt;A swarm of butterflies: parallelizing RooFit&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_w6-Be9A0zcDpN4VLb4OftQ-bf6f2222.DyiS1WLV_2agpsu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;They can leave quite a mess.&lt;/p&gt;
&lt;p&gt;Parallelization is a common source of round-off errors, but in fact, my errors happened before the actual parallelization. What’s more, the results weren’t off by a few bits like the &lt;code&gt;1 + 2/3&lt;/code&gt; example above. They were sometimes off by as much as the 5th significant digit, like in &lt;code&gt;1.000**0**&lt;/code&gt; versus &lt;code&gt;1.000**1**&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This certainly cannot be explained by floating point round-off alone. Seeing as the point of RooFit is to robustly determine whether billions of €/$/CHF and many thousands of hours were spent sensibly, one might imagine the anxiety that such errors could produce in its stakeholders: the particle physicists, their funders, the world and myself.&lt;/p&gt;
&lt;p&gt;In the end, the error could be explained by a combination of factors, all originating from floating point precision errors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initially tiny errors were, in fact, blown up to cause the larger errors we saw.&lt;/li&gt;
&lt;li&gt;Due to the sensitivity of the fitting algorithm, a bit-size difference in input will change the direction of the search for the model’s optimal parameters.&lt;/li&gt;
&lt;li&gt;After several search steps, a few bit-size differences and ensuing differing search directions will have made a big difference in the outcome.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;dealing-with-chaos&quot;&gt;Dealing with chaos&lt;/h3&gt;
&lt;p&gt;RooFit does “compensate” for this search strategy by demanding a certain precision in the search outcome. By default, this precision comes down to precision up to the 5th significant digit, so that explains why the differences in outcome were never larger than that.&lt;/p&gt;
&lt;p&gt;Still, this kind of “imprecision” is a long way from ==the differences of order== ==&lt;code&gt;10^-17&lt;/code&gt;== ==numerical scientists are well used to==, so it stands out immediately when you’re trying to reproduce earlier experiments.&lt;/p&gt;
&lt;p&gt;In fact, this was not the only effect we saw.&lt;/p&gt;
&lt;p&gt;Some runs of the algorithm, using particularly pathological models, converged a lot slower or sometimes not at all, while they did converge before. The small differences in search direction can bring the algorithm into a problematic part of the parameter space.&lt;/p&gt;
&lt;p&gt;In most cases, RooFit (actually Minuit, the minimizer behind the scenes) can deal quite cleverly with such cases, but it usually does take some extra time.&lt;/p&gt;
&lt;h2 id=&quot;how-to-catch-butterflies&quot;&gt;How to catch butterflies&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;930&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__VfBrGlGdiR89ytOXj6Zcw-6af30ad5.BkSoZtns_1Rai1m.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Like a ninja&lt;/p&gt;
&lt;p&gt;Here are some things I encountered and will try to remember next time I find myself in such a situation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Print values in hexadecimal notation&lt;/strong&gt;. Floating point numbers are always rounded in some way. Why settle for anything less than the absolute bit-wise truth? ==For instance, in C++, use== ==&lt;code&gt;std::cout &amp;#x3C;&amp;#x3C; std::hexfloat &amp;#x3C;&amp;#x3C; your_float;&lt;/code&gt;====. Set it back to decimal afterwards using== ==&lt;code&gt;std::defaultfloat&lt;/code&gt;====.==&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace your problem to the source&lt;/strong&gt;. This may sound obvious, but it can be such a huge pain in the ass that I reckon this is in fact the reason why most people just accept floating point values (ok, it is the reason &lt;strong&gt;I&lt;/strong&gt; accept them). Surely, navigating through 20 layers of functions passing your value along is arduous. When arriving at the source, it can still be challenging to see exactly what is causing your error, especially when multiple arithmetic operations are involved. Some examples are:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trigonometric functions&lt;/strong&gt; like sines can give identical results for as much as three consecutive, bit-wise different floating point numbers, mainly around the maxima and minima. This means that these and the inverse relations such as the arcsine can in fact hide floating point errors! When you have become as paranoid for floating point errors as I have, and you notice that a bit-wise difference in input does &lt;strong&gt;not&lt;/strong&gt; cause the differences in outcome you were expecting, this can be even more vexing than your initial &lt;strong&gt;different&lt;/strong&gt; outcome. Or, in technical terms: what the crap?!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mapping of values to different ranges&lt;/strong&gt; using division, like often happens in coordinate transformations, can cause loss of least significant bits (thanks to &lt;a href=&quot;https://medium.com/@lourensveen&quot;&gt;@lourensveen&lt;/a&gt; for pointing this one out to me!). For instance, mapping to [0,1] can be useful in some cases. Note that this can also cause a nasty bug where your mapping operation results in values outside of your intended bounds, like &lt;code&gt;1.000000000000000001&lt;/code&gt;. Next time I encounter this bug, before I rip my hairs out, I’ll try to consider that even when I’m sure my maths check out, I need to make sure my computer agrees. Programming is a two-way conversation.&lt;/li&gt;
&lt;li&gt;When doing sums, &lt;strong&gt;make sure the order is fixed&lt;/strong&gt;. This is often an issue in parallel/asynchronous programming, where the order in which cores finish their calculations depends on external factors like your incoming email, whether or not you’re replying to an email, the downloading of embedded images in your emails and many other possible concurrent processes your OS is trying to schedule simultaneously.&lt;/li&gt;
&lt;li&gt;Also, for sums, it’s possible to use higher precision algorithms. &lt;strong&gt;Kahan summation&lt;/strong&gt;, for instance, has an error bound on the order of floating point precision errors. This is typically a lot more precise than naive summation, although it does cost 4 operations instead of one. More precision usually comes at a cost to performance.&lt;/li&gt;
&lt;li&gt;One of the easiest things you can do is just upgrade your algorithm to &lt;strong&gt;use a higher precision floating point type&lt;/strong&gt; for the precision-crucial parts of your calculations, like &lt;code&gt;double&lt;/code&gt; instead of &lt;code&gt;float&lt;/code&gt; in C++.&lt;/li&gt;
&lt;li&gt;… though even this seemingly simple trick can lead to problems! For instance, most modern processors have a so-called extended precision floating point precision mode where floats are internally represented by &lt;strong&gt;80 instead of 64 bits&lt;/strong&gt;. The extra bits are used to “fix” precision errors for you. If you were expecting errors one way, but now aren’t getting them… again, confusion ensues.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do you have related stories involving precision errors? Or do you have some great tactics for avoiding them? Share in the comments! &lt;em&gt;(Edit Aug 8: or join the discussion&lt;/em&gt; &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/959vc2/floating_point_butterfly_effect_searching_for/&quot;&gt;&lt;em&gt;on Reddit&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit 30 Aug:&lt;/em&gt; a great suggestion by is to check out the paper “What Every Computer Scientist Should Know About Floating Point Arithmetic”, originally from 1991 by David Goldberg (&lt;a href=&quot;https://cr.yp.to/2005-590/goldberg.pdf&quot;&gt;here an edited reprint&lt;/a&gt;). Seems like a really great reference on almost anything floating point!&lt;/p&gt;</description><pubDate>Mon, 06 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;searching-for-tiny-bugs-that-cause-big-problems&quot;&gt;Searching for tiny bugs that cause big problems&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4592&quot; height=&quot;3056&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Qoq1_5fKSaZA65JyVWjfmg-1f26fc50.DfHTa5wQ_DKvB5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I know it’s a bug, but it’s so pretty… what harm could it do?&lt;/p&gt;
&lt;p&gt;Last year, I took a few weeks to look into floating point round-off errors in &lt;a href=&quot;http://roofit.sourceforge.net/&quot;&gt;RooFit&lt;/a&gt;, the particle physics model building and fitting code that’s used for many large experiments, like the Higgs boson searches at CERN’s LHC.&lt;/p&gt;
&lt;p&gt;My job was to make RooFit faster by parallelizing part of it, but without changing the outcome of calculations. However, I found that fitting a model to some data set (which is the basic purpose of the code) using my new method did not yield exactly the same result… uh-oh.&lt;/p&gt;
&lt;p&gt;Now, whenever I hear the &lt;em&gt;holy mantra of innocent round-off errors&lt;/em&gt;, I immediately jump up in my seat…&lt;/p&gt;
&lt;p&gt;I hope after reading this blog, you’ll feel the same way and help me to encourage people to chase after their butterflies. Below I shared some helpful tips for solving floating point precision issues. Be sure to add your tips and experiences in the comments!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1024&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9dKx8jvCN8reko75ydVE1w-f5f193c7.kV9w4pzq_1jqmkX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lorenz’s strange attractor, an icon of chaos theory and the butterfly effect. By Dschwen — Own work, CC BY 2.5&lt;/p&gt;
&lt;h2 id=&quot;round-and-round-and-round-it-goes-where-it-stops&quot;&gt;Round and round and round it goes, where it stops…&lt;/h2&gt;
&lt;p&gt;In numerical computing, it is quite common to encounter round-off errors due to floating point precision.&lt;/p&gt;
&lt;p&gt;A sum or difference of two innocent looking values like 1 and 2/3 (two-thirds) may take the first-time programmer by surprise. For instance, Python will tell you that &lt;code&gt;1 + 2/3&lt;/code&gt; equals &lt;code&gt;1.666666666666666***5***&lt;/code&gt;. To any student of basic math, a &lt;em&gt;seven&lt;/em&gt; at the end would have made sense, but a &lt;em&gt;five&lt;/em&gt; is just crazy talk.&lt;/p&gt;
&lt;p&gt;Cue the lesson about floating point numbers, and the student can sleep well again, knowing the world still makes approximate sense.&lt;/p&gt;
&lt;p&gt;For most computational scientists, pretty soon these errors will become a fact of life: no further thought is given when one encounters such errors. An anthropologist studying the tribe of computational scientists would certainly identify the phrase &lt;em&gt;“yeah, there’s always some inevitable round-off errors”&lt;/em&gt; as one of the community’s central chants in its prayers to its digital deity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Yeah, there’s always some inevitable round-off errors…&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my own experience, but also from talking to many people over the years, the floating point round-off is discarded as an integral part of doing numerical science, for instance when doing large simulations or data analysis.&lt;/p&gt;
&lt;p&gt;While this is a useful day-to-day reflex, it pays off to take a deeper look at your calculations and try to find out exactly why you did not get the result you expected.&lt;/p&gt;
&lt;p&gt;Better yet, try to find out whether you can get the result you were looking for after all and, if relevant, how much performance this will cost you versus how much you will gain by this. Even after years of experience (or perhaps especially then), going back to basics in this way can help you gain some new perspectives, as it did for me.&lt;/p&gt;
&lt;p&gt;Most of the time, these errors are not really an issue, but sometimes they can be, as they turned out to be in RooFit.&lt;/p&gt;
&lt;h2 id=&quot;a-swarm-of-butterflies-parallelizing-roofit&quot;&gt;A swarm of butterflies: parallelizing RooFit&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_w6-Be9A0zcDpN4VLb4OftQ-bf6f2222.DyiS1WLV_2agpsu.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;They can leave quite a mess.&lt;/p&gt;
&lt;p&gt;Parallelization is a common source of round-off errors, but in fact, my errors happened before the actual parallelization. What’s more, the results weren’t off by a few bits like the &lt;code&gt;1 + 2/3&lt;/code&gt; example above. They were sometimes off by as much as the 5th significant digit, like in &lt;code&gt;1.000**0**&lt;/code&gt; versus &lt;code&gt;1.000**1**&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This certainly cannot be explained by floating point round-off alone. Seeing as the point of RooFit is to robustly determine whether billions of €/$/CHF and many thousands of hours were spent sensibly, one might imagine the anxiety that such errors could produce in its stakeholders: the particle physicists, their funders, the world and myself.&lt;/p&gt;
&lt;p&gt;In the end, the error could be explained by a combination of factors, all originating from floating point precision errors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Initially tiny errors were, in fact, blown up to cause the larger errors we saw.&lt;/li&gt;
&lt;li&gt;Due to the sensitivity of the fitting algorithm, a bit-size difference in input will change the direction of the search for the model’s optimal parameters.&lt;/li&gt;
&lt;li&gt;After several search steps, a few bit-size differences and ensuing differing search directions will have made a big difference in the outcome.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;dealing-with-chaos&quot;&gt;Dealing with chaos&lt;/h3&gt;
&lt;p&gt;RooFit does “compensate” for this search strategy by demanding a certain precision in the search outcome. By default, this precision comes down to precision up to the 5th significant digit, so that explains why the differences in outcome were never larger than that.&lt;/p&gt;
&lt;p&gt;Still, this kind of “imprecision” is a long way from ==the differences of order== ==&lt;code&gt;10^-17&lt;/code&gt;== ==numerical scientists are well used to==, so it stands out immediately when you’re trying to reproduce earlier experiments.&lt;/p&gt;
&lt;p&gt;In fact, this was not the only effect we saw.&lt;/p&gt;
&lt;p&gt;Some runs of the algorithm, using particularly pathological models, converged a lot slower or sometimes not at all, while they did converge before. The small differences in search direction can bring the algorithm into a problematic part of the parameter space.&lt;/p&gt;
&lt;p&gt;In most cases, RooFit (actually Minuit, the minimizer behind the scenes) can deal quite cleverly with such cases, but it usually does take some extra time.&lt;/p&gt;
&lt;h2 id=&quot;how-to-catch-butterflies&quot;&gt;How to catch butterflies&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;930&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__VfBrGlGdiR89ytOXj6Zcw-6af30ad5.BkSoZtns_1Rai1m.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Like a ninja&lt;/p&gt;
&lt;p&gt;Here are some things I encountered and will try to remember next time I find myself in such a situation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Print values in hexadecimal notation&lt;/strong&gt;. Floating point numbers are always rounded in some way. Why settle for anything less than the absolute bit-wise truth? ==For instance, in C++, use== ==&lt;code&gt;std::cout &amp;#x3C;&amp;#x3C; std::hexfloat &amp;#x3C;&amp;#x3C; your_float;&lt;/code&gt;====. Set it back to decimal afterwards using== ==&lt;code&gt;std::defaultfloat&lt;/code&gt;====.==&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace your problem to the source&lt;/strong&gt;. This may sound obvious, but it can be such a huge pain in the ass that I reckon this is in fact the reason why most people just accept floating point values (ok, it is the reason &lt;strong&gt;I&lt;/strong&gt; accept them). Surely, navigating through 20 layers of functions passing your value along is arduous. When arriving at the source, it can still be challenging to see exactly what is causing your error, especially when multiple arithmetic operations are involved. Some examples are:&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trigonometric functions&lt;/strong&gt; like sines can give identical results for as much as three consecutive, bit-wise different floating point numbers, mainly around the maxima and minima. This means that these and the inverse relations such as the arcsine can in fact hide floating point errors! When you have become as paranoid for floating point errors as I have, and you notice that a bit-wise difference in input does &lt;strong&gt;not&lt;/strong&gt; cause the differences in outcome you were expecting, this can be even more vexing than your initial &lt;strong&gt;different&lt;/strong&gt; outcome. Or, in technical terms: what the crap?!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mapping of values to different ranges&lt;/strong&gt; using division, like often happens in coordinate transformations, can cause loss of least significant bits (thanks to &lt;a href=&quot;https://medium.com/@lourensveen&quot;&gt;@lourensveen&lt;/a&gt; for pointing this one out to me!). For instance, mapping to [0,1] can be useful in some cases. Note that this can also cause a nasty bug where your mapping operation results in values outside of your intended bounds, like &lt;code&gt;1.000000000000000001&lt;/code&gt;. Next time I encounter this bug, before I rip my hairs out, I’ll try to consider that even when I’m sure my maths check out, I need to make sure my computer agrees. Programming is a two-way conversation.&lt;/li&gt;
&lt;li&gt;When doing sums, &lt;strong&gt;make sure the order is fixed&lt;/strong&gt;. This is often an issue in parallel/asynchronous programming, where the order in which cores finish their calculations depends on external factors like your incoming email, whether or not you’re replying to an email, the downloading of embedded images in your emails and many other possible concurrent processes your OS is trying to schedule simultaneously.&lt;/li&gt;
&lt;li&gt;Also, for sums, it’s possible to use higher precision algorithms. &lt;strong&gt;Kahan summation&lt;/strong&gt;, for instance, has an error bound on the order of floating point precision errors. This is typically a lot more precise than naive summation, although it does cost 4 operations instead of one. More precision usually comes at a cost to performance.&lt;/li&gt;
&lt;li&gt;One of the easiest things you can do is just upgrade your algorithm to &lt;strong&gt;use a higher precision floating point type&lt;/strong&gt; for the precision-crucial parts of your calculations, like &lt;code&gt;double&lt;/code&gt; instead of &lt;code&gt;float&lt;/code&gt; in C++.&lt;/li&gt;
&lt;li&gt;… though even this seemingly simple trick can lead to problems! For instance, most modern processors have a so-called extended precision floating point precision mode where floats are internally represented by &lt;strong&gt;80 instead of 64 bits&lt;/strong&gt;. The extra bits are used to “fix” precision errors for you. If you were expecting errors one way, but now aren’t getting them… again, confusion ensues.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do you have related stories involving precision errors? Or do you have some great tactics for avoiding them? Share in the comments! &lt;em&gt;(Edit Aug 8: or join the discussion&lt;/em&gt; &lt;a href=&quot;https://www.reddit.com/r/cpp/comments/959vc2/floating_point_butterfly_effect_searching_for/&quot;&gt;&lt;em&gt;on Reddit&lt;/em&gt;&lt;/a&gt;&lt;em&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit 30 Aug:&lt;/em&gt; a great suggestion by is to check out the paper “What Every Computer Scientist Should Know About Floating Point Arithmetic”, originally from 1991 by David Goldberg (&lt;a href=&quot;https://cr.yp.to/2005-590/goldberg.pdf&quot;&gt;here an edited reprint&lt;/a&gt;). Seems like a really great reference on almost anything floating point!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_9dKx8jvCN8reko75ydVE1w-f5f193c7.kV9w4pzq.png" medium="image"/><author>Patrick Bos</author></item><item><title>jump start your python project with this template</title><link>https://blog2.esciencecenter.nl/posts/2018-08-01---jump-start-your-python-project-with-this-template</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-08-01---jump-start-your-python-project-with-this-template</guid><description>&lt;h2 id=&quot;spend-less-time-creating-high-quality-software&quot;&gt;Spend less time creating high quality software&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_haFkoDH9n76tojtq8MqHbQ-0fbfa97d.Bw32NEUx_Zg6XFp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Use our python template to build better software.&lt;/p&gt;
&lt;p&gt;At the Netherlands eScience Center, we believe that &lt;a href=&quot;https://www.software.ac.uk/resources/publications/better-software-better-research&quot;&gt;better software leads to better research&lt;/a&gt;. We wrote a &lt;a href=&quot;https://guide.esciencecenter.nl/&quot;&gt;guide&lt;/a&gt; to help you create high quality software. However, if you try to follow the guide, you quickly find out that it is a lot of work, and some of it is repetitive.&lt;/p&gt;
&lt;p&gt;So, we made the &lt;a href=&quot;https://www.research-software.nl/software/nlesc-python-template&quot;&gt;Netherlands eScience Center Python template&lt;/a&gt;, that automates part of the work for new Python packages. The Python template helps beginners to get started, and experienced developers to save time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spend less time setting up and configuring your new Python packages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Python template allows you to generate a basic project structure, so you can spend less time setting up and configuring your new Python packages, and automatically follow development best-practices right from the start. The ‘empty’ Python project contains a README with extensive documentation about the project setup, and provides further instructions on what to do.&lt;/p&gt;
&lt;h3 id=&quot;default-configurations&quot;&gt;Default configurations&lt;/h3&gt;
&lt;p&gt;When writing software, there is a lot to configure. The Python template comes with sensible default configurations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;setup.py&lt;/code&gt;, for installing the package, and specifying package metadata and dependencies,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setup.cfg&lt;/code&gt;, for defining additional installation commands, e.g., to run tests and to build the documentation,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.editorconfig&lt;/code&gt;, for making sure your editor or &lt;a href=&quot;https://en.wikipedia.org/wiki/Integrated_development_environment&quot;&gt;IDE&lt;/a&gt; plays nice with your python code,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.gitignore&lt;/code&gt;, for keeping unwanted files out of your &lt;a href=&quot;https://help.github.com/articles/about-repositories/&quot;&gt;git repository&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;boilerplate-testing-and-documentation&quot;&gt;Boilerplate testing and documentation&lt;/h3&gt;
&lt;p&gt;Software tests help you make sure your software does what it is supposed to do. Documentation tells users how to use your software. However, setting up tests and documentation can be a hassle. If you use the Python template, you can immediately start writing tests and documentation, so everything works as expected right from the start!&lt;/p&gt;
&lt;h3 id=&quot;code-style-checking&quot;&gt;Code style checking&lt;/h3&gt;
&lt;p&gt;Following code style conventions makes it easier for others (and yourself) to understand your code. The Python template is set up with a default &lt;a href=&quot;https://editorconfig.org/&quot;&gt;.editorconfig&lt;/a&gt; and &lt;a href=&quot;http://prospector.readthedocs.io/en/master/&quot;&gt;prospector&lt;/a&gt; to automatically check the code style.&lt;/p&gt;
&lt;h3 id=&quot;miscellaneous-files-included&quot;&gt;Miscellaneous files included&lt;/h3&gt;
&lt;p&gt;In addition to code and configuration, there are miscellaneous files that make life easier for you and your users by clarifying what you did and what you expect from others. The Python template contains a&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Software license, to specify how users can use the software,&lt;/li&gt;
&lt;li&gt;Change log, to keep your users up to date about changes to the code,&lt;/li&gt;
&lt;li&gt;Code of Conduct, to tell users and contributers how to behave professionally, and&lt;/li&gt;
&lt;li&gt;Contributing guidelines, to explain how others can help to develop the software,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;so you don’t have to remember adding them.&lt;/p&gt;
&lt;h3 id=&quot;freedom-to-choose&quot;&gt;Freedom to choose&lt;/h3&gt;
&lt;p&gt;Project requirements differ. While the Python template makes some choices for you, it also tries to give you as much freedom as possible. For example, the template does not force you to use a &lt;a href=&quot;https://wiki.python.org/moin/Python2orPython3&quot;&gt;specific Python version&lt;/a&gt;, but comes set up for both Python 2 and 3. The template also leaves you free to choose the package manager (i.e., &lt;a href=&quot;https://www.w3schools.com/python/python_pip.asp&quot;&gt;pip&lt;/a&gt; or &lt;a href=&quot;https://conda.io/docs/&quot;&gt;conda&lt;/a&gt;) that best suits your requirements.&lt;/p&gt;
&lt;h3 id=&quot;what-are-you-waiting-for&quot;&gt;What are you waiting for?&lt;/h3&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/NLeSC/python-template&quot;&gt;Netherlands eScience Center Python template&lt;/a&gt; and let us know what you think!&lt;/p&gt;</description><pubDate>Wed, 01 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;spend-less-time-creating-high-quality-software&quot;&gt;Spend less time creating high quality software&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;350&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_haFkoDH9n76tojtq8MqHbQ-0fbfa97d.Bw32NEUx_Zg6XFp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Use our python template to build better software.&lt;/p&gt;
&lt;p&gt;At the Netherlands eScience Center, we believe that &lt;a href=&quot;https://www.software.ac.uk/resources/publications/better-software-better-research&quot;&gt;better software leads to better research&lt;/a&gt;. We wrote a &lt;a href=&quot;https://guide.esciencecenter.nl/&quot;&gt;guide&lt;/a&gt; to help you create high quality software. However, if you try to follow the guide, you quickly find out that it is a lot of work, and some of it is repetitive.&lt;/p&gt;
&lt;p&gt;So, we made the &lt;a href=&quot;https://www.research-software.nl/software/nlesc-python-template&quot;&gt;Netherlands eScience Center Python template&lt;/a&gt;, that automates part of the work for new Python packages. The Python template helps beginners to get started, and experienced developers to save time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spend less time setting up and configuring your new Python packages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Python template allows you to generate a basic project structure, so you can spend less time setting up and configuring your new Python packages, and automatically follow development best-practices right from the start. The ‘empty’ Python project contains a README with extensive documentation about the project setup, and provides further instructions on what to do.&lt;/p&gt;
&lt;h3 id=&quot;default-configurations&quot;&gt;Default configurations&lt;/h3&gt;
&lt;p&gt;When writing software, there is a lot to configure. The Python template comes with sensible default configurations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;setup.py&lt;/code&gt;, for installing the package, and specifying package metadata and dependencies,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setup.cfg&lt;/code&gt;, for defining additional installation commands, e.g., to run tests and to build the documentation,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.editorconfig&lt;/code&gt;, for making sure your editor or &lt;a href=&quot;https://en.wikipedia.org/wiki/Integrated_development_environment&quot;&gt;IDE&lt;/a&gt; plays nice with your python code,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.gitignore&lt;/code&gt;, for keeping unwanted files out of your &lt;a href=&quot;https://help.github.com/articles/about-repositories/&quot;&gt;git repository&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;boilerplate-testing-and-documentation&quot;&gt;Boilerplate testing and documentation&lt;/h3&gt;
&lt;p&gt;Software tests help you make sure your software does what it is supposed to do. Documentation tells users how to use your software. However, setting up tests and documentation can be a hassle. If you use the Python template, you can immediately start writing tests and documentation, so everything works as expected right from the start!&lt;/p&gt;
&lt;h3 id=&quot;code-style-checking&quot;&gt;Code style checking&lt;/h3&gt;
&lt;p&gt;Following code style conventions makes it easier for others (and yourself) to understand your code. The Python template is set up with a default &lt;a href=&quot;https://editorconfig.org/&quot;&gt;.editorconfig&lt;/a&gt; and &lt;a href=&quot;http://prospector.readthedocs.io/en/master/&quot;&gt;prospector&lt;/a&gt; to automatically check the code style.&lt;/p&gt;
&lt;h3 id=&quot;miscellaneous-files-included&quot;&gt;Miscellaneous files included&lt;/h3&gt;
&lt;p&gt;In addition to code and configuration, there are miscellaneous files that make life easier for you and your users by clarifying what you did and what you expect from others. The Python template contains a&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Software license, to specify how users can use the software,&lt;/li&gt;
&lt;li&gt;Change log, to keep your users up to date about changes to the code,&lt;/li&gt;
&lt;li&gt;Code of Conduct, to tell users and contributers how to behave professionally, and&lt;/li&gt;
&lt;li&gt;Contributing guidelines, to explain how others can help to develop the software,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;so you don’t have to remember adding them.&lt;/p&gt;
&lt;h3 id=&quot;freedom-to-choose&quot;&gt;Freedom to choose&lt;/h3&gt;
&lt;p&gt;Project requirements differ. While the Python template makes some choices for you, it also tries to give you as much freedom as possible. For example, the template does not force you to use a &lt;a href=&quot;https://wiki.python.org/moin/Python2orPython3&quot;&gt;specific Python version&lt;/a&gt;, but comes set up for both Python 2 and 3. The template also leaves you free to choose the package manager (i.e., &lt;a href=&quot;https://www.w3schools.com/python/python_pip.asp&quot;&gt;pip&lt;/a&gt; or &lt;a href=&quot;https://conda.io/docs/&quot;&gt;conda&lt;/a&gt;) that best suits your requirements.&lt;/p&gt;
&lt;h3 id=&quot;what-are-you-waiting-for&quot;&gt;What are you waiting for?&lt;/h3&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/NLeSC/python-template&quot;&gt;Netherlands eScience Center Python template&lt;/a&gt; and let us know what you think!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_haFkoDH9n76tojtq8MqHbQ-0fbfa97d.Bw32NEUx.jpeg" medium="image"/><author>Janneke van der Zwaan</author></item><item><title>what we can learn from tomatoes — feeding the planet with improved plant breeding</title><link>https://blog2.esciencecenter.nl/posts/2018-07-12---what-we-can-learn-from-tomatoes-feeding-the-planet-with-improved-plant-breeding</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-07-12---what-we-can-learn-from-tomatoes-feeding-the-planet-with-improved-plant-breeding</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1401&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_b2IqWiEJSVrhQ1bQ2O2CyA-aee9d580.BOcWMS15_5yMlz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: PhD candidate Gurnoor Singh at Wageningen University and Research, Dr. Richard Finkers from the Wageningen Plant Research institute and Dr. Arnold Kuzniar from the Netherlands eScience Center&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon&lt;/em&gt; | &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just outside of the quiet town of Wageningen, surrounded by vast fields of grass and crops, the ultra-modern buildings and stark white greenhouses of Wageningen University and Research catch the eye. The institution is well known for its groundbreaking contributions in biological sciences across the country. And it is in one of the university’s hot houses filled with tomato, potato, and spring onion plants that a small, but diverse team of researchers are working on the future of plant breeding.&lt;/p&gt;
&lt;p&gt;Already in 2015, the Netherlands eScience Center granted funding to the collaboration project of Dr. Richard Finkers and Prof. Richard Visser, both employed at Wageningen University and Research. The ambitious research question they posed themselves: How can science help to ensure food and nutrient availability for our continuously growing world population? A potential answer lies in the genetic characteristics of the tomato, according to the &lt;a href=&quot;https://www.esciencecenter.nl/project/prediction-of-candidate-genes-for-traits-using-interoperable-genome-annotat&quot;&gt;&lt;em&gt;candYgene&lt;/em&gt; project&lt;/a&gt;. Within the domain of genetics research and plant breeding, it is widely known and accepted that certain characteristics of a plant genome can have a direct impact on qualities like heat tolerance, quality, or resistance to pest and diseases. Identifying candidate genes with favourable attributes for the breeding process would decrease time effort and represents a crucial advantage in creating more resilient crops and, consequently, secure future food supply.&lt;/p&gt;
&lt;h3 id=&quot;discovering-the-holy-grail-of-plant-breeding-together&quot;&gt;Discovering the “holy grail” of plant breeding together&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ii86CSSyimnkzxo6EvjNxQ-65225314.DyHlhY_q_Z1gNCOe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Richard: “In a project like candYgene, we focus on on combining current knowledge that is burried in data resources to breed the seeds of the future.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What is much less obvious, however, is which genes specifically influence such characteristics and to what extent this occurs in the so-called Quantitative Trait Loci (QTLs).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AJ7iLK9ek8btBhJu2KIHeA-dd0958d5.hKtoJyL-_Z1i6SpN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The combination possibilities of these QTLs are almost endless. Together with eSience engineer Dr. Arnold Kuzniar and PhD candidate Gurnoor Singh, the group set out to come up with a new method for plant breeding experts to tackle the common problem of an overwhelming amount of data. Especially growing scientific output in the field of genetics research poses a great challenge to scientists. The vast amount of crop species, where publication on other crops might contain the linking pin in biological understanding of a trait, can lead researchers of a specific crop to overlook this potentially important information. But their ability to analyse the available data is also limited by their human constraints like the necessity to sleep and have a work-life balance. And that is where technology can help to improve the research process.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5vG2h866mKfn4pE2Cru4jQ-3e31cd50.N2KphnGN_ZkkGQ4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Prof. Richard Visser, the main initiator of the project, formulates the idea behind the pairing up with the eScience Center this way: “We wanted to tap into the knowledge and expertise of eScientists. Having people dedicated to coming up with computer solutions is not trivial and this interaction takes the cooperation to a more professional level.”&lt;/p&gt;
&lt;p&gt;In a close collaboration effort, Arnold and Gurnoor managed to pair their expertise’s to come up with a solution to harness the already existing data about QTLs from tables included in numerous peer-reviewed articles. The results of the PhD candidate’s analysis of this information was combined with genome annotations in public databases by the eScience engineer with the help of &lt;a href=&quot;https://www.research-software.nl/software/qtl-tableminer&quot;&gt;QTL TableMiner++&lt;/a&gt;. This newly developed tool is the first pivotal achievement of the project and extracts QTL data from literature and makes it readable for a machine, enabling targeted search requests. “Dissecting the relationships between genes and traits is the holy grail of genetics research“, says Arnold, stating that especially the close collaboration with Gurnoor was “crucial”. Richard is very clear on how important the unique merging of eScience and domain expertise was for the project: “Gurnoor and Arnold have really done groundbreaking work in this project. There is no other team in the world that invested so much time in trying to link different data resources and then linking them to different candidate genes.”&lt;/p&gt;
&lt;h3 id=&quot;teamwork-is-a-slow-growing-seed&quot;&gt;Teamwork is a slow-growing seed&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iOR_DJwADi2E0dgGDP9k8g-30d3589e.B4sVzAj0_1OL8eT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Richard Finkers in one of the green houses of Wageningen University and Research&lt;/p&gt;
&lt;p&gt;This idea of paving new pathways in research and driving innovation forwards serves as one of the central motivations for Arnold. “Working with domain scientists to solve a biological problem using digital technologies is what drives me.” PhD candidate Gurnoor also sees clear benefits in terms of career by working in a multidisciplinary project:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“You can find your own individual path in sectors where many other people, for example, in plant breeding don’t know how to process big amounts of data or how bioinformatics works. So this experience will definitely help me to enter a new field.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1401&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XJ8knfpb5FaBmzbM-wpwww-53c793f4.CGgafsS4_pojNv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But before the team was able to arrive at this point in the &lt;em&gt;candYgene&lt;/em&gt; project, the unique components of this collaborative process posed a few hurdles that had to be overcome together. “It was a learning curve for everyone. The start is always challenging because people have a different vocabulary and expectations”, Arnold remembers, backed up by Richard: “It takes time to build a relationship and to work together effectively, that cannot happen in two weeks.“ In this way, the co-leader of the project expresses that it was decisive that Arnold is spending two days a week in the Wageningen office with the rest of the team.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_aYyo-_WaAohJiyje7qQySg-7520bc8b.DMhHnvSu_Z1tkosX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XHIyHYB4foeDlkatFSEoZQ-bc3300b4.BYT0x7hK_Z1Ll7qh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RQS_YfQm0_wU42_u01rkww-61fa4893.jVC44m3r_2pDHy9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uk0EpDjS7JvM-AKiJni18w-db629e25.CW9n1C-C_1icuKQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;growing-impact-beyond-state-lines-and-disciplines&quot;&gt;Growing impact beyond state lines and disciplines&lt;/h3&gt;
&lt;p&gt;After this demanding orientation phase, the group is now happy with what they have achieved so far. “The feedback from my international network has been very positive. A great number of researchers is interested in using the tool we developed and appreciate that we made the information that was hidden in literature“, Richard announces not without a sense of pride. Reactions as these show that it is still not a common practice to share research results within the domain, or even across disciplines. As someone who mostly works together with the industrial sector, the still underdeveloped field of open science represents one of the central in his opinion: “There should be more space in the funding landscape to enable and enforce the accessibility and availability of data. That is the only way to spark new innovations.“&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_s8wK88EcBrigIM47-WDlcw-81884216.Bg-2pfLJ_Z1IdCiS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</description><pubDate>Thu, 12 Jul 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1401&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_b2IqWiEJSVrhQ1bQ2O2CyA-aee9d580.BOcWMS15_5yMlz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: PhD candidate Gurnoor Singh at Wageningen University and Research, Dr. Richard Finkers from the Wageningen Plant Research institute and Dr. Arnold Kuzniar from the Netherlands eScience Center&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon&lt;/em&gt; | &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just outside of the quiet town of Wageningen, surrounded by vast fields of grass and crops, the ultra-modern buildings and stark white greenhouses of Wageningen University and Research catch the eye. The institution is well known for its groundbreaking contributions in biological sciences across the country. And it is in one of the university’s hot houses filled with tomato, potato, and spring onion plants that a small, but diverse team of researchers are working on the future of plant breeding.&lt;/p&gt;
&lt;p&gt;Already in 2015, the Netherlands eScience Center granted funding to the collaboration project of Dr. Richard Finkers and Prof. Richard Visser, both employed at Wageningen University and Research. The ambitious research question they posed themselves: How can science help to ensure food and nutrient availability for our continuously growing world population? A potential answer lies in the genetic characteristics of the tomato, according to the &lt;a href=&quot;https://www.esciencecenter.nl/project/prediction-of-candidate-genes-for-traits-using-interoperable-genome-annotat&quot;&gt;&lt;em&gt;candYgene&lt;/em&gt; project&lt;/a&gt;. Within the domain of genetics research and plant breeding, it is widely known and accepted that certain characteristics of a plant genome can have a direct impact on qualities like heat tolerance, quality, or resistance to pest and diseases. Identifying candidate genes with favourable attributes for the breeding process would decrease time effort and represents a crucial advantage in creating more resilient crops and, consequently, secure future food supply.&lt;/p&gt;
&lt;h3 id=&quot;discovering-the-holy-grail-of-plant-breeding-together&quot;&gt;Discovering the “holy grail” of plant breeding together&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ii86CSSyimnkzxo6EvjNxQ-65225314.DyHlhY_q_Z1gNCOe.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Richard: “In a project like candYgene, we focus on on combining current knowledge that is burried in data resources to breed the seeds of the future.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What is much less obvious, however, is which genes specifically influence such characteristics and to what extent this occurs in the so-called Quantitative Trait Loci (QTLs).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AJ7iLK9ek8btBhJu2KIHeA-dd0958d5.hKtoJyL-_Z1i6SpN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The combination possibilities of these QTLs are almost endless. Together with eSience engineer Dr. Arnold Kuzniar and PhD candidate Gurnoor Singh, the group set out to come up with a new method for plant breeding experts to tackle the common problem of an overwhelming amount of data. Especially growing scientific output in the field of genetics research poses a great challenge to scientists. The vast amount of crop species, where publication on other crops might contain the linking pin in biological understanding of a trait, can lead researchers of a specific crop to overlook this potentially important information. But their ability to analyse the available data is also limited by their human constraints like the necessity to sleep and have a work-life balance. And that is where technology can help to improve the research process.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5vG2h866mKfn4pE2Cru4jQ-3e31cd50.N2KphnGN_ZkkGQ4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Prof. Richard Visser, the main initiator of the project, formulates the idea behind the pairing up with the eScience Center this way: “We wanted to tap into the knowledge and expertise of eScientists. Having people dedicated to coming up with computer solutions is not trivial and this interaction takes the cooperation to a more professional level.”&lt;/p&gt;
&lt;p&gt;In a close collaboration effort, Arnold and Gurnoor managed to pair their expertise’s to come up with a solution to harness the already existing data about QTLs from tables included in numerous peer-reviewed articles. The results of the PhD candidate’s analysis of this information was combined with genome annotations in public databases by the eScience engineer with the help of &lt;a href=&quot;https://www.research-software.nl/software/qtl-tableminer&quot;&gt;QTL TableMiner++&lt;/a&gt;. This newly developed tool is the first pivotal achievement of the project and extracts QTL data from literature and makes it readable for a machine, enabling targeted search requests. “Dissecting the relationships between genes and traits is the holy grail of genetics research“, says Arnold, stating that especially the close collaboration with Gurnoor was “crucial”. Richard is very clear on how important the unique merging of eScience and domain expertise was for the project: “Gurnoor and Arnold have really done groundbreaking work in this project. There is no other team in the world that invested so much time in trying to link different data resources and then linking them to different candidate genes.”&lt;/p&gt;
&lt;h3 id=&quot;teamwork-is-a-slow-growing-seed&quot;&gt;Teamwork is a slow-growing seed&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iOR_DJwADi2E0dgGDP9k8g-30d3589e.B4sVzAj0_1OL8eT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Richard Finkers in one of the green houses of Wageningen University and Research&lt;/p&gt;
&lt;p&gt;This idea of paving new pathways in research and driving innovation forwards serves as one of the central motivations for Arnold. “Working with domain scientists to solve a biological problem using digital technologies is what drives me.” PhD candidate Gurnoor also sees clear benefits in terms of career by working in a multidisciplinary project:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“You can find your own individual path in sectors where many other people, for example, in plant breeding don’t know how to process big amounts of data or how bioinformatics works. So this experience will definitely help me to enter a new field.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1401&quot; height=&quot;934&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XJ8knfpb5FaBmzbM-wpwww-53c793f4.CGgafsS4_pojNv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;But before the team was able to arrive at this point in the &lt;em&gt;candYgene&lt;/em&gt; project, the unique components of this collaborative process posed a few hurdles that had to be overcome together. “It was a learning curve for everyone. The start is always challenging because people have a different vocabulary and expectations”, Arnold remembers, backed up by Richard: “It takes time to build a relationship and to work together effectively, that cannot happen in two weeks.“ In this way, the co-leader of the project expresses that it was decisive that Arnold is spending two days a week in the Wageningen office with the rest of the team.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_aYyo-_WaAohJiyje7qQySg-7520bc8b.DMhHnvSu_Z1tkosX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XHIyHYB4foeDlkatFSEoZQ-bc3300b4.BYT0x7hK_Z1Ll7qh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RQS_YfQm0_wU42_u01rkww-61fa4893.jVC44m3r_2pDHy9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1100&quot; height=&quot;733&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uk0EpDjS7JvM-AKiJni18w-db629e25.CW9n1C-C_1icuKQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;growing-impact-beyond-state-lines-and-disciplines&quot;&gt;Growing impact beyond state lines and disciplines&lt;/h3&gt;
&lt;p&gt;After this demanding orientation phase, the group is now happy with what they have achieved so far. “The feedback from my international network has been very positive. A great number of researchers is interested in using the tool we developed and appreciate that we made the information that was hidden in literature“, Richard announces not without a sense of pride. Reactions as these show that it is still not a common practice to share research results within the domain, or even across disciplines. As someone who mostly works together with the industrial sector, the still underdeveloped field of open science represents one of the central in his opinion: “There should be more space in the funding landscape to enable and enforce the accessibility and availability of data. That is the only way to spark new innovations.“&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1328&quot; height=&quot;885&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_s8wK88EcBrigIM47-WDlcw-81884216.Bg-2pfLJ_Z1IdCiS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Ii86CSSyimnkzxo6EvjNxQ-65225314.DyHlhY_q.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>the end of theory for earth sciences</title><link>https://blog2.esciencecenter.nl/posts/2018-07-11---the-end-of-theory-for-earth-sciences</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-07-11---the-end-of-theory-for-earth-sciences</guid><description>&lt;p&gt;“The end of theory.” This is the title of an &lt;a href=&quot;https://www.wired.com/2008/06/pb-theory/&quot;&gt;article&lt;/a&gt; in Wired Magazine 10 years ago. No theory needed, the data deluge allows us to extract any knowledge by exploring data. This new empiricism received lots of attention and criticism. I came across it a few years ago when I started to immerse myself into the world of big data, artificial intelligence and computing. Having a background in climate research, I thought I knew all about computation and data. I was wrong.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;851&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Gpdu85aecoj1ih13jkjREA-9fdd973f.CaapzvcI_Z1U9h6C.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image Credit: NASA/NOAA/GSFC/Suomi NPP/VIIRS/Norman Kuring&lt;/p&gt;
&lt;p&gt;I work at the &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; now, which is an expertise center on research software at the interface of computer and data science and research applications. I got fascinated by the &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;wealth of projects&lt;/a&gt; at the eScience Center. Astronomers plowing through Petabytes of data to find pulsars, high energy physicists fitting their models to data from particle accelerators in a massive parallel way, humanities scholars learning with machines from ancient texts, sociologists unraveling complex networks, medical scientists taking advantage of modern sequencing methods, imaging techniques and coupling to many other data sets. It is a world with new names as SPARK and XENON and where bright stickers cover laptops. It is only natural to think about my own field of research and what all these developments in data sciences entail.&lt;/p&gt;
&lt;p&gt;In Earth sciences, including meteorology, it has been about theory and data in the past century. Based on theory, there is a quest for resolving finer scales in numerical models as physical processes interact seamlessly from the planetary to the molecular scales. Having a theory has large advantages. We know which equations to solve and theory limits state and parameter space in to explore. Still, to resolve deep convection, one of the most important drivers of the large scale weather and climate, at least a thousand-fold more computational resources are needed. New exascale computing developments are promising, but it will take much more than increasing generic computing resources and the machines are too energy-hungry. We clearly need new paradigms. Only through co-design with manufacturers, hardware vendors, software engineers, computer scientists and weather and climate scientists such a huge quest can be taken on. We can take astronomy for inspiration. Projects like LOFAR are a success due to co-design and its focus on research software and workflows to make very efficient pipelines. Only when we take such a professional approach that serves an entire community we can meet the demands.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Only through co-design with manufacturers, hardware vendors, software engineers, computer scientists and weather and climate scientists such a huge quest can be taken on”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do we need new data science methods as well? Of course. Processes at unresolved scales are not fully understood and boundary conditions, think of details and characteristics of the land surface, are poorly known. Interactions and processes beyond the physical domain often don’t have a basic theory. There is already work ongoing in heuristic modelling for radiative transfer, turbulence and cloud characteristics. Not only can such studies aid in increasing understanding, it also enables to accelerate simulations. Again, taking advantage from computer and data science knowledge and domain knowledge will bring in the necessary interdisciplinary perspective to make progress.&lt;/p&gt;
&lt;p&gt;The data integration is an even bigger challenge. There is so much data out there to take profit from. We can’t even count it. They say it must by Zetabytes. Using data from unconventional sensors in meteorology, such as my cell phone, is still at its infancy, let alone using social media data. Especially at short forecast horizons and at small scales, the heterogeneity of the environment and the limits of computation raises opportunities for machine learned models and to include unconventional data. Also, weather and climate information is just one source of information to base decisions on. It takes a much wider perspective on data and simulations to advance science and to advance informed decision making.&lt;/p&gt;
&lt;p&gt;All of this seems daunting to work on, but in proposals like Extreme Earth (a Flagship project proposed to the European Commission), our community comes together and dares to dream and pass disciplinary boundaries. Digital technology when developed in co-design will help us to reach our goals. We are on a mission. Confronting theory and simulations at all scales with data interactively will allow us to increase scientific understanding and improve informed decision making. I am looking forward to that bright Extreme Earth sticker, the only one that may cover my laptop case.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AJuDCuv6Bp8yXgx98QeNow-164cbc9d.BIDg2LrM_26EiDX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</description><pubDate>Wed, 11 Jul 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;“The end of theory.” This is the title of an &lt;a href=&quot;https://www.wired.com/2008/06/pb-theory/&quot;&gt;article&lt;/a&gt; in Wired Magazine 10 years ago. No theory needed, the data deluge allows us to extract any knowledge by exploring data. This new empiricism received lots of attention and criticism. I came across it a few years ago when I started to immerse myself into the world of big data, artificial intelligence and computing. Having a background in climate research, I thought I knew all about computation and data. I was wrong.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;851&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Gpdu85aecoj1ih13jkjREA-9fdd973f.CaapzvcI_Z1U9h6C.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Image Credit: NASA/NOAA/GSFC/Suomi NPP/VIIRS/Norman Kuring&lt;/p&gt;
&lt;p&gt;I work at the &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; now, which is an expertise center on research software at the interface of computer and data science and research applications. I got fascinated by the &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;wealth of projects&lt;/a&gt; at the eScience Center. Astronomers plowing through Petabytes of data to find pulsars, high energy physicists fitting their models to data from particle accelerators in a massive parallel way, humanities scholars learning with machines from ancient texts, sociologists unraveling complex networks, medical scientists taking advantage of modern sequencing methods, imaging techniques and coupling to many other data sets. It is a world with new names as SPARK and XENON and where bright stickers cover laptops. It is only natural to think about my own field of research and what all these developments in data sciences entail.&lt;/p&gt;
&lt;p&gt;In Earth sciences, including meteorology, it has been about theory and data in the past century. Based on theory, there is a quest for resolving finer scales in numerical models as physical processes interact seamlessly from the planetary to the molecular scales. Having a theory has large advantages. We know which equations to solve and theory limits state and parameter space in to explore. Still, to resolve deep convection, one of the most important drivers of the large scale weather and climate, at least a thousand-fold more computational resources are needed. New exascale computing developments are promising, but it will take much more than increasing generic computing resources and the machines are too energy-hungry. We clearly need new paradigms. Only through co-design with manufacturers, hardware vendors, software engineers, computer scientists and weather and climate scientists such a huge quest can be taken on. We can take astronomy for inspiration. Projects like LOFAR are a success due to co-design and its focus on research software and workflows to make very efficient pipelines. Only when we take such a professional approach that serves an entire community we can meet the demands.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Only through co-design with manufacturers, hardware vendors, software engineers, computer scientists and weather and climate scientists such a huge quest can be taken on”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do we need new data science methods as well? Of course. Processes at unresolved scales are not fully understood and boundary conditions, think of details and characteristics of the land surface, are poorly known. Interactions and processes beyond the physical domain often don’t have a basic theory. There is already work ongoing in heuristic modelling for radiative transfer, turbulence and cloud characteristics. Not only can such studies aid in increasing understanding, it also enables to accelerate simulations. Again, taking advantage from computer and data science knowledge and domain knowledge will bring in the necessary interdisciplinary perspective to make progress.&lt;/p&gt;
&lt;p&gt;The data integration is an even bigger challenge. There is so much data out there to take profit from. We can’t even count it. They say it must by Zetabytes. Using data from unconventional sensors in meteorology, such as my cell phone, is still at its infancy, let alone using social media data. Especially at short forecast horizons and at small scales, the heterogeneity of the environment and the limits of computation raises opportunities for machine learned models and to include unconventional data. Also, weather and climate information is just one source of information to base decisions on. It takes a much wider perspective on data and simulations to advance science and to advance informed decision making.&lt;/p&gt;
&lt;p&gt;All of this seems daunting to work on, but in proposals like Extreme Earth (a Flagship project proposed to the European Commission), our community comes together and dares to dream and pass disciplinary boundaries. Digital technology when developed in co-design will help us to reach our goals. We are on a mission. Confronting theory and simulations at all scales with data interactively will allow us to increase scientific understanding and improve informed decision making. I am looking forward to that bright Extreme Earth sticker, the only one that may cover my laptop case.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;278&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AJuDCuv6Bp8yXgx98QeNow-164cbc9d.BIDg2LrM_26EiDX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Gpdu85aecoj1ih13jkjREA-9fdd973f.CaapzvcI.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Flavour your linked data with garlic</title><link>https://blog2.esciencecenter.nl/posts/2018-06-12---flavour-your-linked-data-with-garlic</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-06-12---flavour-your-linked-data-with-garlic</guid><description>&lt;h2 id=&quot;explore-linked-data-collections-via-web-apis--zero-coding-required&quot;&gt;Explore linked data collections via Web-API’s — zero coding required!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Linked_data&quot;&gt;Linked data&lt;/a&gt; is growing in importance — and rightly so: it facilitates machine readability of data, making it easier for machines to explore connections in meaning (semantic) which are obvious to humans but not to machines.&lt;/p&gt;
&lt;p&gt;SPARQL! In the world of linked data, &lt;a href=&quot;https://www.w3.org/TR/rdf-sparql-query/&quot;&gt;SPARQL queries&lt;/a&gt; are used extensively as the query language to extract data from a &lt;a href=&quot;https://ontotext.com/knowledgehub/fundamentals/what-is-rdf-triplestore/&quot;&gt;triple store&lt;/a&gt; (a special type of database for storing linked data): they are our main tool to interact with linked data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1199&quot; height=&quot;377&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AAfUPXTqK7n7GFxLRUm8IA-22c7fd43.D4gNCw-h_CbeL5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A SPARQL query&lt;/p&gt;
&lt;p&gt;But writing SPARQL queries is not the most trivial of tasks. Most researchers who &lt;em&gt;want&lt;/em&gt; to work with linked data do not &lt;em&gt;know&lt;/em&gt; how to write SPARQL queries — and maybe they shouldn’t need to know! Let the SPARQL expert write a few queries which can search through the data and the domain expert can use these queries as required.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/CLARIAH/grlc&quot;&gt;&lt;em&gt;&lt;strong&gt;grlc&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; — grlc (pronounced ‘garlic’) is a tool which &lt;em&gt;“automatically builds Web APIs using SPARQL queries stored in git repositories”&lt;/em&gt;. What this means in practice is that you can store your &lt;a href=&quot;https://github.com/albertmeronyo/lodapi/&quot;&gt;SPARQL queries on GitHub&lt;/a&gt; and then you can run your queries on your favourite programming language (Python, Javascript, etc.) using a Web API (including &lt;a href=&quot;https://swagger.io/&quot;&gt;swagger&lt;/a&gt; documentation) just as easily as loading data from a web page.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;699&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_a3nAq2OlHti-wvFN3TGLVw-cbf7c688.T8BLzRG5_Z11xdp5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Grlc — from GitHub to data&lt;/p&gt;
&lt;h3 id=&quot;who-is-using-grlc&quot;&gt;Who is using grlc?&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;grlc&lt;/em&gt; was initially developed as one of the tools used in &lt;a href=&quot;https://www.clariah.nl/&quot;&gt;CLARIAH&lt;/a&gt;, the Dutch research infrastructure for the arts and humanities. It was then adopted to be part of the CLARIAH &lt;a href=&quot;https://www.clariah.nl/werkpakketten/focusgebieden/media-studies&quot;&gt;MediaSuite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Within the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we are promoting the use of &lt;em&gt;grlc&lt;/em&gt; in our projects which have a linked data component. So far, it has been used within the &lt;a href=&quot;https://www.esciencecenter.nl/project/prediction-of-candidate-genes-for-traits-using-interoperable-genome-annotat&quot;&gt;&lt;em&gt;CandyGene&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/project/data-quality-in-a-distributed-learning-environment&quot;&gt;&lt;em&gt;DataQuality&lt;/em&gt;&lt;/a&gt; projects. In both cases, the Web API is used to load data on a &lt;a href=&quot;http://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt; notebook to visualize the results of the queries. This enables researchers to interact with data in triple stores without having to type a single line of SPARQL.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;725&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZgE1l17dt7laWb5bca6K-g-bba2c7c4.CklkLZbj_FwPux.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Loading data via grlc into Jupyter notebooks — these plots were created from data loaded via a grlc Web API.&lt;/p&gt;
&lt;h3 id=&quot;extra-features&quot;&gt;Extra features&lt;/h3&gt;
&lt;p&gt;But where is the data stored? Do I need to load all my data at once, or can I paginate my query? Do my results get cached? Can I customize the output of my query? What if I want… — all valid questions, but the answers are beyond the scope of this blog post. If you want to know more details of what &lt;em&gt;grlc&lt;/em&gt; can and cannot do, please &lt;a href=&quot;https://github.com/CLARIAH/grlc#usage&quot;&gt;head to the usage section&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;If you are working with linked data, you should use &lt;em&gt;grlc&lt;/em&gt;!&lt;/p&gt;</description><pubDate>Tue, 12 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;explore-linked-data-collections-via-web-apis--zero-coding-required&quot;&gt;Explore linked data collections via Web-API’s — zero coding required!&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Linked_data&quot;&gt;Linked data&lt;/a&gt; is growing in importance — and rightly so: it facilitates machine readability of data, making it easier for machines to explore connections in meaning (semantic) which are obvious to humans but not to machines.&lt;/p&gt;
&lt;p&gt;SPARQL! In the world of linked data, &lt;a href=&quot;https://www.w3.org/TR/rdf-sparql-query/&quot;&gt;SPARQL queries&lt;/a&gt; are used extensively as the query language to extract data from a &lt;a href=&quot;https://ontotext.com/knowledgehub/fundamentals/what-is-rdf-triplestore/&quot;&gt;triple store&lt;/a&gt; (a special type of database for storing linked data): they are our main tool to interact with linked data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1199&quot; height=&quot;377&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AAfUPXTqK7n7GFxLRUm8IA-22c7fd43.D4gNCw-h_CbeL5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A SPARQL query&lt;/p&gt;
&lt;p&gt;But writing SPARQL queries is not the most trivial of tasks. Most researchers who &lt;em&gt;want&lt;/em&gt; to work with linked data do not &lt;em&gt;know&lt;/em&gt; how to write SPARQL queries — and maybe they shouldn’t need to know! Let the SPARQL expert write a few queries which can search through the data and the domain expert can use these queries as required.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://github.com/CLARIAH/grlc&quot;&gt;&lt;em&gt;&lt;strong&gt;grlc&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; — grlc (pronounced ‘garlic’) is a tool which &lt;em&gt;“automatically builds Web APIs using SPARQL queries stored in git repositories”&lt;/em&gt;. What this means in practice is that you can store your &lt;a href=&quot;https://github.com/albertmeronyo/lodapi/&quot;&gt;SPARQL queries on GitHub&lt;/a&gt; and then you can run your queries on your favourite programming language (Python, Javascript, etc.) using a Web API (including &lt;a href=&quot;https://swagger.io/&quot;&gt;swagger&lt;/a&gt; documentation) just as easily as loading data from a web page.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;699&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_a3nAq2OlHti-wvFN3TGLVw-cbf7c688.T8BLzRG5_Z11xdp5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Grlc — from GitHub to data&lt;/p&gt;
&lt;h3 id=&quot;who-is-using-grlc&quot;&gt;Who is using grlc?&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;grlc&lt;/em&gt; was initially developed as one of the tools used in &lt;a href=&quot;https://www.clariah.nl/&quot;&gt;CLARIAH&lt;/a&gt;, the Dutch research infrastructure for the arts and humanities. It was then adopted to be part of the CLARIAH &lt;a href=&quot;https://www.clariah.nl/werkpakketten/focusgebieden/media-studies&quot;&gt;MediaSuite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Within the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we are promoting the use of &lt;em&gt;grlc&lt;/em&gt; in our projects which have a linked data component. So far, it has been used within the &lt;a href=&quot;https://www.esciencecenter.nl/project/prediction-of-candidate-genes-for-traits-using-interoperable-genome-annotat&quot;&gt;&lt;em&gt;CandyGene&lt;/em&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.esciencecenter.nl/project/data-quality-in-a-distributed-learning-environment&quot;&gt;&lt;em&gt;DataQuality&lt;/em&gt;&lt;/a&gt; projects. In both cases, the Web API is used to load data on a &lt;a href=&quot;http://jupyter.org/&quot;&gt;Jupyter&lt;/a&gt; notebook to visualize the results of the queries. This enables researchers to interact with data in triple stores without having to type a single line of SPARQL.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;725&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZgE1l17dt7laWb5bca6K-g-bba2c7c4.CklkLZbj_FwPux.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Loading data via grlc into Jupyter notebooks — these plots were created from data loaded via a grlc Web API.&lt;/p&gt;
&lt;h3 id=&quot;extra-features&quot;&gt;Extra features&lt;/h3&gt;
&lt;p&gt;But where is the data stored? Do I need to load all my data at once, or can I paginate my query? Do my results get cached? Can I customize the output of my query? What if I want… — all valid questions, but the answers are beyond the scope of this blog post. If you want to know more details of what &lt;em&gt;grlc&lt;/em&gt; can and cannot do, please &lt;a href=&quot;https://github.com/CLARIAH/grlc#usage&quot;&gt;head to the usage section&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;If you are working with linked data, you should use &lt;em&gt;grlc&lt;/em&gt;!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_AAfUPXTqK7n7GFxLRUm8IA-22c7fd43.D4gNCw-h.jpeg" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>blobs, bumps, clouds and clusters</title><link>https://blog2.esciencecenter.nl/posts/2018-06-05---blobs-bumps-clouds-and-clusters</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-06-05---blobs-bumps-clouds-and-clusters</guid><description>&lt;h2 id=&quot;statistical-fluke-or-scientific-evidence&quot;&gt;Statistical fluke or scientific evidence?&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1354&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vzyMIYweAqDc2ZA352uVSw-bbe2c107.CsHlSDZi_ZlHicU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Definitely a blob.&lt;/p&gt;
&lt;p&gt;Another earth-shattering discovery is on the horizon. &lt;a href=&quot;https://www.quantamagazine.org/evidence-found-for-a-new-fundamental-particle-20180601/&quot;&gt;Evidence was found for a new fundamental particle&lt;/a&gt;! The times we live in!&lt;/p&gt;
&lt;p&gt;Coming from an astronomy background, I should have known better than to click on the link, but click and read I did. I’ve always had a weak spot for revolutionary cosmological and particle physics theories. Revolutionary theories of any kind, come to think of it.&lt;/p&gt;
&lt;p&gt;I’m not sure whether the evidence is yet as solid as the inviting title suggests. “[…] a few hundred more electron neutrinos than expected” sounds to me like “please extend our funding, we promise we’ll find more”. Nevertheless, it is an exciting possibility and I hope they’ll get to continue their experiments, perhaps on a slightly larger scale so that we won’t have to wait another 15 years for another few hundred events.&lt;/p&gt;
&lt;p&gt;Physics aside, one quote that caught my attention was the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I am not ready to bet my money yet because the excess is kind of a blob on a plot”, Conrad said. “What if something else can make a blob? To be really convinced, I want to see, with high significance, this predicted wiggle.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is exactly the kind of language that astronomers use when discussing latest results. Astronomy and particle physics seem pretty similar then, staring at fuzzy blobs and bumps and making something out of it. Also, in both cases, these are blobs, bumps and wiggles that took at least a year of modeling and data reduction to produce. And the best bumps are those that have not been explained before.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1372&quot; height=&quot;1000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6-utQVilhdQwzgmk9-PVbw-6fe45bd8.CWZoLDnF_29dwaY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looks like nebulas to me.&lt;/p&gt;
&lt;p&gt;The innocent bystander may wonder whether professional scientists talking in such childish terms can be taken seriously at all. The fact that a senior writer in a popular science publication did not edit out the blobs and wiggles may already tell you that you should take it seriously.&lt;/p&gt;
&lt;p&gt;In fact, this kind of language can tell you whether some discovery is really new. In a year or so, after a first paper has been published and some conference talks have been given, the blob or wiggle may have been officially upgraded to an “excess” (already seen in the above quote), a “shapoid”, a “cloud”, a “cluster” or some other nebulous but more official sounding term.&lt;/p&gt;
&lt;p&gt;Our little baby blob has then reached its toddler phase. It will start walking and talking a little. But it has a long way to go towards adulthood. And, sadly, infant mortality rates among blobs are pretty high.&lt;/p&gt;
&lt;p&gt;Perhaps, though, it will some day be explained by something other than a statistical fluke or some existing theory (the main causes of blob mortality). Maybe, then, it will get a real name. A “phenomenon” or even a bonafide “theory”, together with the surname of its discoverer or explainer. One can hope.&lt;/p&gt;
&lt;p&gt;When do you think we should take blobs, bumps, clouds and clusters seriously? Leave your thoughts in the comments!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YAzuyHQ0Fb9nXFmFq9Z8iA-1fd6abf5.D86DCUU2_1dqAXU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From &lt;a href=&quot;https://www.exploratorium.edu/blogs/spectrum/blob-might-ruin-christmas&quot;&gt;https://www.exploratorium.edu/blogs/spectrum/blob-might-ruin-christmas&lt;/a&gt;. Oceanographers have learned to make use of the full terrifying potential of the term.&lt;/p&gt;</description><pubDate>Tue, 05 Jun 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;statistical-fluke-or-scientific-evidence&quot;&gt;Statistical fluke or scientific evidence?&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1354&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vzyMIYweAqDc2ZA352uVSw-bbe2c107.CsHlSDZi_ZlHicU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Definitely a blob.&lt;/p&gt;
&lt;p&gt;Another earth-shattering discovery is on the horizon. &lt;a href=&quot;https://www.quantamagazine.org/evidence-found-for-a-new-fundamental-particle-20180601/&quot;&gt;Evidence was found for a new fundamental particle&lt;/a&gt;! The times we live in!&lt;/p&gt;
&lt;p&gt;Coming from an astronomy background, I should have known better than to click on the link, but click and read I did. I’ve always had a weak spot for revolutionary cosmological and particle physics theories. Revolutionary theories of any kind, come to think of it.&lt;/p&gt;
&lt;p&gt;I’m not sure whether the evidence is yet as solid as the inviting title suggests. “[…] a few hundred more electron neutrinos than expected” sounds to me like “please extend our funding, we promise we’ll find more”. Nevertheless, it is an exciting possibility and I hope they’ll get to continue their experiments, perhaps on a slightly larger scale so that we won’t have to wait another 15 years for another few hundred events.&lt;/p&gt;
&lt;p&gt;Physics aside, one quote that caught my attention was the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I am not ready to bet my money yet because the excess is kind of a blob on a plot”, Conrad said. “What if something else can make a blob? To be really convinced, I want to see, with high significance, this predicted wiggle.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is exactly the kind of language that astronomers use when discussing latest results. Astronomy and particle physics seem pretty similar then, staring at fuzzy blobs and bumps and making something out of it. Also, in both cases, these are blobs, bumps and wiggles that took at least a year of modeling and data reduction to produce. And the best bumps are those that have not been explained before.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1372&quot; height=&quot;1000&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6-utQVilhdQwzgmk9-PVbw-6fe45bd8.CWZoLDnF_29dwaY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Looks like nebulas to me.&lt;/p&gt;
&lt;p&gt;The innocent bystander may wonder whether professional scientists talking in such childish terms can be taken seriously at all. The fact that a senior writer in a popular science publication did not edit out the blobs and wiggles may already tell you that you should take it seriously.&lt;/p&gt;
&lt;p&gt;In fact, this kind of language can tell you whether some discovery is really new. In a year or so, after a first paper has been published and some conference talks have been given, the blob or wiggle may have been officially upgraded to an “excess” (already seen in the above quote), a “shapoid”, a “cloud”, a “cluster” or some other nebulous but more official sounding term.&lt;/p&gt;
&lt;p&gt;Our little baby blob has then reached its toddler phase. It will start walking and talking a little. But it has a long way to go towards adulthood. And, sadly, infant mortality rates among blobs are pretty high.&lt;/p&gt;
&lt;p&gt;Perhaps, though, it will some day be explained by something other than a statistical fluke or some existing theory (the main causes of blob mortality). Maybe, then, it will get a real name. A “phenomenon” or even a bonafide “theory”, together with the surname of its discoverer or explainer. One can hope.&lt;/p&gt;
&lt;p&gt;When do you think we should take blobs, bumps, clouds and clusters seriously? Leave your thoughts in the comments!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1400&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YAzuyHQ0Fb9nXFmFq9Z8iA-1fd6abf5.D86DCUU2_1dqAXU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From &lt;a href=&quot;https://www.exploratorium.edu/blogs/spectrum/blob-might-ruin-christmas&quot;&gt;https://www.exploratorium.edu/blogs/spectrum/blob-might-ruin-christmas&lt;/a&gt;. Oceanographers have learned to make use of the full terrifying potential of the term.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_6-utQVilhdQwzgmk9-PVbw-6fe45bd8.CWZoLDnF.png" medium="image"/><author>Patrick Bos</author></item><item><title>research and software perspectives from different communities</title><link>https://blog2.esciencecenter.nl/posts/2018-04-13---research-and-software-perspectives-from-different-communities</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-04-13---research-and-software-perspectives-from-different-communities</guid><description>&lt;p&gt;Last week the Principal Investigators collaborating with the eScience Center’s team came together to share experiences on collaborative research projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography:&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;Elodie Burrillon&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NslHgcDVP6ymEbepbC6mKA-8b580f11.D4BRn4a3_1BCKyg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our work is driven by the challenges faced by academic researchers, which is why we want to deeply understand the needs and objectives of our principal investigators. We are convinced that by working together with researchers from different academic disciplines and technology areas we can advance the state of academic research. One of the goals of this day was therefore to jointly signal challenges and formulate opinions and solutions at the intersection of software and academic research.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inspiring talks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The day started and ended with inspiring talks from eScience Prinicipal Investigators. In the morning, Christian Lange from Utrecht University presented his research on the Arabic-Islamic corpus. The ‘Bridging the Gap’ project is a collaboration with Christian Lange’s team and the eScience Center in which we develop and apply research software to gain more insight into the vast corpus of digitized Arabic texts that has become available in the last decade.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YwSRFSDLxiT_qfwVAFS2ng-2ff5fbae.DLz75-So_ifXIB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Christian Lange (Utrecht University) presents his research on the Arabic-Islamic corpus&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Talkshows&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Christian Lange’s presentation was followed by a talkshow with two eScience Research Engineers collaborating on this project: Dafne van Kuppevelt and Janneke van der Zwaan.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YtKjStkdu92GKlbSHFbsSw-6c6cd812.DYOJ2y8C_11CH4K.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dafne van Kuppevelt and Janneke van der Zwaan, eScience Research Engineers&lt;/p&gt;
&lt;p&gt;Dafne and Janneke talked about their experience on working in a discipline they were unfamiliar with before (Arabic literature), and the process of finding and re-using research software.&lt;/p&gt;
&lt;p&gt;Finding and re-using software in different research communities was also the topic of the talkshow that followed. Joeri van Leeuwen (ASTRON), astronomer, Rolf Hut (TU Delft), hydrologist, and Martin Reynaert (Tilburg University), digital humanities, discussed how the practices of working with research software differ between their communities. The talkshow resulted in a lively discussion in which it was clear that there are different practices and opinions between communities around the use and sharing of software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tNWgkoDZ9nLj1uejnRZi6g-bb65e5fb.PjutP8Qz_KkDF9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen (ASTRON), Rolf Hut (TU Delft), and Martin Reynaert (Tilburg University)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Break-out sessions on research &amp;#x26; software&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DKDaoGdt6iw3rrz-Q4LYEQ-d4f7b3cf.B-Bgb1Cp_1OwqSS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the afternoon this discussion continued in smaller groups, in which different ways to stimulate to re-use of software were explored.&lt;/p&gt;
&lt;p&gt;After lunch, Jurriaan Spaaks, eScience Research Engineer, presented the eScience Center’s Research Software Directory (RSD). The RSD is one of the vehicles by which the eScience Center aims to encourage the re-use of software. However, the success of any such directory depends on how well it fits the needs of Principal Investigators and different research communities. Jurriaan’s presentation was therefore followed by a break-out session in which Principal Investigators and the eScience Center’s team developed SWOT-analyses of the RSD — what are its strengths and weaknesses, and can we identify opportunities or threats?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sk0HcsdCg_TWh3OQ-e9H8w-218e5c8b.DoimTZoZ_Z1yXzpl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;After two energetic break-out sessions, Principal Investigator Frank Takes closed the day by presenting his exciting research on offshore finance in which he uses software to analyze complex relations and networks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Valuable insights&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The day provided valuable new input for the eScience Center on the needs of different research communities, which will guide the continued development of our activities in enabling digitally enhanced research, and specifically also the RSD. We are thankful for the contributions and inspirational insights of our collaborative partners in these discussions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_L46N7f2PycQ4ggbwLhq-rA-273a1c44.Dxowfbql_ZpRdHW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</description><pubDate>Fri, 13 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week the Principal Investigators collaborating with the eScience Center’s team came together to share experiences on collaborative research projects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography:&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;Elodie Burrillon&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NslHgcDVP6ymEbepbC6mKA-8b580f11.D4BRn4a3_1BCKyg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our work is driven by the challenges faced by academic researchers, which is why we want to deeply understand the needs and objectives of our principal investigators. We are convinced that by working together with researchers from different academic disciplines and technology areas we can advance the state of academic research. One of the goals of this day was therefore to jointly signal challenges and formulate opinions and solutions at the intersection of software and academic research.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inspiring talks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The day started and ended with inspiring talks from eScience Prinicipal Investigators. In the morning, Christian Lange from Utrecht University presented his research on the Arabic-Islamic corpus. The ‘Bridging the Gap’ project is a collaboration with Christian Lange’s team and the eScience Center in which we develop and apply research software to gain more insight into the vast corpus of digitized Arabic texts that has become available in the last decade.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YwSRFSDLxiT_qfwVAFS2ng-2ff5fbae.DLz75-So_ifXIB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Christian Lange (Utrecht University) presents his research on the Arabic-Islamic corpus&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Talkshows&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Christian Lange’s presentation was followed by a talkshow with two eScience Research Engineers collaborating on this project: Dafne van Kuppevelt and Janneke van der Zwaan.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_YtKjStkdu92GKlbSHFbsSw-6c6cd812.DYOJ2y8C_11CH4K.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dafne van Kuppevelt and Janneke van der Zwaan, eScience Research Engineers&lt;/p&gt;
&lt;p&gt;Dafne and Janneke talked about their experience on working in a discipline they were unfamiliar with before (Arabic literature), and the process of finding and re-using research software.&lt;/p&gt;
&lt;p&gt;Finding and re-using software in different research communities was also the topic of the talkshow that followed. Joeri van Leeuwen (ASTRON), astronomer, Rolf Hut (TU Delft), hydrologist, and Martin Reynaert (Tilburg University), digital humanities, discussed how the practices of working with research software differ between their communities. The talkshow resulted in a lively discussion in which it was clear that there are different practices and opinions between communities around the use and sharing of software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_tNWgkoDZ9nLj1uejnRZi6g-bb65e5fb.PjutP8Qz_KkDF9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen (ASTRON), Rolf Hut (TU Delft), and Martin Reynaert (Tilburg University)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Break-out sessions on research &amp;#x26; software&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DKDaoGdt6iw3rrz-Q4LYEQ-d4f7b3cf.B-Bgb1Cp_1OwqSS.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the afternoon this discussion continued in smaller groups, in which different ways to stimulate to re-use of software were explored.&lt;/p&gt;
&lt;p&gt;After lunch, Jurriaan Spaaks, eScience Research Engineer, presented the eScience Center’s Research Software Directory (RSD). The RSD is one of the vehicles by which the eScience Center aims to encourage the re-use of software. However, the success of any such directory depends on how well it fits the needs of Principal Investigators and different research communities. Jurriaan’s presentation was therefore followed by a break-out session in which Principal Investigators and the eScience Center’s team developed SWOT-analyses of the RSD — what are its strengths and weaknesses, and can we identify opportunities or threats?&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sk0HcsdCg_TWh3OQ-e9H8w-218e5c8b.DoimTZoZ_Z1yXzpl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;After two energetic break-out sessions, Principal Investigator Frank Takes closed the day by presenting his exciting research on offshore finance in which he uses software to analyze complex relations and networks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Valuable insights&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The day provided valuable new input for the eScience Center on the needs of different research communities, which will guide the continued development of our activities in enabling digitally enhanced research, and specifically also the RSD. We are thankful for the contributions and inspirational insights of our collaborative partners in these discussions.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_L46N7f2PycQ4ggbwLhq-rA-273a1c44.Dxowfbql_ZpRdHW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_YwSRFSDLxiT_qfwVAFS2ng-2ff5fbae.DLz75-So.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>active learning</title><link>https://blog2.esciencecenter.nl/posts/2018-03-20---active-learning</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-03-20---active-learning</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ip7UM0nLXChqg8vw6hivcg-bf510538.DwMkw30r_Z19svro.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Computers perform better than humans in arithmetic and chess but if there is one task in which humans are superior it is image processing. But for how long? In 2015 there was a breakthrough in computing science: the &lt;a href=&quot;https://arxiv.org/pdf/1512.03385.pdf&quot;&gt;ResNet&lt;/a&gt; system won the international image recognition competition &lt;a href=&quot;http://image-net.org/&quot;&gt;ImageNet Challenge&lt;/a&gt; with a score of 96.5%. People achieve 95% on that task. For the first time, a computer was better than humans in identifying objects in images.&lt;/p&gt;
&lt;p&gt;The winning system used machine learning to recognize objects in images. The advantage of using machine learning is that you do not need to specify a task in great detail. Instead you provide the computer with examples of input and required output. If the task is recognizing the content of images, the input consists of images while the associated outputs are labels specifying the contents of the images. The computer then uses machine learning to learn how to assign labels to any image based on the available examples.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;292&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_blKiRBXTOa73tuXYonlUfQ-02d4804b.BNxsJbEh_jENmX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Three examples of labelled images from the ImageNet challenge: label people (left), label house (center) and label website (right)&lt;/p&gt;
&lt;p&gt;If we want the machine learner to perform well, we need to supply it with many good training examples. But what are the best examples? An image which ==is== very similar to one of the known examples, will probably not contribute much to the learning process. But an image which is quite different, might be a good new training example.&lt;/p&gt;
&lt;p&gt;It would be nice if there was an automatic method for determining of which training examples a machine learner would benefit most. Then we can restrict human labeling efforts to these data and quickly improve the machine learning. Such a method exists: it is called &lt;strong&gt;active learning&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;879&quot; height=&quot;287&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BdSQuGsyzCI0zuM8pIQenA-5eae29ef.c3MIcM6i_xP49K.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The active learning process: a machine learner labels new data based on training examples. The best items are selected by active learning. These are labelled by a human annotator and added to the training examples after which the process is repeated.&lt;/p&gt;
&lt;p&gt;Active learning is a semi-automatic method for expanding the training set of a machine learner. For example, if we want to learn the difference between images of cats and images of dogs, we can train a machine learner using images which are labelled either “cat” or “dog”. We can expand this set of training examples with active learning by performing the following six steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;train the machine learner with all available labelled training examples&lt;/li&gt;
&lt;li&gt;use the learner to classify many unlabelled images&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;select the images which could be most instructive for the learner&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;ask a human to assign correct labels to these images&lt;/li&gt;
&lt;li&gt;add the newly labelled images to the training set and retrain&lt;/li&gt;
&lt;li&gt;repeat steps 2–5 until the performance reaches an acceptable level&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The most challenging part of this active learning process is step 3. There are two ways of performing this step. First, we can require the machine learner to specify for each predicted label how confident it is about the prediction, and select the items with the lowest confidence (uncertainty sampling). Second, we can use several competing machine learners to predict labels and select the items on which they disagree (query-by-committee, more detailed information can be found in a study by &lt;a href=&quot;http://burrsettles.com/pub/settles.activelearning.pdf&quot;&gt;Burr Settles&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;840&quot; height=&quot;199&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LtDiL648MS0Fd45E_ArEWg-868eeae4.DQiYl6oy_11M3P7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Examples of images from the competition Dog vs Cats by Kaggle. The best image recognition systems currently manage to recognize more than 98% of these images correctly.&lt;/p&gt;
&lt;h2 id=&quot;example-automatic-spelling-correction&quot;&gt;Example: automatic spelling correction&lt;/h2&gt;
&lt;p&gt;An example of an application of active learning is the study of &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/acl2001.pdf&quot;&gt;Michelle Banko and Eric Brill&lt;/a&gt; on automatic spelling correction. They started with a training text of one million words and achieved a score of 96% on their task. By adding to the training data randomly selected texts with a total length of six million words, they managed to improve the score to 97%. But next, they showed that if the extra texts of six million words were selected with active learning (query-by-committee), the score on their task went up to almost 99%, a significant reduction of the error.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;990&quot; height=&quot;157&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uWJdJ52Us6JFY3nwA6Xvzg-4186a06a.CwJ-TzDy_Z1fFbiM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;when-active-learning-does-not-help&quot;&gt;When active learning does not help&lt;/h2&gt;
&lt;p&gt;Several studies have shown that active learning can be applied successfully to improve the performance of machine learning. Increasing the number of training examples will often improve machine learners. The advantage of active learning is that it picks the new training examples in a smart way so that the machine learner can improve faster than when the training material was chosen randomly. However, active learning does not always perform better than random selection of new training examples. Most importantly, &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0304397510007620&quot;&gt;Sanjoy Dasgupta&lt;/a&gt; has shown that active learning will only work better than random selection if the initial size of training examples is large enough so that the initial machine learner can make reliable predictions. The required training size depends on the problem and is usually hard to estimate.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;88&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QUtAcWuLvlautD5kEL7gfg-bf1343aa.CrG48HDM_ZmexSK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;active-learning-at-the-netherlands-escience-center&quot;&gt;Active learning at the Netherlands eScience Center&lt;/h2&gt;
&lt;p&gt;Since lack of training data is a common problem in machine learning research, there are several projects of the &lt;a href=&quot;http://esciencecenter.nl/&quot;&gt;Netherlands Science Center&lt;/a&gt; that are interested in applying active learning. The method was already used by &lt;a href=&quot;https://ifarm.nl/erikt/papers/2017-icnlssp.pdf&quot;&gt;myself&lt;/a&gt; in the project &lt;a href=&quot;https://www.esciencecenter.nl/project/automated-analysis-of-online-behaviour-on-social-media&quot;&gt;Automated Analysis of Online Behaviour on Social Media&lt;/a&gt; (2017) for obtaining more political tweets labelled with the intention of the sender. The topic active learning was also discussed in the meetings of the Machine Learning group of the eScience Center. Do you have any active learning tips and tricks for our group? Please let us know in the comments below!&lt;/p&gt;</description><pubDate>Tue, 20 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;600&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ip7UM0nLXChqg8vw6hivcg-bf510538.DwMkw30r_Z19svro.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Computers perform better than humans in arithmetic and chess but if there is one task in which humans are superior it is image processing. But for how long? In 2015 there was a breakthrough in computing science: the &lt;a href=&quot;https://arxiv.org/pdf/1512.03385.pdf&quot;&gt;ResNet&lt;/a&gt; system won the international image recognition competition &lt;a href=&quot;http://image-net.org/&quot;&gt;ImageNet Challenge&lt;/a&gt; with a score of 96.5%. People achieve 95% on that task. For the first time, a computer was better than humans in identifying objects in images.&lt;/p&gt;
&lt;p&gt;The winning system used machine learning to recognize objects in images. The advantage of using machine learning is that you do not need to specify a task in great detail. Instead you provide the computer with examples of input and required output. If the task is recognizing the content of images, the input consists of images while the associated outputs are labels specifying the contents of the images. The computer then uses machine learning to learn how to assign labels to any image based on the available examples.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;292&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_blKiRBXTOa73tuXYonlUfQ-02d4804b.BNxsJbEh_jENmX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Three examples of labelled images from the ImageNet challenge: label people (left), label house (center) and label website (right)&lt;/p&gt;
&lt;p&gt;If we want the machine learner to perform well, we need to supply it with many good training examples. But what are the best examples? An image which ==is== very similar to one of the known examples, will probably not contribute much to the learning process. But an image which is quite different, might be a good new training example.&lt;/p&gt;
&lt;p&gt;It would be nice if there was an automatic method for determining of which training examples a machine learner would benefit most. Then we can restrict human labeling efforts to these data and quickly improve the machine learning. Such a method exists: it is called &lt;strong&gt;active learning&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;879&quot; height=&quot;287&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BdSQuGsyzCI0zuM8pIQenA-5eae29ef.c3MIcM6i_xP49K.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The active learning process: a machine learner labels new data based on training examples. The best items are selected by active learning. These are labelled by a human annotator and added to the training examples after which the process is repeated.&lt;/p&gt;
&lt;p&gt;Active learning is a semi-automatic method for expanding the training set of a machine learner. For example, if we want to learn the difference between images of cats and images of dogs, we can train a machine learner using images which are labelled either “cat” or “dog”. We can expand this set of training examples with active learning by performing the following six steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;train the machine learner with all available labelled training examples&lt;/li&gt;
&lt;li&gt;use the learner to classify many unlabelled images&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;select the images which could be most instructive for the learner&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;ask a human to assign correct labels to these images&lt;/li&gt;
&lt;li&gt;add the newly labelled images to the training set and retrain&lt;/li&gt;
&lt;li&gt;repeat steps 2–5 until the performance reaches an acceptable level&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The most challenging part of this active learning process is step 3. There are two ways of performing this step. First, we can require the machine learner to specify for each predicted label how confident it is about the prediction, and select the items with the lowest confidence (uncertainty sampling). Second, we can use several competing machine learners to predict labels and select the items on which they disagree (query-by-committee, more detailed information can be found in a study by &lt;a href=&quot;http://burrsettles.com/pub/settles.activelearning.pdf&quot;&gt;Burr Settles&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;840&quot; height=&quot;199&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LtDiL648MS0Fd45E_ArEWg-868eeae4.DQiYl6oy_11M3P7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Examples of images from the competition Dog vs Cats by Kaggle. The best image recognition systems currently manage to recognize more than 98% of these images correctly.&lt;/p&gt;
&lt;h2 id=&quot;example-automatic-spelling-correction&quot;&gt;Example: automatic spelling correction&lt;/h2&gt;
&lt;p&gt;An example of an application of active learning is the study of &lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/acl2001.pdf&quot;&gt;Michelle Banko and Eric Brill&lt;/a&gt; on automatic spelling correction. They started with a training text of one million words and achieved a score of 96% on their task. By adding to the training data randomly selected texts with a total length of six million words, they managed to improve the score to 97%. But next, they showed that if the extra texts of six million words were selected with active learning (query-by-committee), the score on their task went up to almost 99%, a significant reduction of the error.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;990&quot; height=&quot;157&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_uWJdJ52Us6JFY3nwA6Xvzg-4186a06a.CwJ-TzDy_Z1fFbiM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;when-active-learning-does-not-help&quot;&gt;When active learning does not help&lt;/h2&gt;
&lt;p&gt;Several studies have shown that active learning can be applied successfully to improve the performance of machine learning. Increasing the number of training examples will often improve machine learners. The advantage of active learning is that it picks the new training examples in a smart way so that the machine learner can improve faster than when the training material was chosen randomly. However, active learning does not always perform better than random selection of new training examples. Most importantly, &lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0304397510007620&quot;&gt;Sanjoy Dasgupta&lt;/a&gt; has shown that active learning will only work better than random selection if the initial size of training examples is large enough so that the initial machine learner can make reliable predictions. The required training size depends on the problem and is usually hard to estimate.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;88&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QUtAcWuLvlautD5kEL7gfg-bf1343aa.CrG48HDM_ZmexSK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;active-learning-at-the-netherlands-escience-center&quot;&gt;Active learning at the Netherlands eScience Center&lt;/h2&gt;
&lt;p&gt;Since lack of training data is a common problem in machine learning research, there are several projects of the &lt;a href=&quot;http://esciencecenter.nl/&quot;&gt;Netherlands Science Center&lt;/a&gt; that are interested in applying active learning. The method was already used by &lt;a href=&quot;https://ifarm.nl/erikt/papers/2017-icnlssp.pdf&quot;&gt;myself&lt;/a&gt; in the project &lt;a href=&quot;https://www.esciencecenter.nl/project/automated-analysis-of-online-behaviour-on-social-media&quot;&gt;Automated Analysis of Online Behaviour on Social Media&lt;/a&gt; (2017) for obtaining more political tweets labelled with the intention of the sender. The topic active learning was also discussed in the meetings of the Machine Learning group of the eScience Center. Do you have any active learning tips and tricks for our group? Please let us know in the comments below!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_blKiRBXTOa73tuXYonlUfQ-02d4804b.BNxsJbEh.jpeg" medium="image"/><author>Erik Tjong Kim Sang</author></item><item><title>spot  visual scientific data analytics made easy</title><link>https://blog2.esciencecenter.nl/posts/2018-01-16---spot-visual-scientific-data-analytics-made-easy</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2018-01-16---spot-visual-scientific-data-analytics-made-easy</guid><description>&lt;p&gt;&lt;em&gt;If you are using scientific visualization tools in your work then you should read this post. If you are developing a visualization code for your scientific data then you must&lt;/em&gt; &lt;em&gt;&lt;strong&gt;definitely&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;read this blog post (you can also jump straight to the&lt;/em&gt; &lt;a href=&quot;http://nlesc.github.io/spot&quot;&gt;&lt;em&gt;demo&lt;/em&gt;&lt;/a&gt;&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_m1tuq42Vwl4bPaZIZLog0g-55b729d6.DrHryyKI_ZXJw7R.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photography: Elodie Burrillon | &lt;a href=&quot;http://hucopix.com&quot;&gt;http://hucopix.com&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-complex-data-more-to-analyze&quot;&gt;More complex data, more to analyze&lt;/h2&gt;
&lt;p&gt;The amount of the scientific data we were dealing with few decades ago is not even comparable with the data someone uses today while listening to a single song on Spotify (do you remember IBM’s &lt;a href=&quot;http://www-03.ibm.com/ibm/history/ibm100/us/en/icons/ramac/&quot;&gt;RAMAC&lt;/a&gt; with 5 mb of hard drive?).&lt;/p&gt;
&lt;p&gt;Recent developments in the computer world (faster computers, High-performance computing and Cloud systems, GPU computing etc.), faster internet speeds, advanced (big)data processing tools, and the fast adoption of new hardware and sensors (IoT), resulted in having a huge amount of data. We have more information, and more stories to tell about data. However, the data itself does not have any meaning. Researchers need to analyze and summarize their findings in a way that it will be understood easily.&lt;/p&gt;
&lt;p&gt;Imagine a biologist doing research on birds, a physicist searching for new particles, or an artificial intelligence expert working on a new solution to make our lives easier. They all end up with complex data which they need to explain in simple way. A good way to summarize these findings is data visualization.&lt;/p&gt;
&lt;p&gt;Visualization is as important as collecting and analyzing the data. Because, visualization is what one uses to defend an idea or a thesis on particular subject. The presented graphics should be very easy to understand and clearly indicate what one wants to deliver as a message; simple and informative.&lt;/p&gt;
&lt;h2 id=&quot;spot-interactive-responsive-fast-multi-dimensional-scientific-data-visualization&quot;&gt;SPOT: interactive, responsive, fast, multi-dimensional scientific data visualization&lt;/h2&gt;
&lt;p&gt;Most of the scientific data visualization tools require some programming skills or you need to spend a significant amount of time to have a decent plot. Complex data, e.g. multi-dimensional data, requires more complex software to analyze.&lt;/p&gt;
&lt;p&gt;In one of our &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;eScience projects&lt;/a&gt;, the &lt;a href=&quot;https://www.esciencecenter.nl/project/idark&quot;&gt;iDARK&lt;/a&gt; project, we aim to combine the worldwide data within the most general models of Dark Matter. The Dark Matter models will be collected in a database which will be publicly available to researchers. We also make sure to follow &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;FAIR&lt;/a&gt; data principles. The other objective of the project is to develop a visualization tool for Dark Matter models. As the Dark Matter models can have a very high number of variables (more than 100 variables), a visualization tool should be suitable for multi-dimensional data. The database of collected models and the visualization tool will be served at &lt;a href=&quot;http://www.idarksurvey.com/&quot;&gt;http://www.idarksurvey.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a demand for the iDARK project and several other eScience projects, at t &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;he Netherlands eScience Center&lt;/a&gt; we developed a web-based visual data analytics tool to help researchers to interactively produce beautiful charts and to &lt;em&gt;spot&lt;/em&gt; crucial information in your data: &lt;a href=&quot;https://github.com/NLeSC/spot&quot;&gt;&lt;strong&gt;SPOT&lt;/strong&gt;&lt;/a&gt;. We paid special attention during the development SPOT to make it available and useful for as many research areas as possible. As a result, SPOT can be used in other scientific disciplines as well. The workflow of SPOT is shown below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1055&quot; height=&quot;782&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_saMc4m2QUqeh6dpjpjCKLA-495fafb0.Dy3tqAB6_ZW4K0E.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;853&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZKrU1TYC034JaIKdCC33CQ-cbd145a7.bAG6oizQ_13jlUC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Workflow of SPOT.&lt;/p&gt;
&lt;h2 id=&quot;ok-but-why-do-i-need-spot&quot;&gt;OK, but why do I need SPOT?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;A short answer:&lt;/strong&gt; it is easy to use and you can very quickly discover your data &lt;em&gt;without any programming.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A long answer:&lt;/strong&gt; besides producing attractive charts, SPOT has advanced features which can help you to understand your data better. Especially, complex data, e.g. multi-dimensional data, needs more advanced tools for visualization. SPOT can handle this kind of data easily and allows you to explore your data by interacting with it. In other words, it can be used as a data exploration tool. Moreover, if you have more than one dataset, you can connect to a database server and generate your plots. Another bottleneck in data visualization is sharing the produced charts with others. When a plot is shared as an image, no modification can be made. SPOT solves this problem by sharing the dashboard you generate. The plotting session which includes plots, with individual properties, and the data used in plots can be downloaded. This session file can be shared with another user to regenerate the original plots with all the properties.&lt;/p&gt;
&lt;h2 id=&quot;a-closer-look&quot;&gt;A closer look&lt;/h2&gt;
&lt;p&gt;A demo page of SPOT can be accessed at &lt;a href=&quot;https://nlesc-spot.netlify.com/&quot;&gt;http://nlesc.github.io/spot&lt;/a&gt;. When you land to the main page, you will have a dialog to guide you through the interface. We also prepared a tutorial to get you started: &lt;a href=&quot;https://nlesc.github.io/spot-tutorial/tutorial/&quot;&gt;https://nlesc.github.io/spot-tutorial/tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the left hand side you have 3 simple steps which can provide you all the functionalities of SPOT:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Datasets:&lt;/strong&gt; allows you to upload data, connect to a database and configure existing data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analyze:&lt;/strong&gt; this is where you create charts only with mouse clicks and drag &amp;#x26; drop&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Share:&lt;/strong&gt; you can download the charts(and the chart data), or share the complete session with others&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The help button on the bottom left will interactively guide you in each of these pages.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3196&quot; height=&quot;1542&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_HrpKw0q5go8oCvc7i04xtQ-daf48ab0.DL96pEYe_3CLTF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In order to visualize your data, all you need to do is upload your data either in plain CSV file (file with ‘comma separated value’) or JSON (standard Javascript data format) file and a few mouse clicks. Voilà! You have your plots in a decent format already. After that, you can interact with your charts and explore your data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2440&quot; height=&quot;665&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EJd-VBcR7rxCFA7wZ7o7nw-c777b754.Ly5BiImP_1IjsRE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interactive data filtering.&lt;/p&gt;
&lt;h2 id=&quot;a-concise-tour&quot;&gt;A concise tour&lt;/h2&gt;
&lt;p&gt;In order to give you an impression about the user interface and simplicity of visualization process, I will briefly explain you the steps to create plots. You can also try SPOT yourself at the &lt;a href=&quot;https://github.com/NLeSC/spot&quot;&gt;demo page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Datasets page:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Datasets page, you have three options to upload your data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;connect existing database server&lt;/li&gt;
&lt;li&gt;upload a data file in json format&lt;/li&gt;
&lt;li&gt;upload a data file in plain csv file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first option requires a configured database server. The second and the third options are used to upload a file in your computer: just select the file press OK. The file will be uploaded and the content will be scanned, automagically configured by SPOT. If you will be uploading a CSV file, you may need to set options using the gear icon.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;495&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Fs8lNLVk7c0qMFCRTYglZA-1e230556.Dbu-AniE_Z1P47YU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data upload options: connect to a database or upload your own data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;676&quot; height=&quot;277&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MFLOgiZlTHtf2AfUUieZeg-bf20d8d2.D7q_vXO6_HUKzg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is what existing data look like. Only one data is enabled.&lt;/p&gt;
&lt;p&gt;Once you upload data or connect to a database, the existing data will appear in the list. You can enable or disable the data using the switch button. Advanced configuration of each data can be accessed using the gear button.&lt;/p&gt;
&lt;p&gt;Once you have configured your data, you can navigate to the Analyze page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Analyze page:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to create a chart, you can click on one of the 8 chart icons. The cart will be created in the dashboard and settings will be displayed immediately. Simply drag and drop variable(s) to the one of the highlighted boxes in the chart window. Press the gear icon to close settings and view the cart. It is so simple, isn’t it? You can create as many charts as you like. All the charts will be connected to each other (multi-coordinated view). When you apply a filter in one of the charts, the other charts will be updated accordingly. Depending on the chart type, options in the settings view may change. In my next blog post, I will explain how to create more complicated charts and how to interact with them. If you are impatient, please go ahead and try it yourself.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2440&quot; height=&quot;665&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_qxdCcjTagQgnjJwCTSkarQ-77da73d4.DBiWJxby_Z172Dhf.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Share page:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you complete your analysis, you can share your dashboard in this page. You can download the complete session or the data only. This session file can be used to restore the session using &lt;em&gt;upload session&lt;/em&gt; option. Alternatively, you can upload the session to the cloud and share the link. The shared link can be used to load the session using the &lt;em&gt;get session&lt;/em&gt; option.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Cloud sharing uses the&lt;/em&gt; &lt;a href=&quot;https://www.file.io/&quot;&gt;&lt;em&gt;file.io&lt;/em&gt;&lt;/a&gt; &lt;em&gt;service and the link will only be available for 14 days.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;656&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LRHqp-QF7tTWyer2G9AJnw-66f83f6b.DrYOWcG3_1yPWdG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;free-and-open-source&quot;&gt;Free and Open source&lt;/h2&gt;
&lt;p&gt;Unlike most of the data analytics tools, all these features &lt;strong&gt;come at no cost.&lt;/strong&gt; SPOT is a Free and Open Source Software, with a very permissive licence(Apache License 2.0)&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We also have a &lt;a href=&quot;https://github.com/NLeSC/spot-desktop-app/releases/tag/0.1.0&quot;&gt;desktop version of the SPOT&lt;/a&gt; which will allow you to use SPOT as a standalone desktop application.&lt;/p&gt;
&lt;p&gt;Let us know what you think —is it easy to use for you? Do you miss any crucial features? Let us know in the comments below!&lt;/p&gt;</description><pubDate>Tue, 16 Jan 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;If you are using scientific visualization tools in your work then you should read this post. If you are developing a visualization code for your scientific data then you must&lt;/em&gt; &lt;em&gt;&lt;strong&gt;definitely&lt;/strong&gt;&lt;/em&gt; &lt;em&gt;read this blog post (you can also jump straight to the&lt;/em&gt; &lt;a href=&quot;http://nlesc.github.io/spot&quot;&gt;&lt;em&gt;demo&lt;/em&gt;&lt;/a&gt;&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1000&quot; height=&quot;667&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_m1tuq42Vwl4bPaZIZLog0g-55b729d6.DrHryyKI_ZXJw7R.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photography: Elodie Burrillon | &lt;a href=&quot;http://hucopix.com&quot;&gt;http://hucopix.com&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-complex-data-more-to-analyze&quot;&gt;More complex data, more to analyze&lt;/h2&gt;
&lt;p&gt;The amount of the scientific data we were dealing with few decades ago is not even comparable with the data someone uses today while listening to a single song on Spotify (do you remember IBM’s &lt;a href=&quot;http://www-03.ibm.com/ibm/history/ibm100/us/en/icons/ramac/&quot;&gt;RAMAC&lt;/a&gt; with 5 mb of hard drive?).&lt;/p&gt;
&lt;p&gt;Recent developments in the computer world (faster computers, High-performance computing and Cloud systems, GPU computing etc.), faster internet speeds, advanced (big)data processing tools, and the fast adoption of new hardware and sensors (IoT), resulted in having a huge amount of data. We have more information, and more stories to tell about data. However, the data itself does not have any meaning. Researchers need to analyze and summarize their findings in a way that it will be understood easily.&lt;/p&gt;
&lt;p&gt;Imagine a biologist doing research on birds, a physicist searching for new particles, or an artificial intelligence expert working on a new solution to make our lives easier. They all end up with complex data which they need to explain in simple way. A good way to summarize these findings is data visualization.&lt;/p&gt;
&lt;p&gt;Visualization is as important as collecting and analyzing the data. Because, visualization is what one uses to defend an idea or a thesis on particular subject. The presented graphics should be very easy to understand and clearly indicate what one wants to deliver as a message; simple and informative.&lt;/p&gt;
&lt;h2 id=&quot;spot-interactive-responsive-fast-multi-dimensional-scientific-data-visualization&quot;&gt;SPOT: interactive, responsive, fast, multi-dimensional scientific data visualization&lt;/h2&gt;
&lt;p&gt;Most of the scientific data visualization tools require some programming skills or you need to spend a significant amount of time to have a decent plot. Complex data, e.g. multi-dimensional data, requires more complex software to analyze.&lt;/p&gt;
&lt;p&gt;In one of our &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;eScience projects&lt;/a&gt;, the &lt;a href=&quot;https://www.esciencecenter.nl/project/idark&quot;&gt;iDARK&lt;/a&gt; project, we aim to combine the worldwide data within the most general models of Dark Matter. The Dark Matter models will be collected in a database which will be publicly available to researchers. We also make sure to follow &lt;a href=&quot;https://www.nature.com/articles/sdata201618&quot;&gt;FAIR&lt;/a&gt; data principles. The other objective of the project is to develop a visualization tool for Dark Matter models. As the Dark Matter models can have a very high number of variables (more than 100 variables), a visualization tool should be suitable for multi-dimensional data. The database of collected models and the visualization tool will be served at &lt;a href=&quot;http://www.idarksurvey.com/&quot;&gt;http://www.idarksurvey.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As a demand for the iDARK project and several other eScience projects, at t &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;he Netherlands eScience Center&lt;/a&gt; we developed a web-based visual data analytics tool to help researchers to interactively produce beautiful charts and to &lt;em&gt;spot&lt;/em&gt; crucial information in your data: &lt;a href=&quot;https://github.com/NLeSC/spot&quot;&gt;&lt;strong&gt;SPOT&lt;/strong&gt;&lt;/a&gt;. We paid special attention during the development SPOT to make it available and useful for as many research areas as possible. As a result, SPOT can be used in other scientific disciplines as well. The workflow of SPOT is shown below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1055&quot; height=&quot;782&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_saMc4m2QUqeh6dpjpjCKLA-495fafb0.Dy3tqAB6_ZW4K0E.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;853&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZKrU1TYC034JaIKdCC33CQ-cbd145a7.bAG6oizQ_13jlUC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Workflow of SPOT.&lt;/p&gt;
&lt;h2 id=&quot;ok-but-why-do-i-need-spot&quot;&gt;OK, but why do I need SPOT?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;A short answer:&lt;/strong&gt; it is easy to use and you can very quickly discover your data &lt;em&gt;without any programming.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A long answer:&lt;/strong&gt; besides producing attractive charts, SPOT has advanced features which can help you to understand your data better. Especially, complex data, e.g. multi-dimensional data, needs more advanced tools for visualization. SPOT can handle this kind of data easily and allows you to explore your data by interacting with it. In other words, it can be used as a data exploration tool. Moreover, if you have more than one dataset, you can connect to a database server and generate your plots. Another bottleneck in data visualization is sharing the produced charts with others. When a plot is shared as an image, no modification can be made. SPOT solves this problem by sharing the dashboard you generate. The plotting session which includes plots, with individual properties, and the data used in plots can be downloaded. This session file can be shared with another user to regenerate the original plots with all the properties.&lt;/p&gt;
&lt;h2 id=&quot;a-closer-look&quot;&gt;A closer look&lt;/h2&gt;
&lt;p&gt;A demo page of SPOT can be accessed at &lt;a href=&quot;https://nlesc-spot.netlify.com/&quot;&gt;http://nlesc.github.io/spot&lt;/a&gt;. When you land to the main page, you will have a dialog to guide you through the interface. We also prepared a tutorial to get you started: &lt;a href=&quot;https://nlesc.github.io/spot-tutorial/tutorial/&quot;&gt;https://nlesc.github.io/spot-tutorial/tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On the left hand side you have 3 simple steps which can provide you all the functionalities of SPOT:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Datasets:&lt;/strong&gt; allows you to upload data, connect to a database and configure existing data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analyze:&lt;/strong&gt; this is where you create charts only with mouse clicks and drag &amp;#x26; drop&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Share:&lt;/strong&gt; you can download the charts(and the chart data), or share the complete session with others&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The help button on the bottom left will interactively guide you in each of these pages.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3196&quot; height=&quot;1542&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_HrpKw0q5go8oCvc7i04xtQ-daf48ab0.DL96pEYe_3CLTF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In order to visualize your data, all you need to do is upload your data either in plain CSV file (file with ‘comma separated value’) or JSON (standard Javascript data format) file and a few mouse clicks. Voilà! You have your plots in a decent format already. After that, you can interact with your charts and explore your data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2440&quot; height=&quot;665&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EJd-VBcR7rxCFA7wZ7o7nw-c777b754.Ly5BiImP_1IjsRE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Interactive data filtering.&lt;/p&gt;
&lt;h2 id=&quot;a-concise-tour&quot;&gt;A concise tour&lt;/h2&gt;
&lt;p&gt;In order to give you an impression about the user interface and simplicity of visualization process, I will briefly explain you the steps to create plots. You can also try SPOT yourself at the &lt;a href=&quot;https://github.com/NLeSC/spot&quot;&gt;demo page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Datasets page:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Datasets page, you have three options to upload your data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;connect existing database server&lt;/li&gt;
&lt;li&gt;upload a data file in json format&lt;/li&gt;
&lt;li&gt;upload a data file in plain csv file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first option requires a configured database server. The second and the third options are used to upload a file in your computer: just select the file press OK. The file will be uploaded and the content will be scanned, automagically configured by SPOT. If you will be uploading a CSV file, you may need to set options using the gear icon.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;495&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Fs8lNLVk7c0qMFCRTYglZA-1e230556.Dbu-AniE_Z1P47YU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Data upload options: connect to a database or upload your own data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;676&quot; height=&quot;277&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_MFLOgiZlTHtf2AfUUieZeg-bf20d8d2.D7q_vXO6_HUKzg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is what existing data look like. Only one data is enabled.&lt;/p&gt;
&lt;p&gt;Once you upload data or connect to a database, the existing data will appear in the list. You can enable or disable the data using the switch button. Advanced configuration of each data can be accessed using the gear button.&lt;/p&gt;
&lt;p&gt;Once you have configured your data, you can navigate to the Analyze page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Analyze page:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In order to create a chart, you can click on one of the 8 chart icons. The cart will be created in the dashboard and settings will be displayed immediately. Simply drag and drop variable(s) to the one of the highlighted boxes in the chart window. Press the gear icon to close settings and view the cart. It is so simple, isn’t it? You can create as many charts as you like. All the charts will be connected to each other (multi-coordinated view). When you apply a filter in one of the charts, the other charts will be updated accordingly. Depending on the chart type, options in the settings view may change. In my next blog post, I will explain how to create more complicated charts and how to interact with them. If you are impatient, please go ahead and try it yourself.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2440&quot; height=&quot;665&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_qxdCcjTagQgnjJwCTSkarQ-77da73d4.DBiWJxby_Z172Dhf.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Share page:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you complete your analysis, you can share your dashboard in this page. You can download the complete session or the data only. This session file can be used to restore the session using &lt;em&gt;upload session&lt;/em&gt; option. Alternatively, you can upload the session to the cloud and share the link. The shared link can be used to load the session using the &lt;em&gt;get session&lt;/em&gt; option.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: Cloud sharing uses the&lt;/em&gt; &lt;a href=&quot;https://www.file.io/&quot;&gt;&lt;em&gt;file.io&lt;/em&gt;&lt;/a&gt; &lt;em&gt;service and the link will only be available for 14 days.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;656&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LRHqp-QF7tTWyer2G9AJnw-66f83f6b.DrYOWcG3_1yPWdG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;free-and-open-source&quot;&gt;Free and Open source&lt;/h2&gt;
&lt;p&gt;Unlike most of the data analytics tools, all these features &lt;strong&gt;come at no cost.&lt;/strong&gt; SPOT is a Free and Open Source Software, with a very permissive licence(Apache License 2.0)&lt;strong&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We also have a &lt;a href=&quot;https://github.com/NLeSC/spot-desktop-app/releases/tag/0.1.0&quot;&gt;desktop version of the SPOT&lt;/a&gt; which will allow you to use SPOT as a standalone desktop application.&lt;/p&gt;
&lt;p&gt;Let us know what you think —is it easy to use for you? Do you miss any crucial features? Let us know in the comments below!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_saMc4m2QUqeh6dpjpjCKLA-495fafb0.Dy3tqAB6.png" medium="image"/><author>Faruk Diblen</author></item><item><title>digital technologies to analyze eyewitness accounts of mass violence</title><link>https://blog2.esciencecenter.nl/posts/2017-12-20---digital-technologies-to-analyze-eyewitness-accounts-of-mass-violence</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-12-20---digital-technologies-to-analyze-eyewitness-accounts-of-mass-violence</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-YDWQk9Mzv_xb9zkY6XZVA-92746fca.1NeKo-ky_2gPsvB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Susan Hogervorst, historian, assistant professor in historical culture and history didactics, Open University of the Netherlands, and researcher at Erasmus University Rotterdam&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon |&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In 2017, Susan Hogervorst (Open University of the Netherlands) received a &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;grant&lt;/a&gt; and in-kind expertise from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; for her project &lt;a href=&quot;https://www.esciencecenter.nl/project/evidence&quot;&gt;EviDENce&lt;/a&gt;. Much of our historical knowledge is based on oral or written accounts of eyewitnesses, particularly in cases of war and mass violence, when regular ways of documentation and record keeping are often absent. EviDENce explores new ways of analyzing and contextualizing historical sources by applying event modelling and semantic web technologies.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QLjAXK6hWYE9hLf3pZHFfA-fa06635e.B0E5Xaqj_151iaA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-meta-perspective-on-history&quot;&gt;A meta-perspective on history&lt;/h3&gt;
&lt;p&gt;“Historical culture refers to all the ways individuals and societies deal and engage with the past. I wrote my dissertation on memory cultures of concentration camp Ravensbrück in Europe, 1945–2010. I studied (mostly unofficial, private) archives of associations of Ravensbrück survivors from different countries, to examine what story about that camp they had developed and made public after 1945, and how this story related to other representations about Ravensbruck — of historians, artists, journalists, politicians, and so on. In a sense, it was about reconstructing the process of production, circulation and competition of knowledge about the past in this case Ravensbrück, that was either derived from personal experience, or from other sources. I continued studying historical culture, for example for a book I co-authored about the Rotterdam bombing raid in public memory, which was published in 2015 at the commemoration of the bombardment, then 75 years ago.”&lt;/p&gt;
&lt;p&gt;“Many people are interested in history. And especially in case of contemporary history, many people have historical knowledge based on personal experience, family stories, or otherwise. I find it important to take on a meta-perspective, especially regarding contemporary history, in which much has not yet been crystalized, and let people look differently to what they (think they) already know.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fB_fenEv0EvwTXzPS3nnGQ-0266d3d8.De2Ph4Ne_O5POx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-cultural-function-of-eyewitnesses&quot;&gt;The cultural function of eyewitnesses&lt;/h3&gt;
&lt;p&gt;“During the last couple of years, I got more and more interested in the eyewitness, both as a source of historical knowledge, and as a cultural figure. Since the 1960s, Holocaust survivors emerged as witnesses and bearers of memory. They appeared in the media, in educational settings, and were important in political debates. Since the 1980s, public memory of WW2 has been characterized by a sense of loss, as well as urgency, regarding the upcoming disappearance of the eyewitness generations. It is important to reflect on the cultural functions of eyewitnesses, and the meanings that different audiences ascribe to them. What will be lost, exactly, and for whom? What kind of knowledge about the past do eyewitnesses produce? How did this change over time and under which conditions? And how have eyewitnesses of important historical events been perceived by the public, and by historians?”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Y0rq7AVW-K4kBqmpY9vYig-3ec0a78c.qqMPSF0X_aKb93.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;turning-to-digital-humanities&quot;&gt;Turning to digital humanities&lt;/h3&gt;
&lt;p&gt;“In a current &lt;a href=&quot;https://www.eshcc.eur.nl/english/rei/&quot;&gt;project at Erasmus University Rotterdam&lt;/a&gt;, I examine the use of digital collections of video interviews with eyewitnesses of war, in museums, in education, and online. I recently turned to digital humanities to address these kinds of questions in a different way. In a &lt;a href=&quot;https://www.clariah.nl/projecten/research-pilots/crossewt/crossewt&quot;&gt;CLARIAH Research Pilot project&lt;/a&gt;, I automatically investigate and compare the changing content of oral history interviews with WW2 eyewitnesses, newspaper articles with WW2 eyewitness interviews, and radio and TV programs with WW2 eyewitnesses since 1945.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ik0YjJ6mBh-5PaGj-bVvDQ-1ae2704a.BPm9IKv7_Z20Ey7c.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-new-perspective-on-the-fundamentals-of-historical-research&quot;&gt;A new perspective on the fundamentals of historical research&lt;/h3&gt;
&lt;p&gt;“ Now, in our collaboration with the eScience Center and the KNAW Humanities Cluster that recently started, I have the chance to expand these questions in multiple ways: regarding topics, research period, as well as methodology. We will try to examine the representation of war and violence in Dutch ego-documents over a period of no less than 5 centuries. Ego-documents is the umbrella term for all writings about the self, like diaries, letters, autobiographies, and memoirs. We use digitized eco-documents from both Netwerk Oorlogsbronnen as well as from the Meertens Institute &lt;a href=&quot;http://www.nederlab.nl/&quot;&gt;Nederlab infrastructure&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sOhqP1QP1yuq_BicHReFNA-6c149094.zO0cKfdD_H3eyT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Apart from discovering new things, and working together with colleagues from different disciplines, for me the most exciting aspect of digital humanities research is to contribute to developing (and sharing) a new perspective on the fundamentals of historical research.”&lt;/p&gt;
&lt;h3 id=&quot;collaborating-with-escience-research-engineers&quot;&gt;Collaborating with eScience Research Engineers&lt;/h3&gt;
&lt;p&gt;“By collaborating with eScience Research Engineers we want to develop a method that automatically extracts concepts and context information from large historical text corpora. Concepts like “oppression” or “terror”, that describe how individuals experienced violent events. Currently, historical researchers find their sources by searching for specific keywords, or by filtering on document types or time periods. The software tools they use are mainly relying on literally recognizing (sequences of) words. But in many of these documents the concepts they are looking for are described using different wording, or are only implicitly mentioned in the text. We believe that enriching the documents with descriptions such as “violent” or “first-hand experience” would enable researchers to more efficiently find relevant sources, and process more material.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0YLvXWxv6pfotbKLuZUk4Q-6d0fcae8.B9Qx50ou_Z1I2hY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineers Wouter Kouw (left) and Martine de Vos (center)&lt;/p&gt;
&lt;h3 id=&quot;combining-semantic-web-technology-and-machine-learning&quot;&gt;Combining semantic web technology and machine learning&lt;/h3&gt;
&lt;p&gt;“eScience Research Engineer Martine de Vos has expertise in semantic web technologies. The semantic web (the web of linked data) contains lots of shared vocabularies with knowledge on persons, locations and events. Labeling the text in historical documents with concepts from these shared vocabularies — a process called annotation — adds context and meaning to it. This would help us to collect and analyze information from historical documents, automatically and in a meaningful way. Even more, annotation with vocabulary concepts enables linking of these documents with datasets elsewhere on the semantic web that are on the same concepts.”&lt;/p&gt;
&lt;p&gt;“eSience Research Engineer Wouter Kouw is an expert in machine learning — teaching computer systems to perform tasks. Using annotated historical documents as examples, we should be able to train a system that automatically detects persons, locations and events in new documents, that have not been annotated. We could use additional information from the semantic web to improve the system’s performance. For example, since we are specifically focusing on violent events, we could cross-reference the concept ‘raid’ with the WO2 thesaurus to determine that this is “an act by a controlling force on the populace” and therefore constitutes a violent event.”&lt;/p&gt;
&lt;h3 id=&quot;three-years-from-now&quot;&gt;Three years from now&lt;/h3&gt;
&lt;p&gt;“Three years from now we hope we can make empirically sustained statements about the ways past eyewitnesses have described violent events, and how this has developed over time. On a methodological level, we hope to have a thorough use case about how event modeling can help detecting relevant indicators for historical phenomena or concepts in text corpora that can hardly be translated into search terms. If this succeeds, we might have a way to analyze large text corpora in a way that is meaningful to me and other humanities scholars.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8MVQ0g9cPQOgKxR9KoLtNw-3ef744a0.Cb--sA3E_1lvo8x.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Project EviDENce team members. From left to right: Jeroen Willemsen, Marieke van Erp, Susan Hogervorst, Martine de Vos, Wouter Kouw&lt;/p&gt;</description><pubDate>Wed, 20 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-YDWQk9Mzv_xb9zkY6XZVA-92746fca.1NeKo-ky_2gPsvB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Dr. Susan Hogervorst, historian, assistant professor in historical culture and history didactics, Open University of the Netherlands, and researcher at Erasmus University Rotterdam&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon |&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In 2017, Susan Hogervorst (Open University of the Netherlands) received a &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;grant&lt;/a&gt; and in-kind expertise from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; for her project &lt;a href=&quot;https://www.esciencecenter.nl/project/evidence&quot;&gt;EviDENce&lt;/a&gt;. Much of our historical knowledge is based on oral or written accounts of eyewitnesses, particularly in cases of war and mass violence, when regular ways of documentation and record keeping are often absent. EviDENce explores new ways of analyzing and contextualizing historical sources by applying event modelling and semantic web technologies.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QLjAXK6hWYE9hLf3pZHFfA-fa06635e.B0E5Xaqj_151iaA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-meta-perspective-on-history&quot;&gt;A meta-perspective on history&lt;/h3&gt;
&lt;p&gt;“Historical culture refers to all the ways individuals and societies deal and engage with the past. I wrote my dissertation on memory cultures of concentration camp Ravensbrück in Europe, 1945–2010. I studied (mostly unofficial, private) archives of associations of Ravensbrück survivors from different countries, to examine what story about that camp they had developed and made public after 1945, and how this story related to other representations about Ravensbruck — of historians, artists, journalists, politicians, and so on. In a sense, it was about reconstructing the process of production, circulation and competition of knowledge about the past in this case Ravensbrück, that was either derived from personal experience, or from other sources. I continued studying historical culture, for example for a book I co-authored about the Rotterdam bombing raid in public memory, which was published in 2015 at the commemoration of the bombardment, then 75 years ago.”&lt;/p&gt;
&lt;p&gt;“Many people are interested in history. And especially in case of contemporary history, many people have historical knowledge based on personal experience, family stories, or otherwise. I find it important to take on a meta-perspective, especially regarding contemporary history, in which much has not yet been crystalized, and let people look differently to what they (think they) already know.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fB_fenEv0EvwTXzPS3nnGQ-0266d3d8.De2Ph4Ne_O5POx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-cultural-function-of-eyewitnesses&quot;&gt;The cultural function of eyewitnesses&lt;/h3&gt;
&lt;p&gt;“During the last couple of years, I got more and more interested in the eyewitness, both as a source of historical knowledge, and as a cultural figure. Since the 1960s, Holocaust survivors emerged as witnesses and bearers of memory. They appeared in the media, in educational settings, and were important in political debates. Since the 1980s, public memory of WW2 has been characterized by a sense of loss, as well as urgency, regarding the upcoming disappearance of the eyewitness generations. It is important to reflect on the cultural functions of eyewitnesses, and the meanings that different audiences ascribe to them. What will be lost, exactly, and for whom? What kind of knowledge about the past do eyewitnesses produce? How did this change over time and under which conditions? And how have eyewitnesses of important historical events been perceived by the public, and by historians?”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Y0rq7AVW-K4kBqmpY9vYig-3ec0a78c.qqMPSF0X_aKb93.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;turning-to-digital-humanities&quot;&gt;Turning to digital humanities&lt;/h3&gt;
&lt;p&gt;“In a current &lt;a href=&quot;https://www.eshcc.eur.nl/english/rei/&quot;&gt;project at Erasmus University Rotterdam&lt;/a&gt;, I examine the use of digital collections of video interviews with eyewitnesses of war, in museums, in education, and online. I recently turned to digital humanities to address these kinds of questions in a different way. In a &lt;a href=&quot;https://www.clariah.nl/projecten/research-pilots/crossewt/crossewt&quot;&gt;CLARIAH Research Pilot project&lt;/a&gt;, I automatically investigate and compare the changing content of oral history interviews with WW2 eyewitnesses, newspaper articles with WW2 eyewitness interviews, and radio and TV programs with WW2 eyewitnesses since 1945.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ik0YjJ6mBh-5PaGj-bVvDQ-1ae2704a.BPm9IKv7_Z20Ey7c.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-new-perspective-on-the-fundamentals-of-historical-research&quot;&gt;A new perspective on the fundamentals of historical research&lt;/h3&gt;
&lt;p&gt;“ Now, in our collaboration with the eScience Center and the KNAW Humanities Cluster that recently started, I have the chance to expand these questions in multiple ways: regarding topics, research period, as well as methodology. We will try to examine the representation of war and violence in Dutch ego-documents over a period of no less than 5 centuries. Ego-documents is the umbrella term for all writings about the self, like diaries, letters, autobiographies, and memoirs. We use digitized eco-documents from both Netwerk Oorlogsbronnen as well as from the Meertens Institute &lt;a href=&quot;http://www.nederlab.nl/&quot;&gt;Nederlab infrastructure&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sOhqP1QP1yuq_BicHReFNA-6c149094.zO0cKfdD_H3eyT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Apart from discovering new things, and working together with colleagues from different disciplines, for me the most exciting aspect of digital humanities research is to contribute to developing (and sharing) a new perspective on the fundamentals of historical research.”&lt;/p&gt;
&lt;h3 id=&quot;collaborating-with-escience-research-engineers&quot;&gt;Collaborating with eScience Research Engineers&lt;/h3&gt;
&lt;p&gt;“By collaborating with eScience Research Engineers we want to develop a method that automatically extracts concepts and context information from large historical text corpora. Concepts like “oppression” or “terror”, that describe how individuals experienced violent events. Currently, historical researchers find their sources by searching for specific keywords, or by filtering on document types or time periods. The software tools they use are mainly relying on literally recognizing (sequences of) words. But in many of these documents the concepts they are looking for are described using different wording, or are only implicitly mentioned in the text. We believe that enriching the documents with descriptions such as “violent” or “first-hand experience” would enable researchers to more efficiently find relevant sources, and process more material.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0YLvXWxv6pfotbKLuZUk4Q-6d0fcae8.B9Qx50ou_Z1I2hY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineers Wouter Kouw (left) and Martine de Vos (center)&lt;/p&gt;
&lt;h3 id=&quot;combining-semantic-web-technology-and-machine-learning&quot;&gt;Combining semantic web technology and machine learning&lt;/h3&gt;
&lt;p&gt;“eScience Research Engineer Martine de Vos has expertise in semantic web technologies. The semantic web (the web of linked data) contains lots of shared vocabularies with knowledge on persons, locations and events. Labeling the text in historical documents with concepts from these shared vocabularies — a process called annotation — adds context and meaning to it. This would help us to collect and analyze information from historical documents, automatically and in a meaningful way. Even more, annotation with vocabulary concepts enables linking of these documents with datasets elsewhere on the semantic web that are on the same concepts.”&lt;/p&gt;
&lt;p&gt;“eSience Research Engineer Wouter Kouw is an expert in machine learning — teaching computer systems to perform tasks. Using annotated historical documents as examples, we should be able to train a system that automatically detects persons, locations and events in new documents, that have not been annotated. We could use additional information from the semantic web to improve the system’s performance. For example, since we are specifically focusing on violent events, we could cross-reference the concept ‘raid’ with the WO2 thesaurus to determine that this is “an act by a controlling force on the populace” and therefore constitutes a violent event.”&lt;/p&gt;
&lt;h3 id=&quot;three-years-from-now&quot;&gt;Three years from now&lt;/h3&gt;
&lt;p&gt;“Three years from now we hope we can make empirically sustained statements about the ways past eyewitnesses have described violent events, and how this has developed over time. On a methodological level, we hope to have a thorough use case about how event modeling can help detecting relevant indicators for historical phenomena or concepts in text corpora that can hardly be translated into search terms. If this succeeds, we might have a way to analyze large text corpora in a way that is meaningful to me and other humanities scholars.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8MVQ0g9cPQOgKxR9KoLtNw-3ef744a0.Cb--sA3E_1lvo8x.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Project EviDENce team members. From left to right: Jeroen Willemsen, Marieke van Erp, Susan Hogervorst, Martine de Vos, Wouter Kouw&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_QLjAXK6hWYE9hLf3pZHFfA-fa06635e.B0E5Xaqj.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>escience is about being bold enough to ask the right questions at the right time</title><link>https://blog2.esciencecenter.nl/posts/2017-12-20---escience-is-about-being-bold-enough-to-ask-the-right-questions-at-the-right-time</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-12-20---escience-is-about-being-bold-enough-to-ask-the-right-questions-at-the-right-time</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iKLnA1ZxrXtILMGgGC-yZA-93ca433e.c5WyVJWC_ZUfiIr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The 2017 eScience Principal Investigator Day. Photography: Elodie Burrillon/HUCOPIX&lt;/p&gt;
&lt;p&gt;Almost three years ago, I started working at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and I have gradually come to a better understanding of what the job of an eScience Research Engineer involves. The bottom line is that coding is the least time consuming part of my work. I’ll quickly list my job activities to clarify the main misconception.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The most important aspect of my work is being bold enough to ask the right questions at the right time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once a proposal is granted, a kick-off meeting is held and after that the actual work begins. During that first phase of the project the engineers have a first look at the code, compile it and run it. The engineers are usually confronted with a lot of aspects of the code that they cannot immediately fully comprehend, they have to work their way through it. This can be done either by trying to understand the most accessible or top level parts of the code or by producing a call graph depicting the interdependencies of the different modules comprising the software package. For an efficient-computing project the engineer will profile the code to gain insight into the main bottlenecks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3HGsC-COahd88l_jDPyWVw-8a624840.BLODd0b3_1GaeyK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineer Dafne van Kuppevelt discussing with Gijs van Dijck, Professor of Private Law at Maastricht University. Photography: Elodie Burrillon/HUCOPIX&lt;/p&gt;
&lt;p&gt;But, guess what, during the next phase, which is the main phase of the project, the targets as described in the proposal may look only remotely achievable, obsolete, or less interesting than other research questions that came up. In other words, the project’s goals are moving targets and we continuously need to redefine our priorities. This occurs, of course, quite commonly when running any complex project. Hence, soon after a project starts, we need to evaluate, talk, discuss. Here are some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Asking the right questions at the right time&lt;/strong&gt;: “Is this feasible within the allocated time?”, “Why do you want to do this?”, “I do not understand this.”, “I do not see how this work relates to the project goals.” and “Why do you want me to maintain this software package? Better versions of it have been developed and maintained by a large user community and are freely available”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sparring with the Principal Investigator (P.I.).&lt;/strong&gt; The P.I. has written the proposal, but it is not set in stone. It may not be recommendable to pursue every aspect of the proposal. During the course of the project, insights or flaws emerge that require measures. For example, the lateral impact of the software — the extent to which the use of the software will transcend the domain of the P.I. — may be compromised if the original proposal would be continued rigidly. In this case, meetings with the P.I. are required to guarantee the lateral impact of the software we develop.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Sz37ESqssS0LQa7hn2JDYw-8151848d.C_3WdXWh_Z2xAsN.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;eScience Research Engineer Arnold Kuzniar discussing with Jeroen de Ridder, Associate Professor at University Medical Center Utrecht. Photography: Elodie Burrillon/HUCOPIX&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Continuous discussion with all stakeholders is essential&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For eScience (or software) projects there is another aspect that involves a lot of communication: software design. We cannot define a software architecture without numerous discussions with all stakeholders. We need to know about the software requirements, the users, the interactions between the users and the software, its maintainability and interoperability. We need to keep a record of the outcome of all these discussions; they will turn out to be indispensable.&lt;/p&gt;
&lt;p&gt;Of course, eScience Research Engineers are also programmers. One part of that is the coding of algorithms; this is mostly an individual activity. More time-consuming parts, however, are tasks related to programming, but at a meta-level. It involves taking care of software portability and sustainability, writing unit tests and documentation and implementing version control and continuous integration. These are tasks that we mostly not perform invidually, but in collaboration with other project team members, such as the P.I.&lt;/p&gt;
&lt;p&gt;Now that you have worked your way through this blog, look at all of the above. It is a lot about talking, right? About clear communication, difficult conversations and being open about the problems that you are facing, the doubts you have: is this going to work, is this feasible? For me, being an eScience Research Engineer, &lt;strong&gt;the most important aspect of my work is being bold enough to ask the right questions at the right time&lt;/strong&gt;.&lt;/p&gt;</description><pubDate>Wed, 20 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_iKLnA1ZxrXtILMGgGC-yZA-93ca433e.c5WyVJWC_ZUfiIr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The 2017 eScience Principal Investigator Day. Photography: Elodie Burrillon/HUCOPIX&lt;/p&gt;
&lt;p&gt;Almost three years ago, I started working at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; and I have gradually come to a better understanding of what the job of an eScience Research Engineer involves. The bottom line is that coding is the least time consuming part of my work. I’ll quickly list my job activities to clarify the main misconception.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The most important aspect of my work is being bold enough to ask the right questions at the right time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once a proposal is granted, a kick-off meeting is held and after that the actual work begins. During that first phase of the project the engineers have a first look at the code, compile it and run it. The engineers are usually confronted with a lot of aspects of the code that they cannot immediately fully comprehend, they have to work their way through it. This can be done either by trying to understand the most accessible or top level parts of the code or by producing a call graph depicting the interdependencies of the different modules comprising the software package. For an efficient-computing project the engineer will profile the code to gain insight into the main bottlenecks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3HGsC-COahd88l_jDPyWVw-8a624840.BLODd0b3_1GaeyK.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineer Dafne van Kuppevelt discussing with Gijs van Dijck, Professor of Private Law at Maastricht University. Photography: Elodie Burrillon/HUCOPIX&lt;/p&gt;
&lt;p&gt;But, guess what, during the next phase, which is the main phase of the project, the targets as described in the proposal may look only remotely achievable, obsolete, or less interesting than other research questions that came up. In other words, the project’s goals are moving targets and we continuously need to redefine our priorities. This occurs, of course, quite commonly when running any complex project. Hence, soon after a project starts, we need to evaluate, talk, discuss. Here are some examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Asking the right questions at the right time&lt;/strong&gt;: “Is this feasible within the allocated time?”, “Why do you want to do this?”, “I do not understand this.”, “I do not see how this work relates to the project goals.” and “Why do you want me to maintain this software package? Better versions of it have been developed and maintained by a large user community and are freely available”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sparring with the Principal Investigator (P.I.).&lt;/strong&gt; The P.I. has written the proposal, but it is not set in stone. It may not be recommendable to pursue every aspect of the proposal. During the course of the project, insights or flaws emerge that require measures. For example, the lateral impact of the software — the extent to which the use of the software will transcend the domain of the P.I. — may be compromised if the original proposal would be continued rigidly. In this case, meetings with the P.I. are required to guarantee the lateral impact of the software we develop.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Sz37ESqssS0LQa7hn2JDYw-8151848d.C_3WdXWh_Z2xAsN.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;eScience Research Engineer Arnold Kuzniar discussing with Jeroen de Ridder, Associate Professor at University Medical Center Utrecht. Photography: Elodie Burrillon/HUCOPIX&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Continuous discussion with all stakeholders is essential&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For eScience (or software) projects there is another aspect that involves a lot of communication: software design. We cannot define a software architecture without numerous discussions with all stakeholders. We need to know about the software requirements, the users, the interactions between the users and the software, its maintainability and interoperability. We need to keep a record of the outcome of all these discussions; they will turn out to be indispensable.&lt;/p&gt;
&lt;p&gt;Of course, eScience Research Engineers are also programmers. One part of that is the coding of algorithms; this is mostly an individual activity. More time-consuming parts, however, are tasks related to programming, but at a meta-level. It involves taking care of software portability and sustainability, writing unit tests and documentation and implementing version control and continuous integration. These are tasks that we mostly not perform invidually, but in collaboration with other project team members, such as the P.I.&lt;/p&gt;
&lt;p&gt;Now that you have worked your way through this blog, look at all of the above. It is a lot about talking, right? About clear communication, difficult conversations and being open about the problems that you are facing, the doubts you have: is this going to work, is this feasible? For me, being an eScience Research Engineer, &lt;strong&gt;the most important aspect of my work is being bold enough to ask the right questions at the right time&lt;/strong&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_3HGsC-COahd88l_jDPyWVw-8a624840.BLODd0b3.jpeg" medium="image"/><author>Hanno Spreeuw</author></item><item><title>introducing nl-rse</title><link>https://blog2.esciencecenter.nl/posts/2017-12-20---introducing-nl-rse</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-12-20---introducing-nl-rse</guid><description>&lt;p&gt;&lt;em&gt;Bootstrapping the community of Research Software Engineers in the Netherlands.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LmBD9OaRAJPnBYBoZwyZMw-68abbf5d.Caekald3_DjFB9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Research software has become an indispensable instrument for virtually every academic researcher. A case in point: &lt;a href=&quot;http://dx.doi.org/10.5281/zenodo.14809&quot;&gt;survey data&lt;/a&gt; from the UK revealed that 92% of academics use research software, 69% say that their research would not be practical without it and 56% develop their own software. Creating, storing and analyzing data is crucial in researchers’ daily work and enables them to address increasingly challenging research questions.&lt;/p&gt;
&lt;p&gt;This rapid digitization of research has strongly increased the number of people writing and contributing to research software. This is part of a more general trend, where positions like &lt;a href=&quot;https://www.tudelft.nl/en/library/theme-portals/research-data-management/research-data-management/data-stewardship/&quot;&gt;&lt;em&gt;data stewards&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;information managers&lt;/em&gt;, research data officer, &lt;em&gt;research supporter&lt;/em&gt; and other non-traditional research positions are becoming increasingly recognized as intrinsic positions in the academic research ecosystem. To increase the impact, recognition and visibility of research software in academia, we (&lt;a href=&quot;https://escience-platform.nl/&quot;&gt;ePlan&lt;/a&gt; and the Netherlands eScience Center) have taken the initiative to start and support the community of professionals &lt;em&gt;behind&lt;/em&gt; the software: the Netherlands Research Software Engineers community: &lt;a href=&quot;http://nl-rse.org/&quot;&gt;NL-RSE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The goal of the NL-RSE community fits with the broader national and international open science movement. For example in the Dutch &lt;a href=&quot;https://www.openscience.nl/en/&quot;&gt;National Platform Open Science&lt;/a&gt; and the &lt;a href=&quot;http://ec.europa.eu/research/openscience/index.cfm?pg=open-science-cloud&quot;&gt;European Open Science Cloud&lt;/a&gt; and &lt;a href=&quot;https://www.go-fair.org/&quot;&gt;GO-FAIR&lt;/a&gt;, there is a strong focus on new and digital technologies — &lt;em&gt;including software&lt;/em&gt; — to make research data, methods and outcomes more accessible and better reusable.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;677&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Do0XW7EAl1W5p5L9iuE6lQ-6ae25899.DFqxUYbS_gHx37.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://nl-rse.org/&quot;&gt;http://nl-rse.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NL-RSE is an open community for all people who as (part of) their job are writing software, regardless of the academic discipline or research area. Being member of the community allows research software engineers in the Netherlands to share knowledge, to initiate collaborations and to offer and ask support from other engineers in the Netherlands.&lt;/p&gt;
&lt;h2 id=&quot;tldr-version-of-this-blogpost&quot;&gt;TL;DR version of this blogpost&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sign up to the NL-RSE community &lt;a href=&quot;https://lists.nl-rse.org/mailman/listinfo/everyone&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fill in our survey here (edit — the survey was held in December 2017 and is now closed. We will soon publishing a link to the results)&lt;/li&gt;
&lt;li&gt;Visit the &lt;a href=&quot;http://nl-rse.org/&quot;&gt;website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Get in touch here: &lt;a href=&quot;mailto:info@nl-rse.org&quot;&gt;info@nl-rse.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://dirkgorissen.com/2012/03/26/the-researcher-programmer-a-new-species/&quot;&gt;Dirk Gorissen&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-dutch-guild-of-research-software-engineers&quot;&gt;The Dutch guild of Research Software Engineers&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_cSXU4CeixL3HnY9LBOTXeQ-5626ba8d.CUPAK4bi_2rMAVl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Research software has become an indispensable instrument for virtually every academic researcher&lt;/p&gt;
&lt;p&gt;The increasing reliance on and use of data and digital techniques in academia has led to an ever increasing amount of research software at the very core of the science done. The emergence of research software has gone hand in hand with a strong growth in people who actually &lt;em&gt;develop&lt;/em&gt; research software. Today, the UK at least counts more than &lt;a href=&quot;http://rse.ac.uk/&quot;&gt;800&lt;/a&gt; of professionals who identify as developers of software for research purposes. But for the Netherlands, we don’t know. Sure, we know that there are at least &lt;a href=&quot;https://www.esciencecenter.nl/people&quot;&gt;40 people&lt;/a&gt; actively developing and applying research software in close collaboration with university researchers. But there are many more people throughout the country working on software, managing data, and supporting digital research, distributed over various research institutes, universities, and other knowledge organizations.&lt;/p&gt;
&lt;p&gt;To strengthen the various communities and to increase interaction between them, we have taken the initiative to start the Research Software Engineer (RSE) community in the Netherlands. It is inspired by the successful &lt;a href=&quot;http://rse.ac.uk/&quot;&gt;UK-RSE Association&lt;/a&gt;, as well as the inspirational visits to the &lt;em&gt;First conference of Research Software Engineers&lt;/em&gt; in 2016, events organized by the Software Sustainability Institute, and encounters with UK-RSE and &lt;a href=&quot;http://www.de-rse.org/&quot;&gt;DE-RSE&lt;/a&gt; members.&lt;/p&gt;
&lt;h2 id=&quot;why-the-term-research-software-engineer-rse&quot;&gt;Why the term Research Software Engineer (RSE)?&lt;/h2&gt;
&lt;p&gt;Without a name, it is difficult to refer to a group of people that share a set of skills and characteristics. A name must be descriptive, yet short enough to be meaningful. It must differentiate and be acceptable to both the people who identify with it and the academic community. In 2012, when trying to form a community of people working on software in academia in the UK, a lot of thought and discussion went into what term to use. Eventually, the new name was created by fusing the two skills that make it unique: an understanding of both research &lt;em&gt;and&lt;/em&gt; software engineering. Quoting from the paper that marked the start of the Research Software Engineer community in the UK:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Research institutions need individuals with a new professional designation — the research software engineer. These individuals combine a professional attitude to the exercise of software engineering with a deep understanding of research topics. They lead the design and construction of increasingly complex research software systems, and play an important part in the co-design of research requirements, understanding and addressing software engineering questions that arise in research planning.&lt;/em&gt; [&lt;a href=&quot;http://digital-research-2012.oerc.ox.ac.uk/papers/the-research-software-engineer/at_download/file&quot;&gt;Baxter et al., 2012&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;936&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XWCrOtVijQ8gqcEWKuWMBA-2766622b.rhVz23DQ_NFpx6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;RSEs are often embedded in research groups in small teams, or even by themselves, working hard on the software, algorithms, tools and interfaces that facilitate cutting-edge research. And in many cases, they are academic researchers at the same time, holding positions as (assistant/associate) professor, postdoc or PhD candidate. RSEs closely collaborate with researchers to understand the challenges they face, and then develop research software to provide the answers. Some have started as researchers who spent a lot of time developing software to do their research. Others have started as software developers who have developed a strong affinity with scientific research.&lt;/p&gt;
&lt;h2 id=&quot;building-the-community&quot;&gt;Building the Community&lt;/h2&gt;
&lt;p&gt;Early 2017, ePlan and the eScience Center took the first steps to found NL-RSE. While we hope that the community will run independently at some point, for the time being a few enthusiastic organizations and partner organizations will take care of NL-RSE best we can. Upon learning of our plans, a number of organizations and individuals have already confirmed their interest in supporting NL-RSE. We are very happy to be joined by DTL in setting up NL-RSE, and hope others will follow. Be sure to send us an e-mail (&lt;a href=&quot;mailto:info@nl-rse.org&quot;&gt;info@nl-rse.org&lt;/a&gt;) if you are interested in supporting NL-RSE!&lt;/p&gt;
&lt;p&gt;Although supported by a number of organizations, the NL-RSE community consists of individuals self-identifying as Research Software Engineers. We feel this is the only way to truly build a community.&lt;/p&gt;
&lt;p&gt;The centrepiece of the community is the mailing list. Rather than a newsletter governed by a communication department, any member can send messages to the entire community to make announcements. We also have created a &lt;a href=&quot;https://nl-rse.slack.com/&quot;&gt;Slack Group&lt;/a&gt; for discussions, and a &lt;a href=&quot;http://nl-rse.org/&quot;&gt;website&lt;/a&gt; with information.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;300&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5xwpuYVUP73eMdxb7g5dyg-a7065dc6.BbhHbhLw_Z10GHFw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Better software better research” — slogan by the Software Sustainability Institute in the UK. &lt;a href=&quot;https://software.ac.uk/about&quot;&gt;https://software.ac.uk/about&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The main goal of NL-RSE is to build a community of Research Software Engineers in the Netherlands, build best practices, and learn from each other. Note that NL-RSE is about engineering of research software, rather than research on software engineering, a subtle but crucial difference with the computer science field of software engineering. We also hope to raise awareness of the importance of software in research, and the vital role RSEs play in creating this software. Besides an online presence, we plan to also hold irregular meetings inviting community members to meet up.&lt;/p&gt;
&lt;h2 id=&quot;fill-in-the-survey-edit-survey-closed-in-december-2017&quot;&gt;Fill in the Survey! (edit: survey closed in December 2017)&lt;/h2&gt;
&lt;p&gt;We would like to get a better idea of the community, and to this end are conducting a survey, in cooperation with UK-RSE, where such a survey was held as well. The survey aims to generate insights into how many Research Software Engineers (RSEs) there are in the Netherlands, which academic disciplines they are active in, how they divide their work between research and software engineering, and what their career opportunities are within their organizations. There are 45 questions in the survey, which should take about 10 minutes to complete.&lt;/p&gt;
&lt;h2 id=&quot;join-nl-rse&quot;&gt;Join NL-RSE!&lt;/h2&gt;
&lt;p&gt;If you identify as a Research Software Engineer, and are enthusiastic about joining a community of your peers, please &lt;a href=&quot;https://lists.nl-rse.org/mailman/listinfo/everyone&quot;&gt;sign up for our mailing list!&lt;/a&gt; You can also follow us on Twitter, sign up for the Slack, or send us an &lt;a href=&quot;mailto:info@nl-rse.org&quot;&gt;email&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Wed, 20 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Bootstrapping the community of Research Software Engineers in the Netherlands.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_LmBD9OaRAJPnBYBoZwyZMw-68abbf5d.Caekald3_DjFB9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Research software has become an indispensable instrument for virtually every academic researcher. A case in point: &lt;a href=&quot;http://dx.doi.org/10.5281/zenodo.14809&quot;&gt;survey data&lt;/a&gt; from the UK revealed that 92% of academics use research software, 69% say that their research would not be practical without it and 56% develop their own software. Creating, storing and analyzing data is crucial in researchers’ daily work and enables them to address increasingly challenging research questions.&lt;/p&gt;
&lt;p&gt;This rapid digitization of research has strongly increased the number of people writing and contributing to research software. This is part of a more general trend, where positions like &lt;a href=&quot;https://www.tudelft.nl/en/library/theme-portals/research-data-management/research-data-management/data-stewardship/&quot;&gt;&lt;em&gt;data stewards&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;information managers&lt;/em&gt;, research data officer, &lt;em&gt;research supporter&lt;/em&gt; and other non-traditional research positions are becoming increasingly recognized as intrinsic positions in the academic research ecosystem. To increase the impact, recognition and visibility of research software in academia, we (&lt;a href=&quot;https://escience-platform.nl/&quot;&gt;ePlan&lt;/a&gt; and the Netherlands eScience Center) have taken the initiative to start and support the community of professionals &lt;em&gt;behind&lt;/em&gt; the software: the Netherlands Research Software Engineers community: &lt;a href=&quot;http://nl-rse.org/&quot;&gt;NL-RSE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The goal of the NL-RSE community fits with the broader national and international open science movement. For example in the Dutch &lt;a href=&quot;https://www.openscience.nl/en/&quot;&gt;National Platform Open Science&lt;/a&gt; and the &lt;a href=&quot;http://ec.europa.eu/research/openscience/index.cfm?pg=open-science-cloud&quot;&gt;European Open Science Cloud&lt;/a&gt; and &lt;a href=&quot;https://www.go-fair.org/&quot;&gt;GO-FAIR&lt;/a&gt;, there is a strong focus on new and digital technologies — &lt;em&gt;including software&lt;/em&gt; — to make research data, methods and outcomes more accessible and better reusable.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;677&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Do0XW7EAl1W5p5L9iuE6lQ-6ae25899.DFqxUYbS_gHx37.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://nl-rse.org/&quot;&gt;http://nl-rse.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NL-RSE is an open community for all people who as (part of) their job are writing software, regardless of the academic discipline or research area. Being member of the community allows research software engineers in the Netherlands to share knowledge, to initiate collaborations and to offer and ask support from other engineers in the Netherlands.&lt;/p&gt;
&lt;h2 id=&quot;tldr-version-of-this-blogpost&quot;&gt;TL;DR version of this blogpost&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sign up to the NL-RSE community &lt;a href=&quot;https://lists.nl-rse.org/mailman/listinfo/everyone&quot;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fill in our survey here (edit — the survey was held in December 2017 and is now closed. We will soon publishing a link to the results)&lt;/li&gt;
&lt;li&gt;Visit the &lt;a href=&quot;http://nl-rse.org/&quot;&gt;website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Get in touch here: &lt;a href=&quot;mailto:info@nl-rse.org&quot;&gt;info@nl-rse.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Source: &lt;a href=&quot;https://dirkgorissen.com/2012/03/26/the-researcher-programmer-a-new-species/&quot;&gt;Dirk Gorissen&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-dutch-guild-of-research-software-engineers&quot;&gt;The Dutch guild of Research Software Engineers&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_cSXU4CeixL3HnY9LBOTXeQ-5626ba8d.CUPAK4bi_2rMAVl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Research software has become an indispensable instrument for virtually every academic researcher&lt;/p&gt;
&lt;p&gt;The increasing reliance on and use of data and digital techniques in academia has led to an ever increasing amount of research software at the very core of the science done. The emergence of research software has gone hand in hand with a strong growth in people who actually &lt;em&gt;develop&lt;/em&gt; research software. Today, the UK at least counts more than &lt;a href=&quot;http://rse.ac.uk/&quot;&gt;800&lt;/a&gt; of professionals who identify as developers of software for research purposes. But for the Netherlands, we don’t know. Sure, we know that there are at least &lt;a href=&quot;https://www.esciencecenter.nl/people&quot;&gt;40 people&lt;/a&gt; actively developing and applying research software in close collaboration with university researchers. But there are many more people throughout the country working on software, managing data, and supporting digital research, distributed over various research institutes, universities, and other knowledge organizations.&lt;/p&gt;
&lt;p&gt;To strengthen the various communities and to increase interaction between them, we have taken the initiative to start the Research Software Engineer (RSE) community in the Netherlands. It is inspired by the successful &lt;a href=&quot;http://rse.ac.uk/&quot;&gt;UK-RSE Association&lt;/a&gt;, as well as the inspirational visits to the &lt;em&gt;First conference of Research Software Engineers&lt;/em&gt; in 2016, events organized by the Software Sustainability Institute, and encounters with UK-RSE and &lt;a href=&quot;http://www.de-rse.org/&quot;&gt;DE-RSE&lt;/a&gt; members.&lt;/p&gt;
&lt;h2 id=&quot;why-the-term-research-software-engineer-rse&quot;&gt;Why the term Research Software Engineer (RSE)?&lt;/h2&gt;
&lt;p&gt;Without a name, it is difficult to refer to a group of people that share a set of skills and characteristics. A name must be descriptive, yet short enough to be meaningful. It must differentiate and be acceptable to both the people who identify with it and the academic community. In 2012, when trying to form a community of people working on software in academia in the UK, a lot of thought and discussion went into what term to use. Eventually, the new name was created by fusing the two skills that make it unique: an understanding of both research &lt;em&gt;and&lt;/em&gt; software engineering. Quoting from the paper that marked the start of the Research Software Engineer community in the UK:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Research institutions need individuals with a new professional designation — the research software engineer. These individuals combine a professional attitude to the exercise of software engineering with a deep understanding of research topics. They lead the design and construction of increasingly complex research software systems, and play an important part in the co-design of research requirements, understanding and addressing software engineering questions that arise in research planning.&lt;/em&gt; [&lt;a href=&quot;http://digital-research-2012.oerc.ox.ac.uk/papers/the-research-software-engineer/at_download/file&quot;&gt;Baxter et al., 2012&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;936&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_XWCrOtVijQ8gqcEWKuWMBA-2766622b.rhVz23DQ_NFpx6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;RSEs are often embedded in research groups in small teams, or even by themselves, working hard on the software, algorithms, tools and interfaces that facilitate cutting-edge research. And in many cases, they are academic researchers at the same time, holding positions as (assistant/associate) professor, postdoc or PhD candidate. RSEs closely collaborate with researchers to understand the challenges they face, and then develop research software to provide the answers. Some have started as researchers who spent a lot of time developing software to do their research. Others have started as software developers who have developed a strong affinity with scientific research.&lt;/p&gt;
&lt;h2 id=&quot;building-the-community&quot;&gt;Building the Community&lt;/h2&gt;
&lt;p&gt;Early 2017, ePlan and the eScience Center took the first steps to found NL-RSE. While we hope that the community will run independently at some point, for the time being a few enthusiastic organizations and partner organizations will take care of NL-RSE best we can. Upon learning of our plans, a number of organizations and individuals have already confirmed their interest in supporting NL-RSE. We are very happy to be joined by DTL in setting up NL-RSE, and hope others will follow. Be sure to send us an e-mail (&lt;a href=&quot;mailto:info@nl-rse.org&quot;&gt;info@nl-rse.org&lt;/a&gt;) if you are interested in supporting NL-RSE!&lt;/p&gt;
&lt;p&gt;Although supported by a number of organizations, the NL-RSE community consists of individuals self-identifying as Research Software Engineers. We feel this is the only way to truly build a community.&lt;/p&gt;
&lt;p&gt;The centrepiece of the community is the mailing list. Rather than a newsletter governed by a communication department, any member can send messages to the entire community to make announcements. We also have created a &lt;a href=&quot;https://nl-rse.slack.com/&quot;&gt;Slack Group&lt;/a&gt; for discussions, and a &lt;a href=&quot;http://nl-rse.org/&quot;&gt;website&lt;/a&gt; with information.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;400&quot; height=&quot;300&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5xwpuYVUP73eMdxb7g5dyg-a7065dc6.BbhHbhLw_Z10GHFw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Better software better research” — slogan by the Software Sustainability Institute in the UK. &lt;a href=&quot;https://software.ac.uk/about&quot;&gt;https://software.ac.uk/about&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The main goal of NL-RSE is to build a community of Research Software Engineers in the Netherlands, build best practices, and learn from each other. Note that NL-RSE is about engineering of research software, rather than research on software engineering, a subtle but crucial difference with the computer science field of software engineering. We also hope to raise awareness of the importance of software in research, and the vital role RSEs play in creating this software. Besides an online presence, we plan to also hold irregular meetings inviting community members to meet up.&lt;/p&gt;
&lt;h2 id=&quot;fill-in-the-survey-edit-survey-closed-in-december-2017&quot;&gt;Fill in the Survey! (edit: survey closed in December 2017)&lt;/h2&gt;
&lt;p&gt;We would like to get a better idea of the community, and to this end are conducting a survey, in cooperation with UK-RSE, where such a survey was held as well. The survey aims to generate insights into how many Research Software Engineers (RSEs) there are in the Netherlands, which academic disciplines they are active in, how they divide their work between research and software engineering, and what their career opportunities are within their organizations. There are 45 questions in the survey, which should take about 10 minutes to complete.&lt;/p&gt;
&lt;h2 id=&quot;join-nl-rse&quot;&gt;Join NL-RSE!&lt;/h2&gt;
&lt;p&gt;If you identify as a Research Software Engineer, and are enthusiastic about joining a community of your peers, please &lt;a href=&quot;https://lists.nl-rse.org/mailman/listinfo/everyone&quot;&gt;sign up for our mailing list!&lt;/a&gt; You can also follow us on Twitter, sign up for the Slack, or send us an &lt;a href=&quot;mailto:info@nl-rse.org&quot;&gt;email&lt;/a&gt;.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Do0XW7EAl1W5p5L9iuE6lQ-6ae25899.DFqxUYbS.png" medium="image"/><author>eScience Editorial Team</author></item><item><title>Writing Testable GPU Code</title><link>https://blog2.esciencecenter.nl/posts/2017-12-18---writing-testable-gpu-code</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-12-18---writing-testable-gpu-code</guid><description>&lt;p&gt;Anyone involved in software development has probably heard someone say “testable code is better code”. While I was a bit skeptical at first, I now have to admit that I agree. One of the reasons it may have taken me a bit longer to get convinced is that I mostly write GPU code, in languages such as CUDA and OpenCL.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OtfM8fdvOaIT3OlaUfZBjw-2f2797dc.LneEnDPa_BUSvp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;First of all, you don’t see a lot of GPU code that is thoroughly tested. And while, there are many articles and blogs on how to write good unit tests or how to apply unit testing effectively, none of them focus specifically on testing GPU code. Today, I write unit tests for every bit of GPU code that I write. And since there aren’t that many resources on testing GPU code, I’ll explain how I managed to make testing part of my GPU coding practice.&lt;/p&gt;
&lt;p&gt;Just to be clear, this post is about unit testing GPU code and not about automated testing, formal verification, or model-checking code. While testing comes with its own limitations — in the words of Edsger Dijkstra: &lt;em&gt;“Testing shows the presence, not the absence of bugs”&lt;/em&gt; — testing is easier to apply and is very beneficial to the quality of your code.&lt;/p&gt;
&lt;p&gt;Writing tests for every part of your code forces you to keep functions short, simple, and focused on one thing. It will also force you to think longer on what you are coding. The resulting code is not only well-tested, but also structured differently, because the code is written with testability in mind.&lt;/p&gt;
&lt;h3 id=&quot;unit-testing-gpu-code&quot;&gt;Unit Testing GPU Code&lt;/h3&gt;
&lt;p&gt;Many excellent articles on effective unit testing and how to write good unit tests exist, but most of them focus on problems in object-oriented programming. Let’s take a look at some of the advice and see how it applies to unit testing GPU code.&lt;/p&gt;
&lt;p&gt;In general, articles on unit testing seem to agree that good unit tests have the following properties (&lt;a href=&quot;https://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters&quot;&gt;source&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy to write — you often write multiple tests for a single unit&lt;/li&gt;
&lt;li&gt;Readable — easy to understand what is being tested&lt;/li&gt;
&lt;li&gt;Reliable — should only fail if there is a bug in the code&lt;/li&gt;
&lt;li&gt;Fast — test are run frequently so should complete fast&lt;/li&gt;
&lt;li&gt;Truly unit, not integration — not reliable on external factors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Easy to write.&lt;/strong&gt;&lt;/em&gt; If you have to write host code for every bit of GPU code that you want to test, writing tests can be cumbersome. Fortunately, we will introduce a method that will greatly simplify writing tests for GPU code in the next section of this post.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Readable.&lt;/strong&gt;&lt;/em&gt; It can be a bit difficult to understand the purpose of a test when testing GPU code, because what is being tested is basically encoded into the data that is passed to the GPU code.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Reliable.&lt;/strong&gt;&lt;/em&gt; GPU code is in general very dependent on the host code that is supposed to call it. The test may fail if the data structures on the GPU are allocated incorrectly, if there is not enough memory available to hold the test data, or if the GPU kernel is launched with an incorrect number of threads per block.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Fast.&lt;/strong&gt;&lt;/em&gt; It is often possible to test the code with a smaller problem size than expected in a real application. On other hand, keep in mind that what may be a small problem size to work on for the GPU, may be take a long time to compute on the CPU.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Truly unit.&lt;/strong&gt;&lt;/em&gt; The idea of this point is that the tests should not depend on external factors, such as database servers or file systems. This is something that is hard to achieve for testing GPU code on the GPU. Some people may argue that testing GPU code on your GPU could not even be called ‘unit testing’ because of this point. I’d like to leave the terminology discussion for what it is, and focus on how to test GPU code.&lt;/p&gt;
&lt;h3 id=&quot;testing-gpu-code&quot;&gt;Testing GPU Code&lt;/h3&gt;
&lt;p&gt;Testing in general involves three steps:&lt;br&gt;
1. Decide on some input&lt;br&gt;
2. Execute the system under test&lt;br&gt;
3. Check the behavior of the system under test&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;697&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fosmxReXyy9S3J3J9fdPPA-fbb981ff.D097t5AQ_1Efttv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This may sound very simple, but when we’re talking about GPU code and executing it, things tend to get messy rather quickly. You can see this when we specify everything that needs to happen when our system under test consists of GPU code:&lt;/p&gt;
&lt;p&gt;1. Decide on some input data&lt;br&gt;
2. Compile the GPU code (if not compiled already)&lt;br&gt;
3. Allocate GPU memory&lt;br&gt;
4. Copy input data to the GPU&lt;br&gt;
5. Setup thread block and grid dimensions&lt;br&gt;
6. Call the kernel&lt;br&gt;
7. Copy data back to host memory&lt;br&gt;
8. Free GPU memory&lt;br&gt;
9. Check the behavior of the system under test&lt;/p&gt;
&lt;p&gt;Now if you have to write the host code for steps 2 through 8 for every kernel that you’d like to test, you’ll quickly learn to avoid writing tests for every bit of GPU code that you write. Basically, what we are missing is a good testing framework that allows GPU programmers to easily call GPU code for testing purposes.&lt;/p&gt;
&lt;p&gt;During the development of &lt;a href=&quot;http://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt;, I realized that the simple interface used for tuning GPU kernels could just as easily be used to run GPU kernels. We could support a function that executes a kernel and returns its output, instead of benchmarking the kernel and returning its execution time.&lt;/p&gt;
&lt;p&gt;Let’s take a look at a simple example, where we test a vector addition kernel implemented in CUDA with a short bit of Python code:&lt;/p&gt;
&lt;p&gt;In this example, the kernel code is specified as a string, but it’s also possible to just supply a filename. Note that you can pass either CUDA or OpenCL code, both are supported and the language will be detected automatically. Numpy is used to create some random input data for vectors &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;. We also create an array &lt;code&gt;c&lt;/code&gt; with zeros of the same size and data type. A list called &lt;code&gt;args&lt;/code&gt; is used to hold the arguments for calling the kernel. The &lt;code&gt;params&lt;/code&gt; dictionary is where we specify the thread block dimensions.&lt;/p&gt;
&lt;p&gt;Next, we call the &lt;code&gt;run_kernel&lt;/code&gt; function that takes the name of the function we’d like to test, the code (or filename) as a string, the problem size (used to compute the grid dimensions), and finally the arguments list and parameters dictionary.&lt;/p&gt;
&lt;p&gt;Finally, in the example above we use &lt;code&gt;numpy.allclose&lt;/code&gt; to compare the GPU output with the same result computed in Python using &lt;code&gt;(a+b)&lt;/code&gt;. We use Python’s &lt;code&gt;assert&lt;/code&gt; statement so that our test can be executed using the &lt;strong&gt;nosetests&lt;/strong&gt; or &lt;strong&gt;pytest&lt;/strong&gt; frameworks for testing Python code.&lt;/p&gt;
&lt;p&gt;To summarize, we take another look at our list of steps required to test GPU code, using &lt;a href=&quot;http://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt; as a framework for testing GPU code, the list becomes:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;582&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fW4l25XYSf0AjYg27X3HbA-fb2622ee.DqASCVH2_Z13K2cN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;testing-device-functions&quot;&gt;Testing device functions&lt;/h3&gt;
&lt;p&gt;Now that we have an easy way to test GPU kernels from Python, you may be wondering what about device functions? The way I test device functions is by writing a small wrapper kernel that calls the device function. This allows you to test device functions on the GPU and the wrapper kernel could even take care of creating the necessary context for your device function to execute correctly, such as declaring shared memory and looking up thread and block indices.&lt;/p&gt;
&lt;h3 id=&quot;designing-your-test-case&quot;&gt;Designing your test case&lt;/h3&gt;
&lt;p&gt;The hardest part of testing GPU code is designing a good test case. Actually, designing the testcase is all about choosing what data you put into the code. It’s very easy to just generate some random data, but for many codes using only random data is far too unrealistic. You have to keep in mind what assumptions are in the code about valid ranges for input data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;697&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_n2fyfhTfBwGjbZJa43iptw-5979f48b.CXqXWxp8_Z1f34qh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I ran into a problem like this myself once, when a kernel executed correctly only when one of its inputs was sorted. Testing only with randomly generated data did not reveal a race condition that I had introduced in the code. The bug only surfaced when I started testing with more realistic data.&lt;/p&gt;
&lt;p&gt;Another thing to keep in mind is that there should be sufficient variance in the output of your code. For example, if your GPU code outputs data in the interval [0,1] and your randomly generated input data causes the output to be all ones, you don’t have a very well designed test case and bugs may go undetected.&lt;/p&gt;
&lt;p&gt;The important thing to remember is that in order to design a good test case for your GPU code you should: first understand what your code is doing with the data you put in, and secondly, for more complex kernels, you should not only compare against the output of a CPU version of your code, but also ensure that the output itself makes sense.&lt;/p&gt;
&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;In general, testing GPU code can be a bit more difficult and a bit more work than testing other sorts of code. However, using testing frameworks specifically designed for testing GPU code, such as &lt;a href=&quot;http://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt;, drastically reduces the effort involved in writing tests.&lt;/p&gt;
&lt;p&gt;I hope this post contributes to enabling GPU programmers to make testing an integral part of their code development. And that we may see a lot more GPU code that is developed with testing in mind.&lt;/p&gt;</description><pubDate>Mon, 18 Dec 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Anyone involved in software development has probably heard someone say “testable code is better code”. While I was a bit skeptical at first, I now have to admit that I agree. One of the reasons it may have taken me a bit longer to get convinced is that I mostly write GPU code, in languages such as CUDA and OpenCL.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_OtfM8fdvOaIT3OlaUfZBjw-2f2797dc.LneEnDPa_BUSvp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;First of all, you don’t see a lot of GPU code that is thoroughly tested. And while, there are many articles and blogs on how to write good unit tests or how to apply unit testing effectively, none of them focus specifically on testing GPU code. Today, I write unit tests for every bit of GPU code that I write. And since there aren’t that many resources on testing GPU code, I’ll explain how I managed to make testing part of my GPU coding practice.&lt;/p&gt;
&lt;p&gt;Just to be clear, this post is about unit testing GPU code and not about automated testing, formal verification, or model-checking code. While testing comes with its own limitations — in the words of Edsger Dijkstra: &lt;em&gt;“Testing shows the presence, not the absence of bugs”&lt;/em&gt; — testing is easier to apply and is very beneficial to the quality of your code.&lt;/p&gt;
&lt;p&gt;Writing tests for every part of your code forces you to keep functions short, simple, and focused on one thing. It will also force you to think longer on what you are coding. The resulting code is not only well-tested, but also structured differently, because the code is written with testability in mind.&lt;/p&gt;
&lt;h3 id=&quot;unit-testing-gpu-code&quot;&gt;Unit Testing GPU Code&lt;/h3&gt;
&lt;p&gt;Many excellent articles on effective unit testing and how to write good unit tests exist, but most of them focus on problems in object-oriented programming. Let’s take a look at some of the advice and see how it applies to unit testing GPU code.&lt;/p&gt;
&lt;p&gt;In general, articles on unit testing seem to agree that good unit tests have the following properties (&lt;a href=&quot;https://www.toptal.com/qa/how-to-write-testable-code-and-why-it-matters&quot;&gt;source&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy to write — you often write multiple tests for a single unit&lt;/li&gt;
&lt;li&gt;Readable — easy to understand what is being tested&lt;/li&gt;
&lt;li&gt;Reliable — should only fail if there is a bug in the code&lt;/li&gt;
&lt;li&gt;Fast — test are run frequently so should complete fast&lt;/li&gt;
&lt;li&gt;Truly unit, not integration — not reliable on external factors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Easy to write.&lt;/strong&gt;&lt;/em&gt; If you have to write host code for every bit of GPU code that you want to test, writing tests can be cumbersome. Fortunately, we will introduce a method that will greatly simplify writing tests for GPU code in the next section of this post.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Readable.&lt;/strong&gt;&lt;/em&gt; It can be a bit difficult to understand the purpose of a test when testing GPU code, because what is being tested is basically encoded into the data that is passed to the GPU code.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Reliable.&lt;/strong&gt;&lt;/em&gt; GPU code is in general very dependent on the host code that is supposed to call it. The test may fail if the data structures on the GPU are allocated incorrectly, if there is not enough memory available to hold the test data, or if the GPU kernel is launched with an incorrect number of threads per block.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Fast.&lt;/strong&gt;&lt;/em&gt; It is often possible to test the code with a smaller problem size than expected in a real application. On other hand, keep in mind that what may be a small problem size to work on for the GPU, may be take a long time to compute on the CPU.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Truly unit.&lt;/strong&gt;&lt;/em&gt; The idea of this point is that the tests should not depend on external factors, such as database servers or file systems. This is something that is hard to achieve for testing GPU code on the GPU. Some people may argue that testing GPU code on your GPU could not even be called ‘unit testing’ because of this point. I’d like to leave the terminology discussion for what it is, and focus on how to test GPU code.&lt;/p&gt;
&lt;h3 id=&quot;testing-gpu-code&quot;&gt;Testing GPU Code&lt;/h3&gt;
&lt;p&gt;Testing in general involves three steps:&lt;br&gt;
1. Decide on some input&lt;br&gt;
2. Execute the system under test&lt;br&gt;
3. Check the behavior of the system under test&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;697&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fosmxReXyy9S3J3J9fdPPA-fbb981ff.D097t5AQ_1Efttv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This may sound very simple, but when we’re talking about GPU code and executing it, things tend to get messy rather quickly. You can see this when we specify everything that needs to happen when our system under test consists of GPU code:&lt;/p&gt;
&lt;p&gt;1. Decide on some input data&lt;br&gt;
2. Compile the GPU code (if not compiled already)&lt;br&gt;
3. Allocate GPU memory&lt;br&gt;
4. Copy input data to the GPU&lt;br&gt;
5. Setup thread block and grid dimensions&lt;br&gt;
6. Call the kernel&lt;br&gt;
7. Copy data back to host memory&lt;br&gt;
8. Free GPU memory&lt;br&gt;
9. Check the behavior of the system under test&lt;/p&gt;
&lt;p&gt;Now if you have to write the host code for steps 2 through 8 for every kernel that you’d like to test, you’ll quickly learn to avoid writing tests for every bit of GPU code that you write. Basically, what we are missing is a good testing framework that allows GPU programmers to easily call GPU code for testing purposes.&lt;/p&gt;
&lt;p&gt;During the development of &lt;a href=&quot;http://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt;, I realized that the simple interface used for tuning GPU kernels could just as easily be used to run GPU kernels. We could support a function that executes a kernel and returns its output, instead of benchmarking the kernel and returning its execution time.&lt;/p&gt;
&lt;p&gt;Let’s take a look at a simple example, where we test a vector addition kernel implemented in CUDA with a short bit of Python code:&lt;/p&gt;
&lt;p&gt;In this example, the kernel code is specified as a string, but it’s also possible to just supply a filename. Note that you can pass either CUDA or OpenCL code, both are supported and the language will be detected automatically. Numpy is used to create some random input data for vectors &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;. We also create an array &lt;code&gt;c&lt;/code&gt; with zeros of the same size and data type. A list called &lt;code&gt;args&lt;/code&gt; is used to hold the arguments for calling the kernel. The &lt;code&gt;params&lt;/code&gt; dictionary is where we specify the thread block dimensions.&lt;/p&gt;
&lt;p&gt;Next, we call the &lt;code&gt;run_kernel&lt;/code&gt; function that takes the name of the function we’d like to test, the code (or filename) as a string, the problem size (used to compute the grid dimensions), and finally the arguments list and parameters dictionary.&lt;/p&gt;
&lt;p&gt;Finally, in the example above we use &lt;code&gt;numpy.allclose&lt;/code&gt; to compare the GPU output with the same result computed in Python using &lt;code&gt;(a+b)&lt;/code&gt;. We use Python’s &lt;code&gt;assert&lt;/code&gt; statement so that our test can be executed using the &lt;strong&gt;nosetests&lt;/strong&gt; or &lt;strong&gt;pytest&lt;/strong&gt; frameworks for testing Python code.&lt;/p&gt;
&lt;p&gt;To summarize, we take another look at our list of steps required to test GPU code, using &lt;a href=&quot;http://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt; as a framework for testing GPU code, the list becomes:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;582&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_fW4l25XYSf0AjYg27X3HbA-fb2622ee.DqASCVH2_Z13K2cN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;testing-device-functions&quot;&gt;Testing device functions&lt;/h3&gt;
&lt;p&gt;Now that we have an easy way to test GPU kernels from Python, you may be wondering what about device functions? The way I test device functions is by writing a small wrapper kernel that calls the device function. This allows you to test device functions on the GPU and the wrapper kernel could even take care of creating the necessary context for your device function to execute correctly, such as declaring shared memory and looking up thread and block indices.&lt;/p&gt;
&lt;h3 id=&quot;designing-your-test-case&quot;&gt;Designing your test case&lt;/h3&gt;
&lt;p&gt;The hardest part of testing GPU code is designing a good test case. Actually, designing the testcase is all about choosing what data you put into the code. It’s very easy to just generate some random data, but for many codes using only random data is far too unrealistic. You have to keep in mind what assumptions are in the code about valid ranges for input data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;697&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_n2fyfhTfBwGjbZJa43iptw-5979f48b.CXqXWxp8_Z1f34qh.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I ran into a problem like this myself once, when a kernel executed correctly only when one of its inputs was sorted. Testing only with randomly generated data did not reveal a race condition that I had introduced in the code. The bug only surfaced when I started testing with more realistic data.&lt;/p&gt;
&lt;p&gt;Another thing to keep in mind is that there should be sufficient variance in the output of your code. For example, if your GPU code outputs data in the interval [0,1] and your randomly generated input data causes the output to be all ones, you don’t have a very well designed test case and bugs may go undetected.&lt;/p&gt;
&lt;p&gt;The important thing to remember is that in order to design a good test case for your GPU code you should: first understand what your code is doing with the data you put in, and secondly, for more complex kernels, you should not only compare against the output of a CPU version of your code, but also ensure that the output itself makes sense.&lt;/p&gt;
&lt;h3 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;In general, testing GPU code can be a bit more difficult and a bit more work than testing other sorts of code. However, using testing frameworks specifically designed for testing GPU code, such as &lt;a href=&quot;http://github.com/benvanwerkhoven/kernel_tuner&quot;&gt;Kernel Tuner&lt;/a&gt;, drastically reduces the effort involved in writing tests.&lt;/p&gt;
&lt;p&gt;I hope this post contributes to enabling GPU programmers to make testing an integral part of their code development. And that we may see a lot more GPU code that is developed with testing in mind.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_OtfM8fdvOaIT3OlaUfZBjw-2f2797dc.LneEnDPa.jpeg" medium="image"/><author>Ben van Werkhoven</author></item><item><title>teaching machines to recognize cancer</title><link>https://blog2.esciencecenter.nl/posts/2017-10-18---teaching-machines-to-recognize-cancer</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-10-18---teaching-machines-to-recognize-cancer</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KLXCuQrISaB1OwwRDKOMdQ-afa5f17b.C2EFGvqX_1qwpaM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Jeroen de Ridder, Associate Professor at the University Medical Center Utrecht&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon |&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Jeroen de Ridder is Associate Professor at the University Medical Center Utrecht (UMCU). In 2016, Jeroen received a &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;grant&lt;/a&gt; and in-kind expertise from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; for his project &lt;a href=&quot;https://www.esciencecenter.nl/project/googling-the-cancer-genome&quot;&gt;Googling the cancer genome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Jeroen’s ambition is to create data analytics methods that turn Big Data into value for the patient — in this project the aim is to develop new methods to drive the discovery of novel cancer genes.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Xq9QEOYOb5QZ3_PSRt80dg-41023789.CCUxxuAH_6uEIo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Before I joined the UMCU in May 2016, I was an Assistant Professor at Delft University of Technology. I also did my MSc degree there, originally in the field of Electrical Engineering, later in bioinformatics. My PhD was a joint research project between the Netherlands Cancer Institute and the Delft University of Technology.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“My ambition is to create data analytics methods that turn Big Data into value for the patient.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;what-do-you-find-most-exciting-about-life-science-research&quot;&gt;What do you find most exciting about life science research?&lt;/h3&gt;
&lt;p&gt;“Modern day life science has become so complex that there is only one way forward: bring together different expertises and collaborate.”&lt;/p&gt;
&lt;p&gt;“Bridging the gap between expertise, medicine, genomics, biology, computer science and machine learning is incredibly rewarding and exciting. The possibilities to measure a wide range of phenomena is virtually limitless, the grand challenge is to make sense of them.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lEtMoBF8F_Cwp_9TKIBeRw-29aeb6d7.DgbcMTcA_2pumj4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modern day life science requires collaboration between different expertises&lt;/p&gt;
&lt;h3 id=&quot;biology-and-big-data&quot;&gt;Biology and Big Data&lt;/h3&gt;
&lt;p&gt;“In our lab we create and apply innovative data science methods to advance our understanding of disease biology. Our research efforts are always inspired by a biological question and typically deal with big data, such as large-scale genomics and epigenomics datasets.”&lt;/p&gt;
&lt;p&gt;“As a result, much of the research floats on machine learning and data integration algorithms. We also heavily rely on high-performance computing and statistics.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2ZkltL1NtLD-LtROiFyFMQ-efc511d7.B2-p_NNP_2aS3qB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IxhB2f6qSWeXwLgqoi6WZw-548f8480.Cfg6Erh8_Z1E93PI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;personalized-treatments-for-cancer-patients&quot;&gt;Personalized treatments for cancer patients&lt;/h3&gt;
&lt;p&gt;In the Googling the cancer genome project, Jeroen and his team are developing methods to discover novel cancer genes. Cancer affects millions of people worldwide.&lt;/p&gt;
&lt;p&gt;With the advent of novel DNA sequencing technologies, genome sequencing has now started to become part of a routine workflow for cancer diagnostics. This has the potential to enable fine-tuned personalized treatments for cancer patients.&lt;/p&gt;
&lt;p&gt;In spite of the massive genomic data production, systematic and comprehensive analysis of these data, in particular regarding the detection and interpretation of structural variation, is lagging behind due to computational and algorithmic limitations.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_X4zgXPT0tWkNfjpm4i4sPw-f7735755.BetURIuv_tA7wF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a state-of-the-art nanopore sequencer — a third-generation single-molecue sequencing device that can sequence long stretches of DNA and are particularly suited to provide insight into the structural variation in the human genome&lt;/p&gt;
&lt;h3 id=&quot;what-is-the-scientific-challenge-that-you-aim-to-tackle-by-collaborating-with-escience-research-engineers&quot;&gt;What is the scientific challenge that you aim to tackle by collaborating with eScience Research Engineers?&lt;/h3&gt;
&lt;p&gt;“I force myself to focus on the scientific questions. However, to be able to answer those, often times one or more challenging engineering questions need to be solved. We are not always suited to do that, or it can take too much time. By collaborating with eScience Research Engineers we dramatically speed up this process and tap into expertise and knowledge that we don’t have ourselves. This is proving to be an extremely fruitful way of doing science.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Collaborating with the eScience Center is proving to be an extremely fruitful way of doing science&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BwK6g5_lCYCFE75StqJgcQ-aa3cd4a0.Bu7JEaxS_12HkLF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-kind-of-expertise-do-the-escience-research-engineers-bring-to-your-project&quot;&gt;What kind of expertise do the eScience Research Engineers bring to your project?&lt;/h3&gt;
&lt;p&gt;“Arnold Kuzniar brings in a lot of expertise on ‘developing and porting bioinformatics workflows to High-Performance Computing infrastructures and on linking biological data(bases). Sonja Georgievska brings in deep learning and machine learning expertise.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sBp5q5wN8inhai-KYoQmwA-0501cd2b.CtKO6qtO_1u4265.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Jeroen de Ridder, Marleen Nieboer, Carl Shneider, Arnold Kuzniar and Sonja Georgievska&lt;/p&gt;
&lt;h3 id=&quot;what-does-the-future-look-like-for-your-research-area&quot;&gt;What does the future look like for your research area?&lt;/h3&gt;
&lt;p&gt;“In the near future, I hope we will be able to have applications of our methods in the clinic. This should give clinical geneticists the tools to find novel genomic variants involved in disease. On of the biggest challenges for the coming years will be to leverage the huge leaps in machine learning for clinical genomics. I hope the eScience Center recognizes these trends and will invest in data analytics and machine learning to anticipate this need”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_54Ov8i9Wry2brLoCMGzctg-4efdc5df.DkxoMGhG_zDBGN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Wigard Kloosterman, Marleen Nieboer, Jeroen de Ridder, Arnold Kuzniar, Carl Shneider and Sonja Georgievska&lt;/p&gt;</description><pubDate>Wed, 18 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KLXCuQrISaB1OwwRDKOMdQ-afa5f17b.C2EFGvqX_1qwpaM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Jeroen de Ridder, Associate Professor at the University Medical Center Utrecht&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography: Elodie Burrillon |&lt;/em&gt; &lt;a href=&quot;http://hucopix.com/&quot;&gt;&lt;em&gt;http://hucopix.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Jeroen de Ridder is Associate Professor at the University Medical Center Utrecht (UMCU). In 2016, Jeroen received a &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;grant&lt;/a&gt; and in-kind expertise from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; for his project &lt;a href=&quot;https://www.esciencecenter.nl/project/googling-the-cancer-genome&quot;&gt;Googling the cancer genome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Jeroen’s ambition is to create data analytics methods that turn Big Data into value for the patient — in this project the aim is to develop new methods to drive the discovery of novel cancer genes.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Xq9QEOYOb5QZ3_PSRt80dg-41023789.CCUxxuAH_6uEIo.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Before I joined the UMCU in May 2016, I was an Assistant Professor at Delft University of Technology. I also did my MSc degree there, originally in the field of Electrical Engineering, later in bioinformatics. My PhD was a joint research project between the Netherlands Cancer Institute and the Delft University of Technology.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“My ambition is to create data analytics methods that turn Big Data into value for the patient.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;what-do-you-find-most-exciting-about-life-science-research&quot;&gt;What do you find most exciting about life science research?&lt;/h3&gt;
&lt;p&gt;“Modern day life science has become so complex that there is only one way forward: bring together different expertises and collaborate.”&lt;/p&gt;
&lt;p&gt;“Bridging the gap between expertise, medicine, genomics, biology, computer science and machine learning is incredibly rewarding and exciting. The possibilities to measure a wide range of phenomena is virtually limitless, the grand challenge is to make sense of them.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lEtMoBF8F_Cwp_9TKIBeRw-29aeb6d7.DgbcMTcA_2pumj4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Modern day life science requires collaboration between different expertises&lt;/p&gt;
&lt;h3 id=&quot;biology-and-big-data&quot;&gt;Biology and Big Data&lt;/h3&gt;
&lt;p&gt;“In our lab we create and apply innovative data science methods to advance our understanding of disease biology. Our research efforts are always inspired by a biological question and typically deal with big data, such as large-scale genomics and epigenomics datasets.”&lt;/p&gt;
&lt;p&gt;“As a result, much of the research floats on machine learning and data integration algorithms. We also heavily rely on high-performance computing and statistics.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_2ZkltL1NtLD-LtROiFyFMQ-efc511d7.B2-p_NNP_2aS3qB.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IxhB2f6qSWeXwLgqoi6WZw-548f8480.Cfg6Erh8_Z1E93PI.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;personalized-treatments-for-cancer-patients&quot;&gt;Personalized treatments for cancer patients&lt;/h3&gt;
&lt;p&gt;In the Googling the cancer genome project, Jeroen and his team are developing methods to discover novel cancer genes. Cancer affects millions of people worldwide.&lt;/p&gt;
&lt;p&gt;With the advent of novel DNA sequencing technologies, genome sequencing has now started to become part of a routine workflow for cancer diagnostics. This has the potential to enable fine-tuned personalized treatments for cancer patients.&lt;/p&gt;
&lt;p&gt;In spite of the massive genomic data production, systematic and comprehensive analysis of these data, in particular regarding the detection and interpretation of structural variation, is lagging behind due to computational and algorithmic limitations.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_X4zgXPT0tWkNfjpm4i4sPw-f7735755.BetURIuv_tA7wF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a state-of-the-art nanopore sequencer — a third-generation single-molecue sequencing device that can sequence long stretches of DNA and are particularly suited to provide insight into the structural variation in the human genome&lt;/p&gt;
&lt;h3 id=&quot;what-is-the-scientific-challenge-that-you-aim-to-tackle-by-collaborating-with-escience-research-engineers&quot;&gt;What is the scientific challenge that you aim to tackle by collaborating with eScience Research Engineers?&lt;/h3&gt;
&lt;p&gt;“I force myself to focus on the scientific questions. However, to be able to answer those, often times one or more challenging engineering questions need to be solved. We are not always suited to do that, or it can take too much time. By collaborating with eScience Research Engineers we dramatically speed up this process and tap into expertise and knowledge that we don’t have ourselves. This is proving to be an extremely fruitful way of doing science.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Collaborating with the eScience Center is proving to be an extremely fruitful way of doing science&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_BwK6g5_lCYCFE75StqJgcQ-aa3cd4a0.Bu7JEaxS_12HkLF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-kind-of-expertise-do-the-escience-research-engineers-bring-to-your-project&quot;&gt;What kind of expertise do the eScience Research Engineers bring to your project?&lt;/h3&gt;
&lt;p&gt;“Arnold Kuzniar brings in a lot of expertise on ‘developing and porting bioinformatics workflows to High-Performance Computing infrastructures and on linking biological data(bases). Sonja Georgievska brings in deep learning and machine learning expertise.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sBp5q5wN8inhai-KYoQmwA-0501cd2b.CtKO6qtO_1u4265.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Jeroen de Ridder, Marleen Nieboer, Carl Shneider, Arnold Kuzniar and Sonja Georgievska&lt;/p&gt;
&lt;h3 id=&quot;what-does-the-future-look-like-for-your-research-area&quot;&gt;What does the future look like for your research area?&lt;/h3&gt;
&lt;p&gt;“In the near future, I hope we will be able to have applications of our methods in the clinic. This should give clinical geneticists the tools to find novel genomic variants involved in disease. On of the biggest challenges for the coming years will be to leverage the huge leaps in machine learning for clinical genomics. I hope the eScience Center recognizes these trends and will invest in data analytics and machine learning to anticipate this need”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_54Ov8i9Wry2brLoCMGzctg-4efdc5df.DkxoMGhG_zDBGN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From left to right: Wigard Kloosterman, Marleen Nieboer, Jeroen de Ridder, Arnold Kuzniar, Carl Shneider and Sonja Georgievska&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Xq9QEOYOb5QZ3_PSRt80dg-41023789.CCUxxuAH.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>Demagification of Python, Git and Shell</title><link>https://blog2.esciencecenter.nl/posts/2017-10-17---demagification-of-python-git-and-shell</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-10-17---demagification-of-python-git-and-shell</guid><description>&lt;h2 id=&quot;teaching-researchers-essential-skills-for-digital-science&quot;&gt;Teaching researchers essential skills for digital science&lt;/h2&gt;
&lt;p&gt;With increasing number of data sources and digital tools playing a key role in today’s scholarly research, mastering the essential skills to efficiently deal with such data and tools becomes indispensible for academic researchers. To run our &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;research projects&lt;/a&gt; at the eScience Center in an efficient way, it is important that also our collaborators at universities develop the right digital skills. These skills include&lt;/p&gt;
&lt;p&gt;For this purpose we organized three workshops for our project members based on the &lt;a href=&quot;https://software-carpentry.org/&quot;&gt;Software&lt;/a&gt; and &lt;a href=&quot;http://www.datacarpentry.org/&quot;&gt;Data Carpentry&lt;/a&gt; model. The workshops focused on Version Control with Git &amp;#x26; GitHub, Scientific data analysis with Python and Unix Shell &amp;#x26; Task Automation.&lt;/p&gt;
&lt;p&gt;In this blog post we share some experiences of our essential skills workshops so far.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: On 6 November 2017 the workshop&lt;/em&gt; &lt;a href=&quot;https://www.eventbrite.nl/e/research-data-handling-registration-35594667609&quot;&gt;&lt;em&gt;Research Data Handling&lt;/em&gt;&lt;/a&gt; &lt;em&gt;will be held (you can still register).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RxEy7Gvsc3CVfhQuMAFnkQ-cc0df229.DbLizwAy_ZlTlqW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;demagification-of-essential-skills&quot;&gt;Demagification of essential skills&lt;/h3&gt;
&lt;p&gt;The workshops covered the topics of Github, Shell and Python, giving the participants the basic knowledge of these topics. So, were participants experts in Python after the training? Of course not — it takes years of practice to become an expert in any of these topics. Why then run such a short workshop? Well, our aim is for participants to have a good basis to start learning by themselves after the workshop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1867&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9RMXrTRWLqKKsDXsw8zmCw-78b7b330.FL9gWGG0_JJuPq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mateusz Kuzak demagifies digital science&lt;/p&gt;
&lt;p&gt;Mateusz Kuzak (instructor) calls this the “demagification process”: at first, it looks like magic — an engineer types some magic commands on a black screen and &lt;em&gt;&lt;strong&gt;poof&lt;/strong&gt;&lt;/em&gt; magic happens. But when you start to understand that these commands are nothing magical and that they are just like a recipe, it feels less like something magical and unachievable and more like a super power which you can also learn. In the end our aim is for learners to understand that they can also learn how to use these powers (although, not from a Jedi).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“After the course I found that it is much easier for me to learn and use Python”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is exactly what we are aiming for!&lt;/p&gt;
&lt;h3 id=&quot;personal-interaction-for-maximal-learning-experience&quot;&gt;Personal interaction for maximal learning experience&lt;/h3&gt;
&lt;p&gt;The workshops were attended by 15–20 people, which enabled the various instructors from the eScience Center to spend sufficient time with individual participants. Afterwards, workshop participants pointed out that this was really beneficial to them because in this way they could maximize their learning experience. One participant commented:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I sincerely appreciated the amount of staff around. Besides being absolutely up-to-par for the job, the amount of people covered issues very well which resulted in quick help, where help was allowed to breathe and explain things properly instead of rushing to finish problems due to understaffing.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;what-feedback-told-us&quot;&gt;What feedback told us&lt;/h2&gt;
&lt;p&gt;After the workshops, participants shared their feedback on the workshops through a short suvey. Overall, participants indicated that having attended the workshops will really help them to do much of their work in a more efficient way. Also the hands-on approach, insteading of lecturing, was highly appreciated. Furthermore, the Python workshop participants appreciated the use of Jupyter Notebooks and the introduction into data analysis with Pandas. Also the introduction to &lt;a href=&quot;https://www.gnu.org/software/make/&quot;&gt;Make&lt;/a&gt; in the Shell &amp;#x26; Task Automation course was positively reviewed and could perhaps receive some more attention in the future.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_wt6Hj-laynLpbqVuoMdpvw-46f7b3a1.COhcx_Na_1IRopr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the Python course, various participants suggested to split up the workshop in two levels: a Beginner and an Intermediate/Advanced Python workhop. Perhaps the most positive reviews were probably coming from the workshop on Version control with Git &amp;#x26; GitHub. One participant wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“This workshop is very helpful and in time. I have been trying to teach myself about git and github for a while and I was able to use it to some extend. But only after attending this workshop, I have a crystal-clear idea about the whole framework! Attending this workshop greatly shortened my learning curve. I will be able to use git and github in a much more efficient way now. My students and I will now be able to collaborate better on github now. This also will contribute to my on-going e-Science project. I will highly recommend it to my colleagues and students.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h3&gt;
&lt;p&gt;For our learners, we hope that this workshop has been only the &lt;em&gt;first&lt;/em&gt; step on the learning path and that they will be able to continue on this path. For us this was also a learning experience and we will strive to run more workshops aimed to increase knowledge and improve the quality of science!&lt;/p&gt;
&lt;p&gt;Want to learn essential skills for digital science as well? Stay up to date! &lt;a href=&quot;http://eepurl.com/Szzyf&quot;&gt;Sign up for our newsletter&lt;/a&gt; in which we will announce future workshops.&lt;/p&gt;</description><pubDate>Tue, 17 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;teaching-researchers-essential-skills-for-digital-science&quot;&gt;Teaching researchers essential skills for digital science&lt;/h2&gt;
&lt;p&gt;With increasing number of data sources and digital tools playing a key role in today’s scholarly research, mastering the essential skills to efficiently deal with such data and tools becomes indispensible for academic researchers. To run our &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;research projects&lt;/a&gt; at the eScience Center in an efficient way, it is important that also our collaborators at universities develop the right digital skills. These skills include&lt;/p&gt;
&lt;p&gt;For this purpose we organized three workshops for our project members based on the &lt;a href=&quot;https://software-carpentry.org/&quot;&gt;Software&lt;/a&gt; and &lt;a href=&quot;http://www.datacarpentry.org/&quot;&gt;Data Carpentry&lt;/a&gt; model. The workshops focused on Version Control with Git &amp;#x26; GitHub, Scientific data analysis with Python and Unix Shell &amp;#x26; Task Automation.&lt;/p&gt;
&lt;p&gt;In this blog post we share some experiences of our essential skills workshops so far.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: On 6 November 2017 the workshop&lt;/em&gt; &lt;a href=&quot;https://www.eventbrite.nl/e/research-data-handling-registration-35594667609&quot;&gt;&lt;em&gt;Research Data Handling&lt;/em&gt;&lt;/a&gt; &lt;em&gt;will be held (you can still register).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_RxEy7Gvsc3CVfhQuMAFnkQ-cc0df229.DbLizwAy_ZlTlqW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;demagification-of-essential-skills&quot;&gt;Demagification of essential skills&lt;/h3&gt;
&lt;p&gt;The workshops covered the topics of Github, Shell and Python, giving the participants the basic knowledge of these topics. So, were participants experts in Python after the training? Of course not — it takes years of practice to become an expert in any of these topics. Why then run such a short workshop? Well, our aim is for participants to have a good basis to start learning by themselves after the workshop.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1867&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9RMXrTRWLqKKsDXsw8zmCw-78b7b330.FL9gWGG0_JJuPq.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Mateusz Kuzak demagifies digital science&lt;/p&gt;
&lt;p&gt;Mateusz Kuzak (instructor) calls this the “demagification process”: at first, it looks like magic — an engineer types some magic commands on a black screen and &lt;em&gt;&lt;strong&gt;poof&lt;/strong&gt;&lt;/em&gt; magic happens. But when you start to understand that these commands are nothing magical and that they are just like a recipe, it feels less like something magical and unachievable and more like a super power which you can also learn. In the end our aim is for learners to understand that they can also learn how to use these powers (although, not from a Jedi).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“After the course I found that it is much easier for me to learn and use Python”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is exactly what we are aiming for!&lt;/p&gt;
&lt;h3 id=&quot;personal-interaction-for-maximal-learning-experience&quot;&gt;Personal interaction for maximal learning experience&lt;/h3&gt;
&lt;p&gt;The workshops were attended by 15–20 people, which enabled the various instructors from the eScience Center to spend sufficient time with individual participants. Afterwards, workshop participants pointed out that this was really beneficial to them because in this way they could maximize their learning experience. One participant commented:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I sincerely appreciated the amount of staff around. Besides being absolutely up-to-par for the job, the amount of people covered issues very well which resulted in quick help, where help was allowed to breathe and explain things properly instead of rushing to finish problems due to understaffing.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;what-feedback-told-us&quot;&gt;What feedback told us&lt;/h2&gt;
&lt;p&gt;After the workshops, participants shared their feedback on the workshops through a short suvey. Overall, participants indicated that having attended the workshops will really help them to do much of their work in a more efficient way. Also the hands-on approach, insteading of lecturing, was highly appreciated. Furthermore, the Python workshop participants appreciated the use of Jupyter Notebooks and the introduction into data analysis with Pandas. Also the introduction to &lt;a href=&quot;https://www.gnu.org/software/make/&quot;&gt;Make&lt;/a&gt; in the Shell &amp;#x26; Task Automation course was positively reviewed and could perhaps receive some more attention in the future.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_wt6Hj-laynLpbqVuoMdpvw-46f7b3a1.COhcx_Na_1IRopr.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;For the Python course, various participants suggested to split up the workshop in two levels: a Beginner and an Intermediate/Advanced Python workhop. Perhaps the most positive reviews were probably coming from the workshop on Version control with Git &amp;#x26; GitHub. One participant wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“This workshop is very helpful and in time. I have been trying to teach myself about git and github for a while and I was able to use it to some extend. But only after attending this workshop, I have a crystal-clear idea about the whole framework! Attending this workshop greatly shortened my learning curve. I will be able to use git and github in a much more efficient way now. My students and I will now be able to collaborate better on github now. This also will contribute to my on-going e-Science project. I will highly recommend it to my colleagues and students.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h3&gt;
&lt;p&gt;For our learners, we hope that this workshop has been only the &lt;em&gt;first&lt;/em&gt; step on the learning path and that they will be able to continue on this path. For us this was also a learning experience and we will strive to run more workshops aimed to increase knowledge and improve the quality of science!&lt;/p&gt;
&lt;p&gt;Want to learn essential skills for digital science as well? Stay up to date! &lt;a href=&quot;http://eepurl.com/Szzyf&quot;&gt;Sign up for our newsletter&lt;/a&gt; in which we will announce future workshops.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_RxEy7Gvsc3CVfhQuMAFnkQ-cc0df229.DbLizwAy.jpeg" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>free as in free market</title><link>https://blog2.esciencecenter.nl/posts/2017-10-05---free-as-in-free-market</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-10-05---free-as-in-free-market</guid><description>&lt;h2 id=&quot;or-why-the-gnu-general-public-license-is-open-for-business&quot;&gt;Or why the GNU General Public License is open for business&lt;/h2&gt;
&lt;p&gt;When you release your software on the Internet for others to use, you need to choose a license for it. One issue you might want to consider is further development of your software by commercial parties. In this post, we’ll have a look at the GNU General Public License, and how it affects potential commercial users and developers of your software.&lt;/p&gt;
&lt;h2 id=&quot;commerce-and-free-open-source-software&quot;&gt;Commerce and Free, Open Source Software&lt;/h2&gt;
&lt;p&gt;Science is mostly a publicly funded enterprise. Society is willing to pay for it, because scientific research enables the development of products and services that make people’s lives better. At the &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we work with scientists to develop software for doing scientific research, and where applicable we want to let our software be used commercially by others, and allow people to develop it into commercial products as well.&lt;/p&gt;
&lt;p&gt;To enable this, it is important that the related intellectual property rights are licensed appropriately. Wherever possible, we license the software we develop under a Free, Open Source Software (FOSS) license, in particular, the Apache License 2.0. We sometimes use other FOSS licenses as well, including the GNU General Public License (GPL). This latter license is sometimes believed to be hostile to commercial interests. It’s even been called &lt;a href=&quot;http://ebb.org/bkuhn/blog/2012/12/14/unamerican-mccarthyist-cancer.html&quot;&gt;“communist” and “un-American”&lt;/a&gt; by some particularly hotheaded detractors.&lt;/p&gt;
&lt;p&gt;Much of the confusion here stems from that word “Free” in the term Free Software. Free, in this context, &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html&quot;&gt;refers to the freedom of the users&lt;/a&gt;, not to the price of the software. Or, as the inventor of the term, Richard Stallman, put it: Free Software is “Free as in (free) speech”, not “Free as in (free) beer”.&lt;/p&gt;
&lt;p&gt;I’d like to argue that “Free as in (free) market” is also an appropriate description, describe how the GPL affects commercial software development, and explain why it doesn’t keep a company like Red Hat from making hundreds of millions of dollars per year in profits off of GPL-licensed software.&lt;/p&gt;
&lt;h2 id=&quot;the-market-for-software&quot;&gt;The market for software&lt;/h2&gt;
&lt;p&gt;First, the GPL is not a non-commercial license. Like all other common FOSS licenses, it explicitly allows commercial use of the software licensed under it, as well as the sale of copies. To understand what it does do with respect to commerce, we need to dive a little bit into the economic aspects of software development and use.&lt;/p&gt;
&lt;p&gt;So, let’s consider the market for software, let’s say Microsoft Office (the traditional one, not Office 365). There are the users, who are in economic terms consumers, and the developers, who are producers. Because Microsoft owns the copyrights to Office, only Microsoft is allowed to make and sell copies, and the users can only buy from Microsoft.&lt;/p&gt;
&lt;p&gt;While there are other office products, switching to them is not so easy because of compatibility issues and users having to be retrained. In classical economics terms (you may remember Adam Smith from school), this makes this market &lt;a href=&quot;https://en.wikipedia.org/wiki/Economic_rent&quot;&gt;not so free&lt;/a&gt;, which advantages the producers. Indeed, Microsoft has been making a rather healthy profit from Office for the past two decades.&lt;/p&gt;
&lt;p&gt;Today, the term “free market” is often used to refer to markets that are free from government regulation. In those terms, the market for Office does seem to be rather free. The only government interference with Microsoft Office, has been the decision by European governments to require support for open standard file formats. But they were simply exercising their buying power as a major customer; there was no legislation or litigation involved.&lt;/p&gt;
&lt;p&gt;While this sounds good, it misses a key insight: this whole market for copies of Microsoft Office would not exist without copyright, and copyright is an entirely artificial construct instituted by governments. Without copyright, anyone could make copies, and the price of MS Office would rapidly drop to the marginal cost of making a copy. So another way of looking at this, is that a government-granted monopoly on making copies has resulted in customers paying much more than they otherwise would. That’s not so free at all, whichever terms you use!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;314&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lOmZnKT6YzZqn0H5Jn-oAA-ccf3ad81.DI_VDJbP_Z66aTy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;free-software-makes-free-markets&quot;&gt;Free Software makes free markets&lt;/h2&gt;
&lt;p&gt;This is where Free Software comes in. You may be more familiar with the term Open Source, or the combination Free and Open Source Software (FOSS). In practical terms, there is not much difference (hence the combination term): if a program is Free Software, then it is almost always also Open Source, and vice versa. However, there are philosophical differences (Open Source is much more pragmatic) and what I’m discussing here is the concept of Free Software, so that is the term I will use.&lt;/p&gt;
&lt;p&gt;Free Software is not about price. As I said above, you can sell copies of it as much as you want. The &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html&quot;&gt;Free in Free Software refers to the users’ freedom&lt;/a&gt; to use the program for any purpose, to modify it to suit their needs, to make copies so that they can help their neighbour, and to share their changes so that others can benefit and software can be developed collaboratively.&lt;/p&gt;
&lt;p&gt;This is good news for consumers. It means that the consumers can change between different producers of copies whenever they want, as all the copies are exactly identical. Unhappy? Just switch! Also, they can always get exactly the software they need, by modifying or extending it as needed.&lt;/p&gt;
&lt;p&gt;Free Software creates a perfect free market (in both senses) for copies of software, undoing the monopoly created by copyright law, and making all producers equal. This does drive the price down to the marginal cost of making a copy, but that is a consequence, not the goal.&lt;/p&gt;
&lt;h2 id=&quot;so-why-produce-free-software&quot;&gt;So why produce Free Software?&lt;/h2&gt;
&lt;p&gt;While this sounds good for consumers, it raises the question of why anyone would invest in producing Free Software. Sure, you can reduce development costs when others help develop the software, and perhaps the quality increases because the community knows better than you do on your own. Also, customers like being able to switch, so it is a value-add to your product. But selling copies still won’t cover anyone’s development cost, so doing anything at all seems like a net loss regardless.&lt;/p&gt;
&lt;p&gt;The answer is simple: people invest in developing Free Software because they, or their customers, need software. For example, sometimes scientists need custom software to help with their research, and so the Dutch science funding body NWO funds the Netherlands eScience Center to work with them to create that software. And so my colleagues and I are paid to create software. Once in that situation, making it Free Software &lt;a href=&quot;https://www.openscience.nl/&quot;&gt;improves science&lt;/a&gt; and reduces costs.&lt;/p&gt;
&lt;p&gt;As another example, business users need software to support their business processes. A company like Red Hat provides them with that software, and with support in the form of easy, timely security updates and help if something breaks or needs changing. Red Hat is in a good position to offer such support, because it employs some of the developers working on the software, so that it’s intimately familiar with it. On the other hand, most of the software that comprises their product is written and paid for by others.&lt;/p&gt;
&lt;p&gt;Of course, this does not stop anyone from copying e.g. Red Hat Enterprise Linux, renaming it, and selling support for that. Red Hat are not too happy about this, but they cannot really stop it from happening. To set their products apart, the competing companies add their own improvements, for which they employ developers. And so Free Software keeps getting produced, albeit at a somewhat lower profit margin than non-Free software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sAvfudMrjPG4EScrut1IPg-0a240cbf.DslsYVdP_vohgN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Muhammad Mahdi Karim. Licensed under the GFDL 1.2.&lt;/p&gt;
&lt;h2 id=&quot;the-gnu-general-public-license&quot;&gt;The GNU General Public License&lt;/h2&gt;
&lt;p&gt;I started this blog post mentioning the Apache License version 2.0 (ALv2), and the GNU General Public License. The main difference between these licenses is that the GPL forbids using any software licensed under it in a (partially) non-Free program, while the ALv2 (as well as the BSD and MIT licenses) does allow such use.&lt;/p&gt;
&lt;p&gt;As a result, if we at the eScience Center release something under the GPL, and someone takes it and sells it (or maybe a modified version), they will have to allow their customers to use the software for any purpose, to modify it to suit their needs, to make copies so that they can help their neighbour, and to share their changes, so that others can benefit and software can be developed collaboratively. As a result, they will be in a very free market, as anyone will be able to compete with them: on selling copies, or on selling support services.&lt;/p&gt;
&lt;p&gt;If we release something under the ALv2, anyone selling unmodified copies will still be in a very free market, as their customers can also get a copy from us or anyone else. But in this case, the reseller is allowed to make a modified version available under a license that forbids copying, thus reactivating the copyright monopoly, creating a much less free market, and potentially making higher profits.&lt;/p&gt;
&lt;p&gt;So there you have it. Is it easier to start a company based on non-Free (proprietary) software, as allowed by the ALv2? Probably, because you are more protected from competition. Is it more lucrative? Also, yes. Does the GPL make it impossible to make a profit? Absolutely not.&lt;/p&gt;
&lt;p&gt;It’s just that with the GPL, any market surrounding the software will be more free, which is a bit worse for producers, and a bit better for consumers. Considering that there are many more consumers of software than producers, I’d consider that a win.&lt;/p&gt;</description><pubDate>Thu, 05 Oct 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;or-why-the-gnu-general-public-license-is-open-for-business&quot;&gt;Or why the GNU General Public License is open for business&lt;/h2&gt;
&lt;p&gt;When you release your software on the Internet for others to use, you need to choose a license for it. One issue you might want to consider is further development of your software by commercial parties. In this post, we’ll have a look at the GNU General Public License, and how it affects potential commercial users and developers of your software.&lt;/p&gt;
&lt;h2 id=&quot;commerce-and-free-open-source-software&quot;&gt;Commerce and Free, Open Source Software&lt;/h2&gt;
&lt;p&gt;Science is mostly a publicly funded enterprise. Society is willing to pay for it, because scientific research enables the development of products and services that make people’s lives better. At the &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt;, we work with scientists to develop software for doing scientific research, and where applicable we want to let our software be used commercially by others, and allow people to develop it into commercial products as well.&lt;/p&gt;
&lt;p&gt;To enable this, it is important that the related intellectual property rights are licensed appropriately. Wherever possible, we license the software we develop under a Free, Open Source Software (FOSS) license, in particular, the Apache License 2.0. We sometimes use other FOSS licenses as well, including the GNU General Public License (GPL). This latter license is sometimes believed to be hostile to commercial interests. It’s even been called &lt;a href=&quot;http://ebb.org/bkuhn/blog/2012/12/14/unamerican-mccarthyist-cancer.html&quot;&gt;“communist” and “un-American”&lt;/a&gt; by some particularly hotheaded detractors.&lt;/p&gt;
&lt;p&gt;Much of the confusion here stems from that word “Free” in the term Free Software. Free, in this context, &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html&quot;&gt;refers to the freedom of the users&lt;/a&gt;, not to the price of the software. Or, as the inventor of the term, Richard Stallman, put it: Free Software is “Free as in (free) speech”, not “Free as in (free) beer”.&lt;/p&gt;
&lt;p&gt;I’d like to argue that “Free as in (free) market” is also an appropriate description, describe how the GPL affects commercial software development, and explain why it doesn’t keep a company like Red Hat from making hundreds of millions of dollars per year in profits off of GPL-licensed software.&lt;/p&gt;
&lt;h2 id=&quot;the-market-for-software&quot;&gt;The market for software&lt;/h2&gt;
&lt;p&gt;First, the GPL is not a non-commercial license. Like all other common FOSS licenses, it explicitly allows commercial use of the software licensed under it, as well as the sale of copies. To understand what it does do with respect to commerce, we need to dive a little bit into the economic aspects of software development and use.&lt;/p&gt;
&lt;p&gt;So, let’s consider the market for software, let’s say Microsoft Office (the traditional one, not Office 365). There are the users, who are in economic terms consumers, and the developers, who are producers. Because Microsoft owns the copyrights to Office, only Microsoft is allowed to make and sell copies, and the users can only buy from Microsoft.&lt;/p&gt;
&lt;p&gt;While there are other office products, switching to them is not so easy because of compatibility issues and users having to be retrained. In classical economics terms (you may remember Adam Smith from school), this makes this market &lt;a href=&quot;https://en.wikipedia.org/wiki/Economic_rent&quot;&gt;not so free&lt;/a&gt;, which advantages the producers. Indeed, Microsoft has been making a rather healthy profit from Office for the past two decades.&lt;/p&gt;
&lt;p&gt;Today, the term “free market” is often used to refer to markets that are free from government regulation. In those terms, the market for Office does seem to be rather free. The only government interference with Microsoft Office, has been the decision by European governments to require support for open standard file formats. But they were simply exercising their buying power as a major customer; there was no legislation or litigation involved.&lt;/p&gt;
&lt;p&gt;While this sounds good, it misses a key insight: this whole market for copies of Microsoft Office would not exist without copyright, and copyright is an entirely artificial construct instituted by governments. Without copyright, anyone could make copies, and the price of MS Office would rapidly drop to the marginal cost of making a copy. So another way of looking at this, is that a government-granted monopoly on making copies has resulted in customers paying much more than they otherwise would. That’s not so free at all, whichever terms you use!&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;500&quot; height=&quot;314&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lOmZnKT6YzZqn0H5Jn-oAA-ccf3ad81.DI_VDJbP_Z66aTy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;free-software-makes-free-markets&quot;&gt;Free Software makes free markets&lt;/h2&gt;
&lt;p&gt;This is where Free Software comes in. You may be more familiar with the term Open Source, or the combination Free and Open Source Software (FOSS). In practical terms, there is not much difference (hence the combination term): if a program is Free Software, then it is almost always also Open Source, and vice versa. However, there are philosophical differences (Open Source is much more pragmatic) and what I’m discussing here is the concept of Free Software, so that is the term I will use.&lt;/p&gt;
&lt;p&gt;Free Software is not about price. As I said above, you can sell copies of it as much as you want. The &lt;a href=&quot;https://www.gnu.org/philosophy/free-sw.html&quot;&gt;Free in Free Software refers to the users’ freedom&lt;/a&gt; to use the program for any purpose, to modify it to suit their needs, to make copies so that they can help their neighbour, and to share their changes so that others can benefit and software can be developed collaboratively.&lt;/p&gt;
&lt;p&gt;This is good news for consumers. It means that the consumers can change between different producers of copies whenever they want, as all the copies are exactly identical. Unhappy? Just switch! Also, they can always get exactly the software they need, by modifying or extending it as needed.&lt;/p&gt;
&lt;p&gt;Free Software creates a perfect free market (in both senses) for copies of software, undoing the monopoly created by copyright law, and making all producers equal. This does drive the price down to the marginal cost of making a copy, but that is a consequence, not the goal.&lt;/p&gt;
&lt;h2 id=&quot;so-why-produce-free-software&quot;&gt;So why produce Free Software?&lt;/h2&gt;
&lt;p&gt;While this sounds good for consumers, it raises the question of why anyone would invest in producing Free Software. Sure, you can reduce development costs when others help develop the software, and perhaps the quality increases because the community knows better than you do on your own. Also, customers like being able to switch, so it is a value-add to your product. But selling copies still won’t cover anyone’s development cost, so doing anything at all seems like a net loss regardless.&lt;/p&gt;
&lt;p&gt;The answer is simple: people invest in developing Free Software because they, or their customers, need software. For example, sometimes scientists need custom software to help with their research, and so the Dutch science funding body NWO funds the Netherlands eScience Center to work with them to create that software. And so my colleagues and I are paid to create software. Once in that situation, making it Free Software &lt;a href=&quot;https://www.openscience.nl/&quot;&gt;improves science&lt;/a&gt; and reduces costs.&lt;/p&gt;
&lt;p&gt;As another example, business users need software to support their business processes. A company like Red Hat provides them with that software, and with support in the form of easy, timely security updates and help if something breaks or needs changing. Red Hat is in a good position to offer such support, because it employs some of the developers working on the software, so that it’s intimately familiar with it. On the other hand, most of the software that comprises their product is written and paid for by others.&lt;/p&gt;
&lt;p&gt;Of course, this does not stop anyone from copying e.g. Red Hat Enterprise Linux, renaming it, and selling support for that. Red Hat are not too happy about this, but they cannot really stop it from happening. To set their products apart, the competing companies add their own improvements, for which they employ developers. And so Free Software keeps getting produced, albeit at a somewhat lower profit margin than non-Free software.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sAvfudMrjPG4EScrut1IPg-0a240cbf.DslsYVdP_vohgN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Photo by Muhammad Mahdi Karim. Licensed under the GFDL 1.2.&lt;/p&gt;
&lt;h2 id=&quot;the-gnu-general-public-license&quot;&gt;The GNU General Public License&lt;/h2&gt;
&lt;p&gt;I started this blog post mentioning the Apache License version 2.0 (ALv2), and the GNU General Public License. The main difference between these licenses is that the GPL forbids using any software licensed under it in a (partially) non-Free program, while the ALv2 (as well as the BSD and MIT licenses) does allow such use.&lt;/p&gt;
&lt;p&gt;As a result, if we at the eScience Center release something under the GPL, and someone takes it and sells it (or maybe a modified version), they will have to allow their customers to use the software for any purpose, to modify it to suit their needs, to make copies so that they can help their neighbour, and to share their changes, so that others can benefit and software can be developed collaboratively. As a result, they will be in a very free market, as anyone will be able to compete with them: on selling copies, or on selling support services.&lt;/p&gt;
&lt;p&gt;If we release something under the ALv2, anyone selling unmodified copies will still be in a very free market, as their customers can also get a copy from us or anyone else. But in this case, the reseller is allowed to make a modified version available under a license that forbids copying, thus reactivating the copyright monopoly, creating a much less free market, and potentially making higher profits.&lt;/p&gt;
&lt;p&gt;So there you have it. Is it easier to start a company based on non-Free (proprietary) software, as allowed by the ALv2? Probably, because you are more protected from competition. Is it more lucrative? Also, yes. Does the GPL make it impossible to make a profit? Absolutely not.&lt;/p&gt;
&lt;p&gt;It’s just that with the GPL, any market surrounding the software will be more free, which is a bit worse for producers, and a bit better for consumers. Considering that there are many more consumers of software than producers, I’d consider that a win.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_lOmZnKT6YzZqn0H5Jn-oAA-ccf3ad81.DI_VDJbP.jpeg" medium="image"/><author>Lourens Veen</author></item><item><title>10 ways to keep your successful scientific software alive</title><link>https://blog2.esciencecenter.nl/posts/2017-09-11---10-ways-to-keep-your-successful-scientific-software-alive</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-09-11---10-ways-to-keep-your-successful-scientific-software-alive</guid><description>&lt;p&gt;Imagine, you invest a lot of time and energy in the development of a piece of scientific software. The work pays off and scientists start to use your software in their research. However, the growing user community also produces a stream of help requests, feature requests, and bug reports. What to do about it?&lt;/p&gt;
&lt;h3 id=&quot;keeping-the-software-alive-is-not-a-straightforward-exercise&quot;&gt;Keeping the software alive is not a straightforward exercise&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Software maintenance can be a time consuming activity and is not necessarily a fun or exciting thing to do.&lt;/li&gt;
&lt;li&gt;If you are a scientist, the maintenance of software may not easily translate itself into a new proposal for a research grant. The work required is typically a pile of unrelated issues from a diverse group of stakeholders without a clear overarching and innovative research question.&lt;/li&gt;
&lt;li&gt;If you are the engineer who built the software you may want to move on to work on new technological challenges rather than maintaining the software for the decades to come. On the other hand, if you actually want to continue working on the software, the scientist(s) you work with may not have more funding to pay for your time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Z3U8YgT-cRE1HWas6sr_EA-021a880f.03x9mJkh_Z1PuKx8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sources of images: screenshot; stethoscope, bandage, and red cross (all with Creative Commons license)&lt;/p&gt;
&lt;h3 id=&quot;reasons-to-invest-in-your-scientific-software&quot;&gt;Reasons to invest in your scientific software&lt;/h3&gt;
&lt;p&gt;Despite the challenges mentioned above you may have the following reasons to carry on investing in your scientific software:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It can extend the impact of your original work, which could be good for your track record as engineer or as scientist.&lt;/li&gt;
&lt;li&gt;It can secure the reproducibility of the research that has been done with it, which may be essential if you are a scientist (assuming that no other piece of software exists that can guarantee 100% reproducibility compared with your own software).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, regardless of whether you have stakes in the software as a scientist, as an engineer or both, you have gone from a victorious &lt;strong&gt;“I did it!”&lt;/strong&gt; situation to a depressing &lt;strong&gt;“who has time and interest to help me keep my software alive?”&lt;/strong&gt; situation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If this sounds familiar to you, then the rest of this blog post will help you to do something about it.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;why-are-data-scientists-not-lining-up-to-help&quot;&gt;Why are data scientists not lining up to help?&lt;/h3&gt;
&lt;p&gt;If your software would be as generic as Python’s libraries &lt;a href=&quot;http://www.numpy.org/&quot;&gt;&lt;em&gt;Numpy&lt;/em&gt;&lt;/a&gt; or &lt;a href=&quot;https://keras.io/&quot;&gt;&lt;em&gt;Keras&lt;/em&gt;&lt;/a&gt; or R packages &lt;a href=&quot;http://ggplot2.org/&quot;&gt;&lt;em&gt;ggplot2&lt;/em&gt;&lt;/a&gt; or &lt;a href=&quot;http://topepo.github.io/caret/index.html&quot;&gt;&lt;em&gt;caret&lt;/em&gt;&lt;/a&gt; then data scientists might be lining up by now to help you maintain and improve your software. However, the reality is different: Your software is so much tailored to your field of science that those data scientists are less likely to be interested. Note that I am referring to them as data scientists for convenience, this includes anyone outside your field of research with software development expertise.&lt;/p&gt;
&lt;p&gt;Your software may have been designed for a relatively small community of just a few hundred non-software savvy scientists rather than the thousands of software savvy users (if not more) that are common to generic types of software as mentioned above. With such a user base it may be &lt;em&gt;relatively&lt;/em&gt; easy to find someone able and willing to fix an issue or respond to questions from users. Further, the lack of interest by data scientists to help you may be explained by the fact that your software is not cutting edge from a technological perspective even though it is &lt;em&gt;bleeding edge&lt;/em&gt; from the perspective of your field of research. For example, your software might be the only software in the world able to read in a data format unique to your field of research, account for measurement error using expert-endorsed techniques, and visualize the resulting cleaned data in a way that exactly matches how the big guru of your field introduced it in his/her famous 1970 paper.&lt;/p&gt;
&lt;h3 id=&quot;ten-ways&quot;&gt;Ten ways&lt;/h3&gt;
&lt;p&gt;The ten ways I can think of to keep successful scientific software alive are listed below in no particular order. I wrote this list based on my own experiences from the development and maintenance of &lt;a href=&quot;https://cran.r-project.org/web/packages/GGIR/vignettes/GGIR.html&quot;&gt;R package GGIR&lt;/a&gt;, which has been &lt;a href=&quot;https://github.com/wadpac/GGIR/wiki/Publication-list&quot;&gt;used&lt;/a&gt; by researchers who study human physical activity and sleep. These experiences may not perfectly translate to the nature and context of your software, but I hope there are enough generic elements to make these experiences useful for any type of scientific software.&lt;/p&gt;
&lt;p&gt;When I finished the list I realized that it may be hard to navigate, so to ease navigation I created the visual quadrant as shown below. The quadrant splits the perspective of the engineer from the scientist, and splits options that mainly involve doing the work yourself from the options that are more about involving others.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-h0Ks0DO1TxHuU4NpZDHMg-194d9b03.BrMj_l7V_OrTA8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Map of the ten options as listed below, categorized by the extent you involve others and the extent to which you are a scientist or an engineer&lt;/p&gt;
&lt;h2 id=&quot;research-grants&quot;&gt;Research grants&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WBC-ecWObleDaKUVgBBvGA-0a4aaed6.Cr7Ga7RC_Z16mUqn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Getting a &lt;strong&gt;research grant&lt;/strong&gt; could result in a substantial amount of resources (people time). This option is most realistic if you are a scientist with a position at an academic institution. There may not be funding calls dedicated to scientific software maintenance, but it may be possible to incorporate some time for software maintenance in a grant proposal if it is a logical step towards achieving research goals. We at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; in our capacity as funding body have software sustainability investments explicitly listed in our calls. Scientists are encouraged to set time aside for this within the course of a funded project. Applying for research grants is not necessarily something a software engineer would do, but the engineer could play an important role by encouraging the scientists using the software to account for software maintenance time in their grant proposals. &lt;em&gt;I have had one successful experience with this approach, the research required a new software feature and some bugs to be fixed, by which doing this maintenance work was a justifiable start to the project.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;paid-consultancy&quot;&gt;Paid consultancy&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v5dlR1EtEqS5QR3PY89Uog-b918f99a.DqTLSY6m_1uQsgC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Paid consultancy has the advantage that you, as engineer, make clear to other stakeholders that your time and expertise are not for free. I see three variants on this: (&lt;em&gt;&lt;strong&gt;i) Paid consultancy in spare time&lt;/strong&gt;&lt;/em&gt; — Some tips: you may need to register as a company or as freelancer to obtain a VAT number, make sure to not overload yourself with contractual obligations as even three hours of spare time work per week on top of a full time job can already feel like a burden, note that not all employment contracts allow for spare time consultancy, and Intellectual Property or copyright laws may apply —; &lt;em&gt;&lt;strong&gt;(ii) Paid consultancy as part of your regular job&lt;/strong&gt;&lt;/em&gt; with payments going directly to your employer in exchange for the hours you work on the software — This requires that the work is in line with the mission of the organisation you work for, which may limit the scope of consultancies you can provide —, and; &lt;em&gt;&lt;strong&gt;(iii) Set up a start-up company&lt;/strong&gt;&lt;/em&gt; around the software and find a person to lead it. &lt;em&gt;I have limited but positive personal experiences with the first two options, with a preference for the second. I have no personal experience with the third option, but successful examples I have seen elsewhere include&lt;/em&gt; &lt;a href=&quot;http://audeering.com/technology/opensmile/&quot;&gt;&lt;em&gt;OpenSmile&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://www.scm.com/adf-modeling-suite-2/&quot;&gt;&lt;em&gt;ADF&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;build-developers-community&quot;&gt;Build developers community&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mBRAICGyM8gsE50QiiXhRg-92e4a58c.XaPXv1qO_186kWb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Building a community of software engineers around your scientific software could reduce the work load on individual contributors. However, building a community of engineers around a very research domain specific piece of software could be challenging as I explained in the introduction. &lt;em&gt;My own software has benefited from several unrelated external contributions over the years, but a real ongoing team effort has not been the case for a long time. Very recently a PhD-student in Spain agreed to help me maintain the software. So now we are a community of two persons, which I think is a great step forwards.&lt;/em&gt; Nonetheless, successful examples of (large) community building are possibly more seen for the types of scientific software that have either research domain overarching functionalities like &lt;a href=&quot;http://www.commonwl.org/&quot;&gt;CWL&lt;/a&gt; or Numpy, or are generic enough within a research field to attract multiple developers. So, if you are keen to follow this route then it seems advisable to focus your efforts on the generic features of your software and reach out to people with a potential shared interest in these features. Finally, I would like to point you to a &lt;a href=&quot;http://ivory.idyll.org/blog/2016-sustaining-research-software-development.html&quot;&gt;blog post by C. Titus Brown&lt;/a&gt; from 2016 with a more in dept discussion about community building.&lt;/p&gt;
&lt;h2 id=&quot;student-projects&quot;&gt;Student projects&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lGDKS1oLzO2L5iOcSjYVOw-6fd8574b.z0oxYK_f_2n0fTR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Student projects (students from the research domain) are in my experience ideal for testing the feasibility and documentation of existing software features and for the exploratory development of new software features. If the student project lasts multiple years, like with PhD-students, and if the student has sufficient software skills then it may be realistic to give them more responsibility in the process of software development and maintenance. As I showed in the previous point about community building, PhD-students can be part of your developers community.&lt;/p&gt;
&lt;h2 id=&quot;focus-on-publications&quot;&gt;Focus on publications&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jQtFPqpBNTEWiMWhl3eVZQ-0779e634.Df2twZ_2_2bCCjX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Focus on academic publications about, or using, the software. Thiscould be seen as the conventional academic approach. Here, the objective is that you as a scientist only focus on the software issues that are relevant to your own research, ignoring all other reported issues. This approach may not be ideal from the perspective of other users because not all issues will be addressed. However, the strengths of this classical approach are that it generates evidence to support the validity of specific models or algorithms embedded in your software, it demonstrates feasibility of the software for at least one application area, and it exposes the software to the scientific community it is designed for.&lt;/p&gt;
&lt;h2 id=&quot;outsource-the-work&quot;&gt;Outsource the work&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3-I3Gfj-Edp6SEbtRS38Hw-2ea2ee1f.BSxPw3YL_Z109UlC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Outsourcing to commercial parties could be an option if you, as a scientist, lack access to software engineers, but already have financial resources, and if you have clearly defined software maintenance target(s). The work may be outsourced to any of the many consultancy firms around the world, freelancer websites like &lt;a href=&quot;https://www.freelancer.com/&quot;&gt;https://www.freelancer.com&lt;/a&gt;, or possibly to academics in computer science and software engineering if a match can be found with their research interests. Outsourcing to commercial parties may not be efficient if the work to be done requires a thorough understanding of the science involved and entails time consuming and uncertain research trajectories. &lt;em&gt;The only examples of outsourcing I encountered were not successful,&lt;/em&gt; but if you know successful examples of outsourcing the maintenance of already successful software then please post them in the comments.&lt;/p&gt;
&lt;h2 id=&quot;software-sustainability-guidelines&quot;&gt;Software sustainability guidelines&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_B0FRDnMtWw0b3L6WY0sC1w-0ea41c1c.i8eY4cCU_fO48r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Follow software sustainability guidelines while developing your scientific software as engineer. For example, put your code online and add an open source license, write unit tests, use continuous integration tools, and document your software. Detailed discussions of this topic can be found in the &lt;a href=&quot;https://www.software.ac.uk/software-management-plans&quot;&gt;Software management plans&lt;/a&gt; by the Software Sustainability Institute, the blog posts &lt;a href=&quot;https://danielskatzblog.wordpress.com/2016/09/13/defining-software-sustainability/&quot;&gt;Defining Software Sustainability&lt;/a&gt; and &lt;a href=&quot;https://danielskatzblog.wordpress.com/2015/12/28/hardening-software-vs-making-it-sustainable/&quot;&gt;Hardening software vs making it sustainable&lt;/a&gt; by Daniel S. Katz., a &lt;a href=&quot;https://guide.esciencecenter.nl/software/software_overview.html&quot;&gt;guide&lt;/a&gt; being developed by my colleagues at The Netherlands eScience Center, and a &lt;a href=&quot;https://f1000research.com/articles/5-2000/v1&quot;&gt;paper from 2016 by Haydee Artaza and colleagues&lt;/a&gt;. Following these guidelines will reduce the effort needed to maintain the software, and will make it easier for outsiders to contribute. Needless to say that these guidelines do not generate time (salary) for people to actually do the maintenance. Therefore, following sustainability guidelines is best combined with one or two of the other options mentioned in this blog post. It is important to have clear agreements between scientist and engineer about the sustainability targets within a project. &lt;em&gt;Unfortunately I was not aware of these guidelines when I started developing my own software years ago&lt;/em&gt;, but it is never too late to start prioritizing the guidelines!&lt;/p&gt;
&lt;h2 id=&quot;increase-user-base&quot;&gt;Increase user base&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VnUBtTA390RQW1X4h8eyEw-296ae07e.CAVZ7oi7_1fb4r4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Increase your software’s user base as mentioned in &lt;a href=&quot;https://www.software.ac.uk/blog/2016-10-06-three-tips-software-sustainability-egi-user-forum&quot;&gt;Simon Hettrick’s blog post&lt;/a&gt;: “The more users you have signed up, the more important your software will be to the research community, and the less likely that it will be &lt;em&gt;allowed&lt;/em&gt; to fail”. This is not a direct solution to the question of how to find people time to maintain the software, but it at least pressures a growing number of stakeholders to find a solution. To increase the user base an initial investment from you is required, which could be a challenge on its own. Nonetheless, there may be tricks to grow your user base without too much effort, for example by actively advertising your software if you have not done so before or by joining forces with a similar and/or complementary piece of software like facilitating each others data formats.&lt;/p&gt;
&lt;h2 id=&quot;reduce-cost&quot;&gt;Reduce cost&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GNUvmfwLZ4DYD32WTOVxvw-f2ae77fd.BKdlvy50_HXdze.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Reduce cost as mentioned in &lt;a href=&quot;https://www.software.ac.uk/blog/2016-10-06-three-tips-software-sustainability-egi-user-forum&quot;&gt;Simon Hettrick’s blog post&lt;/a&gt;, which entails that you try to minimize the amount of software components you develop and maintain yourself by aiming to rely as much as possible on off the shelf software &lt;em&gt;developed and maintained by others&lt;/em&gt;, either commercially or open-source. Simon’s blog post provides an excellent reflection on the advantages and disadvantages of this option.&lt;/p&gt;
&lt;h2 id=&quot;unpaid-spare-time-efforts&quot;&gt;Unpaid spare time efforts&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VlaWqK-p0ovD5CI0OmCC8w-65ee47fd.DHddGu4D_Z1q8Tai.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Unpaid spare time effortscan sometimes be an attractive option if you were the engineer who built the software and none of the other options in this list are feasible or immediately available to you. Doing the work in your spare time has the advantage that you can do it whenever it suits you without time pressure. You may even want to see some of the spare time efforts as an investment in your personal skills. Further, spare time efforts can be an effective solution when the amount of work is relatively low and the expected impact is high. The disadvantage of working on the software in your spare time is that it may give other stakeholders the impression that your time and expertise are for free, which is not the case. Lastly, quoting John Wanamaker: “People who cannot find time for recreation are obliged sooner or later to find time for illness”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I hope you found this list of options useful, either for your own scientific software or to learn how you can support someone else’s scientific software.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you think I have missed an option or disagree with the ones I have mentioned: Please leave your thoughts in the comments!&lt;/strong&gt;&lt;/p&gt;</description><pubDate>Mon, 11 Sep 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Imagine, you invest a lot of time and energy in the development of a piece of scientific software. The work pays off and scientists start to use your software in their research. However, the growing user community also produces a stream of help requests, feature requests, and bug reports. What to do about it?&lt;/p&gt;
&lt;h3 id=&quot;keeping-the-software-alive-is-not-a-straightforward-exercise&quot;&gt;Keeping the software alive is not a straightforward exercise&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Software maintenance can be a time consuming activity and is not necessarily a fun or exciting thing to do.&lt;/li&gt;
&lt;li&gt;If you are a scientist, the maintenance of software may not easily translate itself into a new proposal for a research grant. The work required is typically a pile of unrelated issues from a diverse group of stakeholders without a clear overarching and innovative research question.&lt;/li&gt;
&lt;li&gt;If you are the engineer who built the software you may want to move on to work on new technological challenges rather than maintaining the software for the decades to come. On the other hand, if you actually want to continue working on the software, the scientist(s) you work with may not have more funding to pay for your time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1200&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Z3U8YgT-cRE1HWas6sr_EA-021a880f.03x9mJkh_Z1PuKx8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Sources of images: screenshot; stethoscope, bandage, and red cross (all with Creative Commons license)&lt;/p&gt;
&lt;h3 id=&quot;reasons-to-invest-in-your-scientific-software&quot;&gt;Reasons to invest in your scientific software&lt;/h3&gt;
&lt;p&gt;Despite the challenges mentioned above you may have the following reasons to carry on investing in your scientific software:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It can extend the impact of your original work, which could be good for your track record as engineer or as scientist.&lt;/li&gt;
&lt;li&gt;It can secure the reproducibility of the research that has been done with it, which may be essential if you are a scientist (assuming that no other piece of software exists that can guarantee 100% reproducibility compared with your own software).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, regardless of whether you have stakes in the software as a scientist, as an engineer or both, you have gone from a victorious &lt;strong&gt;“I did it!”&lt;/strong&gt; situation to a depressing &lt;strong&gt;“who has time and interest to help me keep my software alive?”&lt;/strong&gt; situation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If this sounds familiar to you, then the rest of this blog post will help you to do something about it.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;why-are-data-scientists-not-lining-up-to-help&quot;&gt;Why are data scientists not lining up to help?&lt;/h3&gt;
&lt;p&gt;If your software would be as generic as Python’s libraries &lt;a href=&quot;http://www.numpy.org/&quot;&gt;&lt;em&gt;Numpy&lt;/em&gt;&lt;/a&gt; or &lt;a href=&quot;https://keras.io/&quot;&gt;&lt;em&gt;Keras&lt;/em&gt;&lt;/a&gt; or R packages &lt;a href=&quot;http://ggplot2.org/&quot;&gt;&lt;em&gt;ggplot2&lt;/em&gt;&lt;/a&gt; or &lt;a href=&quot;http://topepo.github.io/caret/index.html&quot;&gt;&lt;em&gt;caret&lt;/em&gt;&lt;/a&gt; then data scientists might be lining up by now to help you maintain and improve your software. However, the reality is different: Your software is so much tailored to your field of science that those data scientists are less likely to be interested. Note that I am referring to them as data scientists for convenience, this includes anyone outside your field of research with software development expertise.&lt;/p&gt;
&lt;p&gt;Your software may have been designed for a relatively small community of just a few hundred non-software savvy scientists rather than the thousands of software savvy users (if not more) that are common to generic types of software as mentioned above. With such a user base it may be &lt;em&gt;relatively&lt;/em&gt; easy to find someone able and willing to fix an issue or respond to questions from users. Further, the lack of interest by data scientists to help you may be explained by the fact that your software is not cutting edge from a technological perspective even though it is &lt;em&gt;bleeding edge&lt;/em&gt; from the perspective of your field of research. For example, your software might be the only software in the world able to read in a data format unique to your field of research, account for measurement error using expert-endorsed techniques, and visualize the resulting cleaned data in a way that exactly matches how the big guru of your field introduced it in his/her famous 1970 paper.&lt;/p&gt;
&lt;h3 id=&quot;ten-ways&quot;&gt;Ten ways&lt;/h3&gt;
&lt;p&gt;The ten ways I can think of to keep successful scientific software alive are listed below in no particular order. I wrote this list based on my own experiences from the development and maintenance of &lt;a href=&quot;https://cran.r-project.org/web/packages/GGIR/vignettes/GGIR.html&quot;&gt;R package GGIR&lt;/a&gt;, which has been &lt;a href=&quot;https://github.com/wadpac/GGIR/wiki/Publication-list&quot;&gt;used&lt;/a&gt; by researchers who study human physical activity and sleep. These experiences may not perfectly translate to the nature and context of your software, but I hope there are enough generic elements to make these experiences useful for any type of scientific software.&lt;/p&gt;
&lt;p&gt;When I finished the list I realized that it may be hard to navigate, so to ease navigation I created the visual quadrant as shown below. The quadrant splits the perspective of the engineer from the scientist, and splits options that mainly involve doing the work yourself from the options that are more about involving others.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;720&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-h0Ks0DO1TxHuU4NpZDHMg-194d9b03.BrMj_l7V_OrTA8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Map of the ten options as listed below, categorized by the extent you involve others and the extent to which you are a scientist or an engineer&lt;/p&gt;
&lt;h2 id=&quot;research-grants&quot;&gt;Research grants&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WBC-ecWObleDaKUVgBBvGA-0a4aaed6.Cr7Ga7RC_Z16mUqn.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Getting a &lt;strong&gt;research grant&lt;/strong&gt; could result in a substantial amount of resources (people time). This option is most realistic if you are a scientist with a position at an academic institution. There may not be funding calls dedicated to scientific software maintenance, but it may be possible to incorporate some time for software maintenance in a grant proposal if it is a logical step towards achieving research goals. We at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; in our capacity as funding body have software sustainability investments explicitly listed in our calls. Scientists are encouraged to set time aside for this within the course of a funded project. Applying for research grants is not necessarily something a software engineer would do, but the engineer could play an important role by encouraging the scientists using the software to account for software maintenance time in their grant proposals. &lt;em&gt;I have had one successful experience with this approach, the research required a new software feature and some bugs to be fixed, by which doing this maintenance work was a justifiable start to the project.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;paid-consultancy&quot;&gt;Paid consultancy&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v5dlR1EtEqS5QR3PY89Uog-b918f99a.DqTLSY6m_1uQsgC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Paid consultancy has the advantage that you, as engineer, make clear to other stakeholders that your time and expertise are not for free. I see three variants on this: (&lt;em&gt;&lt;strong&gt;i) Paid consultancy in spare time&lt;/strong&gt;&lt;/em&gt; — Some tips: you may need to register as a company or as freelancer to obtain a VAT number, make sure to not overload yourself with contractual obligations as even three hours of spare time work per week on top of a full time job can already feel like a burden, note that not all employment contracts allow for spare time consultancy, and Intellectual Property or copyright laws may apply —; &lt;em&gt;&lt;strong&gt;(ii) Paid consultancy as part of your regular job&lt;/strong&gt;&lt;/em&gt; with payments going directly to your employer in exchange for the hours you work on the software — This requires that the work is in line with the mission of the organisation you work for, which may limit the scope of consultancies you can provide —, and; &lt;em&gt;&lt;strong&gt;(iii) Set up a start-up company&lt;/strong&gt;&lt;/em&gt; around the software and find a person to lead it. &lt;em&gt;I have limited but positive personal experiences with the first two options, with a preference for the second. I have no personal experience with the third option, but successful examples I have seen elsewhere include&lt;/em&gt; &lt;a href=&quot;http://audeering.com/technology/opensmile/&quot;&gt;&lt;em&gt;OpenSmile&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://www.scm.com/adf-modeling-suite-2/&quot;&gt;&lt;em&gt;ADF&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;build-developers-community&quot;&gt;Build developers community&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mBRAICGyM8gsE50QiiXhRg-92e4a58c.XaPXv1qO_186kWb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Building a community of software engineers around your scientific software could reduce the work load on individual contributors. However, building a community of engineers around a very research domain specific piece of software could be challenging as I explained in the introduction. &lt;em&gt;My own software has benefited from several unrelated external contributions over the years, but a real ongoing team effort has not been the case for a long time. Very recently a PhD-student in Spain agreed to help me maintain the software. So now we are a community of two persons, which I think is a great step forwards.&lt;/em&gt; Nonetheless, successful examples of (large) community building are possibly more seen for the types of scientific software that have either research domain overarching functionalities like &lt;a href=&quot;http://www.commonwl.org/&quot;&gt;CWL&lt;/a&gt; or Numpy, or are generic enough within a research field to attract multiple developers. So, if you are keen to follow this route then it seems advisable to focus your efforts on the generic features of your software and reach out to people with a potential shared interest in these features. Finally, I would like to point you to a &lt;a href=&quot;http://ivory.idyll.org/blog/2016-sustaining-research-software-development.html&quot;&gt;blog post by C. Titus Brown&lt;/a&gt; from 2016 with a more in dept discussion about community building.&lt;/p&gt;
&lt;h2 id=&quot;student-projects&quot;&gt;Student projects&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_lGDKS1oLzO2L5iOcSjYVOw-6fd8574b.z0oxYK_f_2n0fTR.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Student projects (students from the research domain) are in my experience ideal for testing the feasibility and documentation of existing software features and for the exploratory development of new software features. If the student project lasts multiple years, like with PhD-students, and if the student has sufficient software skills then it may be realistic to give them more responsibility in the process of software development and maintenance. As I showed in the previous point about community building, PhD-students can be part of your developers community.&lt;/p&gt;
&lt;h2 id=&quot;focus-on-publications&quot;&gt;Focus on publications&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_jQtFPqpBNTEWiMWhl3eVZQ-0779e634.Df2twZ_2_2bCCjX.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Focus on academic publications about, or using, the software. Thiscould be seen as the conventional academic approach. Here, the objective is that you as a scientist only focus on the software issues that are relevant to your own research, ignoring all other reported issues. This approach may not be ideal from the perspective of other users because not all issues will be addressed. However, the strengths of this classical approach are that it generates evidence to support the validity of specific models or algorithms embedded in your software, it demonstrates feasibility of the software for at least one application area, and it exposes the software to the scientific community it is designed for.&lt;/p&gt;
&lt;h2 id=&quot;outsource-the-work&quot;&gt;Outsource the work&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3-I3Gfj-Edp6SEbtRS38Hw-2ea2ee1f.BSxPw3YL_Z109UlC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Outsourcing to commercial parties could be an option if you, as a scientist, lack access to software engineers, but already have financial resources, and if you have clearly defined software maintenance target(s). The work may be outsourced to any of the many consultancy firms around the world, freelancer websites like &lt;a href=&quot;https://www.freelancer.com/&quot;&gt;https://www.freelancer.com&lt;/a&gt;, or possibly to academics in computer science and software engineering if a match can be found with their research interests. Outsourcing to commercial parties may not be efficient if the work to be done requires a thorough understanding of the science involved and entails time consuming and uncertain research trajectories. &lt;em&gt;The only examples of outsourcing I encountered were not successful,&lt;/em&gt; but if you know successful examples of outsourcing the maintenance of already successful software then please post them in the comments.&lt;/p&gt;
&lt;h2 id=&quot;software-sustainability-guidelines&quot;&gt;Software sustainability guidelines&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_B0FRDnMtWw0b3L6WY0sC1w-0ea41c1c.i8eY4cCU_fO48r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Follow software sustainability guidelines while developing your scientific software as engineer. For example, put your code online and add an open source license, write unit tests, use continuous integration tools, and document your software. Detailed discussions of this topic can be found in the &lt;a href=&quot;https://www.software.ac.uk/software-management-plans&quot;&gt;Software management plans&lt;/a&gt; by the Software Sustainability Institute, the blog posts &lt;a href=&quot;https://danielskatzblog.wordpress.com/2016/09/13/defining-software-sustainability/&quot;&gt;Defining Software Sustainability&lt;/a&gt; and &lt;a href=&quot;https://danielskatzblog.wordpress.com/2015/12/28/hardening-software-vs-making-it-sustainable/&quot;&gt;Hardening software vs making it sustainable&lt;/a&gt; by Daniel S. Katz., a &lt;a href=&quot;https://guide.esciencecenter.nl/software/software_overview.html&quot;&gt;guide&lt;/a&gt; being developed by my colleagues at The Netherlands eScience Center, and a &lt;a href=&quot;https://f1000research.com/articles/5-2000/v1&quot;&gt;paper from 2016 by Haydee Artaza and colleagues&lt;/a&gt;. Following these guidelines will reduce the effort needed to maintain the software, and will make it easier for outsiders to contribute. Needless to say that these guidelines do not generate time (salary) for people to actually do the maintenance. Therefore, following sustainability guidelines is best combined with one or two of the other options mentioned in this blog post. It is important to have clear agreements between scientist and engineer about the sustainability targets within a project. &lt;em&gt;Unfortunately I was not aware of these guidelines when I started developing my own software years ago&lt;/em&gt;, but it is never too late to start prioritizing the guidelines!&lt;/p&gt;
&lt;h2 id=&quot;increase-user-base&quot;&gt;Increase user base&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VnUBtTA390RQW1X4h8eyEw-296ae07e.CAVZ7oi7_1fb4r4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Increase your software’s user base as mentioned in &lt;a href=&quot;https://www.software.ac.uk/blog/2016-10-06-three-tips-software-sustainability-egi-user-forum&quot;&gt;Simon Hettrick’s blog post&lt;/a&gt;: “The more users you have signed up, the more important your software will be to the research community, and the less likely that it will be &lt;em&gt;allowed&lt;/em&gt; to fail”. This is not a direct solution to the question of how to find people time to maintain the software, but it at least pressures a growing number of stakeholders to find a solution. To increase the user base an initial investment from you is required, which could be a challenge on its own. Nonetheless, there may be tricks to grow your user base without too much effort, for example by actively advertising your software if you have not done so before or by joining forces with a similar and/or complementary piece of software like facilitating each others data formats.&lt;/p&gt;
&lt;h2 id=&quot;reduce-cost&quot;&gt;Reduce cost&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_GNUvmfwLZ4DYD32WTOVxvw-f2ae77fd.BKdlvy50_HXdze.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Reduce cost as mentioned in &lt;a href=&quot;https://www.software.ac.uk/blog/2016-10-06-three-tips-software-sustainability-egi-user-forum&quot;&gt;Simon Hettrick’s blog post&lt;/a&gt;, which entails that you try to minimize the amount of software components you develop and maintain yourself by aiming to rely as much as possible on off the shelf software &lt;em&gt;developed and maintained by others&lt;/em&gt;, either commercially or open-source. Simon’s blog post provides an excellent reflection on the advantages and disadvantages of this option.&lt;/p&gt;
&lt;h2 id=&quot;unpaid-spare-time-efforts&quot;&gt;Unpaid spare time efforts&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VlaWqK-p0ovD5CI0OmCC8w-65ee47fd.DHddGu4D_Z1q8Tai.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Unpaid spare time effortscan sometimes be an attractive option if you were the engineer who built the software and none of the other options in this list are feasible or immediately available to you. Doing the work in your spare time has the advantage that you can do it whenever it suits you without time pressure. You may even want to see some of the spare time efforts as an investment in your personal skills. Further, spare time efforts can be an effective solution when the amount of work is relatively low and the expected impact is high. The disadvantage of working on the software in your spare time is that it may give other stakeholders the impression that your time and expertise are for free, which is not the case. Lastly, quoting John Wanamaker: “People who cannot find time for recreation are obliged sooner or later to find time for illness”.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I hope you found this list of options useful, either for your own scientific software or to learn how you can support someone else’s scientific software.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you think I have missed an option or disagree with the ones I have mentioned: Please leave your thoughts in the comments!&lt;/strong&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Z3U8YgT-cRE1HWas6sr_EA-021a880f.03x9mJkh.jpeg" medium="image"/><author>Vincent van Hees</author></item><item><title>predicting temperatures in your street</title><link>https://blog2.esciencecenter.nl/posts/2017-08-23---predicting-temperatures-in-your-street</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-08-23---predicting-temperatures-in-your-street</guid><description>&lt;p&gt;The next big thing in weather forecasting&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QMUb9qjiCmHbWME3fqD-Ow-14d2ff44.BWglpMn__YgSn8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example of a high resolution weather forecast at 500m (right) and 100m (left) resolution&lt;/p&gt;
&lt;p&gt;eScience Research Engineers at the Netherlands eScience Center are collaborating with a team of climate scientists to develop a novel approach to predict temperatures in your own street. Before we go into detail on why this is relevant and how we did this, let’s first talk some general history about the why and how of weather forecasting.&lt;/p&gt;
&lt;h3 id=&quot;history-of-weather-forecasting&quot;&gt;History of weather forecasting&lt;/h3&gt;
&lt;p&gt;In the beginning of the 20th century major advances were made in atmospheric physics. It was argued by Vilheml Bjerknes (1862–1951) that numerical weather forecasting should be considered an initial value problem and could be solved by integrating a set of equations. Although he made a small mistake in the set of equations he defined, which was later corrected by Lewis Fry Richardson (1881–1953), Bjerknes laid the foundation for the weather forecasts as we know them today.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;220&quot; height=&quot;351&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Px3hBxi00hpR5Pdn-8e42a317.BX2XWcOV_n9dsw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vilheml Bjerknes&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;253&quot; height=&quot;368&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_C0Fm7w8DQTw9JWie-ee23ba0a.BjhHkMs7_1l1HQF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lewis Fry Richardson&lt;/p&gt;
&lt;p&gt;Richardson then went on to simplify the governing equations and produce the first albeit unrealistic, hand calculated, numerically calculated weather forecast. Because of the large amount of calculations involved it took him six weeks to produce an eight hour weather forecast for one single location. The next big step in the history of numerical weather forecasting was made by the introduction of digital computers in the 1940s. After World War II, weather forecasting was one of the first major applications of digital computers. With the availability of more compute power in more recent years, numerical weather models continued to evolve and became more and more complex.&lt;/p&gt;
&lt;p&gt;Today, we are able to make fairly accurate weather forecasts 7 days in advance. However, all forecasts are still pretty coarse. In reality, weather is pretty fine-grained — it may be raining in your street but dry in the next. Could we predict weather on such a fine-grained scale?&lt;/p&gt;
&lt;h3 id=&quot;why-do-we-need-weather-forecasts-for-the-urban-area&quot;&gt;Why do we need weather forecasts for the urban area&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;607&quot; height=&quot;642&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TMfqkiMQgm-ApTl-q6iqWA-e8a35b9e.qudYIaPx_Z1TXz40.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Traditional weather forecast (source: KNMI)&lt;/p&gt;
&lt;p&gt;Traditional weather forecasts as we all know them from the evening news, although reliable enough to plan an outdoor trip, predict average temperatures in rural areas of several kilometers by size. In cities, where most people live and work, temperatures may be several degrees Celsius higher due to lots of activities going on that produce heat, and building materials and structures that insulate or hold the heat: the city doesn’t release its heat as fast as the surrounding country side. This is called the &lt;em&gt;urban heat island&lt;/em&gt; effect. Increased daytime temperatures, reduced nighttime cooling, and higher air pollution levels associated with urban heat islands can affect human health by contributing to general discomfort, respiratory difficulties, exhaustion, and other heat-related health issues.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;445&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Vl6g_JD4nnBU6UZm-46bafcd8.rqVK_62w_ZsRtrG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Urban heat island temperature profile&lt;/p&gt;
&lt;h3 id=&quot;computational-challenge&quot;&gt;Computational challenge&lt;/h3&gt;
&lt;p&gt;At the Netherlands eScience Center we have two projects related to the subject of weather forecasts for urban areas: Summer in the City (finished) and the follow-up project ERA-URBAN (ongoing). Both projects are in collaboration with the Meteorology and Air Quality group at Wageningen University. In these projects the Weather Research Forecasting (WRF) model, a so-called limited area (regional) model (LAM), is used. Limited area models work by increasing the resolution of a global model in a small, limited area of interest. Such an area could cover for example the northwestern part of Europe. The weather calculated by the global model is used as input at the edges of the regional model for factors such as temperature, wind, and sea surface temperature. The global model determines the very large scale effects of atmospheric and land surface processes, while the regional model adds regional refinement by resolving the local impacts given small scale information about orography (land height), land-sea contrasts, land use, and (optionally) cities. Thus, limited area models downscale the weather prediction from global weather models with regional refinements.&lt;/p&gt;
&lt;p&gt;With the large scale weather and a regional model, we are now able to set up a weather forecast for our region of interest. However, an urban weather forecast should ideally be at a resolution in the order of a few hundred meters or higher. Running a limited area model for the whole of Europe (or even the whole of the Netherlands) at this resolution is still computationally too expensive. A typical way to overcome this is by using nested grids: the model creates a copy of itself on a subdomain at a higher resolution. In our case we went for 4 nested grids, going from low to high resolution: 12.5km — 2.5km — 500m — 100m. This is shown in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;785&quot; height=&quot;738&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_F7iC9xWmKYtNasus-d47005dd.CVEjjRdR_19YpcP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Overview of the forecast domains: The 100m resolution domain is centered on the city of Amsterdam (domain 4). The next domain, at 500m resolution, covers the Randstad (domain 3). The whole of the Netherlands is covered at 2.5 km resoluton (domain 2). The outer domain (at 12.5 km resolution) covers a large part of northern Europe.&lt;/p&gt;
&lt;h3 id=&quot;detailed-description-of-the-area&quot;&gt;Detailed description of the area&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5ravkEZ1j4jjCjDN5tiBsg-80e2a088.C-zlwhQn_Z8i0eN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Algemene hoogtekaart Nederland (AHN) (source: &lt;a href=&quot;https://ahn.arcgisonline.nl/ahnviewer/&quot;&gt;https://ahn.arcgisonline.nl/ahnviewer/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;Typically, the land surface description of the area included with the model comes in a much coarser resolution than what is needed for urban weather forecasts. Therefore, the next step is adding detail to the description of the area. The accuracy of land surface parameters, including topography, land use, vegetation cover, and soil type, influence the modeled land surface processes and characteristics of the atmospheric boundary layer (lowest part of the atmosphere). These variables greatly influence the model performance and directly determine surface parameters such as albedo, emissivity, roughness, porosity and thermal conductivity of the soil. Examples of data sources that were used in this project include NDVI (vegetation) maps (available from e.g. Landsat 7 ETM+ or Digitale Kleuren Luchtfoto Nederland (DKLN)), accurate information on the location and shape of the buildings (&lt;a href=&quot;https://www.kadaster.nl/web/artikel/productartikel/TOP10NL.htm&quot;&gt;TOP10NL&lt;/a&gt;), accurate building heights (&lt;a href=&quot;http://www.ahn.nl/&quot;&gt;AHN&lt;/a&gt;), landuse classes (&lt;a href=&quot;https://www.kadaster.nl/web/artikel/productartikel/TOP10NL.htm&quot;&gt;TOP10NL&lt;/a&gt;) and soil types (&lt;a href=&quot;http://www.wur.nl/nl/show/Grondsoortenkaart.htm&quot;&gt;Grondsoortenkaart&lt;/a&gt;), all at very high resolution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;777&quot; height=&quot;1099&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6ynQLyvXu9mL_cDoCskRpg-1aa525bc.D6hX8VJ-_Z1jFey3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1458&quot; height=&quot;626&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DXkFBTKvVf41QPIuf7PLWA-aa597f3c.BhtW1B8J_Z1MWKj9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Soil types (left, source: ALTERRA ) and land use classes (right)&lt;/p&gt;
&lt;h3 id=&quot;finetuning&quot;&gt;Finetuning&lt;/h3&gt;
&lt;p&gt;Three things remain to be done. Firstly, the sea surface temperatures and river temperatures that follow from the global model that are used as boundary conditions are not very accurate. For a city near the coast, such as Amsterdam, this affects the forecasted temperature. Therefore, we manually set these to more accurate values as obtained from &lt;a href=&quot;https://www.rijkswaterstaat.nl/apps/geoservices/rwsnl/awd.php?mode=html&amp;#x26;projecttype=watertemperatuur&quot;&gt;Rijkswaterstaat&lt;/a&gt;. Secondly, we need to make sure that the heat in the buildings is retained between forecast runs in order to have a more accurate representation of the urban heat island effect. Thirdly, results may be improved even further by assimilating (crowd-sourced) local weather observations into the initial conditions of the regional forecast run (currently this is still an area of research in the ERA-URBAN project and not implemented for the &lt;a href=&quot;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&quot;&gt;operational forecast&lt;/a&gt;). Finally, to automate the whole workflow and automatically create a weather forecast at a daily basis we need a workflow engine. Here we adopted &lt;a href=&quot;https://cylc.github.io/cylc/&quot;&gt;Cylc&lt;/a&gt;, but of course others can be used as well.&lt;/p&gt;
&lt;h3 id=&quot;check-out-the-end-result&quot;&gt;Check out the end result!&lt;/h3&gt;
&lt;p&gt;An example of a 2-day forecast on the 500-m domain of a hot summer day in June 2017 is included in the figure below. For a live daily forecast on all four domains, please visit &lt;a href=&quot;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&quot;&gt;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&lt;/a&gt; (available during the northern hemisphere summer months).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QMUb9qjiCmHbWME3fqD-Ow-14d2ff44.BWglpMn__YgSn8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example temperature forecast for the 500m (left) and 100m (right) domain. Daily temperature forecast for all domains is available via &lt;a href=&quot;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&quot;&gt;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&lt;/a&gt; during the summer months.&lt;/p&gt;</description><pubDate>Wed, 23 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The next big thing in weather forecasting&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QMUb9qjiCmHbWME3fqD-Ow-14d2ff44.BWglpMn__YgSn8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example of a high resolution weather forecast at 500m (right) and 100m (left) resolution&lt;/p&gt;
&lt;p&gt;eScience Research Engineers at the Netherlands eScience Center are collaborating with a team of climate scientists to develop a novel approach to predict temperatures in your own street. Before we go into detail on why this is relevant and how we did this, let’s first talk some general history about the why and how of weather forecasting.&lt;/p&gt;
&lt;h3 id=&quot;history-of-weather-forecasting&quot;&gt;History of weather forecasting&lt;/h3&gt;
&lt;p&gt;In the beginning of the 20th century major advances were made in atmospheric physics. It was argued by Vilheml Bjerknes (1862–1951) that numerical weather forecasting should be considered an initial value problem and could be solved by integrating a set of equations. Although he made a small mistake in the set of equations he defined, which was later corrected by Lewis Fry Richardson (1881–1953), Bjerknes laid the foundation for the weather forecasts as we know them today.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;220&quot; height=&quot;351&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Px3hBxi00hpR5Pdn-8e42a317.BX2XWcOV_n9dsw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Vilheml Bjerknes&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;253&quot; height=&quot;368&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_C0Fm7w8DQTw9JWie-ee23ba0a.BjhHkMs7_1l1HQF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lewis Fry Richardson&lt;/p&gt;
&lt;p&gt;Richardson then went on to simplify the governing equations and produce the first albeit unrealistic, hand calculated, numerically calculated weather forecast. Because of the large amount of calculations involved it took him six weeks to produce an eight hour weather forecast for one single location. The next big step in the history of numerical weather forecasting was made by the introduction of digital computers in the 1940s. After World War II, weather forecasting was one of the first major applications of digital computers. With the availability of more compute power in more recent years, numerical weather models continued to evolve and became more and more complex.&lt;/p&gt;
&lt;p&gt;Today, we are able to make fairly accurate weather forecasts 7 days in advance. However, all forecasts are still pretty coarse. In reality, weather is pretty fine-grained — it may be raining in your street but dry in the next. Could we predict weather on such a fine-grained scale?&lt;/p&gt;
&lt;h3 id=&quot;why-do-we-need-weather-forecasts-for-the-urban-area&quot;&gt;Why do we need weather forecasts for the urban area&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;607&quot; height=&quot;642&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_TMfqkiMQgm-ApTl-q6iqWA-e8a35b9e.qudYIaPx_Z1TXz40.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Traditional weather forecast (source: KNMI)&lt;/p&gt;
&lt;p&gt;Traditional weather forecasts as we all know them from the evening news, although reliable enough to plan an outdoor trip, predict average temperatures in rural areas of several kilometers by size. In cities, where most people live and work, temperatures may be several degrees Celsius higher due to lots of activities going on that produce heat, and building materials and structures that insulate or hold the heat: the city doesn’t release its heat as fast as the surrounding country side. This is called the &lt;em&gt;urban heat island&lt;/em&gt; effect. Increased daytime temperatures, reduced nighttime cooling, and higher air pollution levels associated with urban heat islands can affect human health by contributing to general discomfort, respiratory difficulties, exhaustion, and other heat-related health issues.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;445&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_Vl6g_JD4nnBU6UZm-46bafcd8.rqVK_62w_ZsRtrG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Urban heat island temperature profile&lt;/p&gt;
&lt;h3 id=&quot;computational-challenge&quot;&gt;Computational challenge&lt;/h3&gt;
&lt;p&gt;At the Netherlands eScience Center we have two projects related to the subject of weather forecasts for urban areas: Summer in the City (finished) and the follow-up project ERA-URBAN (ongoing). Both projects are in collaboration with the Meteorology and Air Quality group at Wageningen University. In these projects the Weather Research Forecasting (WRF) model, a so-called limited area (regional) model (LAM), is used. Limited area models work by increasing the resolution of a global model in a small, limited area of interest. Such an area could cover for example the northwestern part of Europe. The weather calculated by the global model is used as input at the edges of the regional model for factors such as temperature, wind, and sea surface temperature. The global model determines the very large scale effects of atmospheric and land surface processes, while the regional model adds regional refinement by resolving the local impacts given small scale information about orography (land height), land-sea contrasts, land use, and (optionally) cities. Thus, limited area models downscale the weather prediction from global weather models with regional refinements.&lt;/p&gt;
&lt;p&gt;With the large scale weather and a regional model, we are now able to set up a weather forecast for our region of interest. However, an urban weather forecast should ideally be at a resolution in the order of a few hundred meters or higher. Running a limited area model for the whole of Europe (or even the whole of the Netherlands) at this resolution is still computationally too expensive. A typical way to overcome this is by using nested grids: the model creates a copy of itself on a subdomain at a higher resolution. In our case we went for 4 nested grids, going from low to high resolution: 12.5km — 2.5km — 500m — 100m. This is shown in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;785&quot; height=&quot;738&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/0_F7iC9xWmKYtNasus-d47005dd.CVEjjRdR_19YpcP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Overview of the forecast domains: The 100m resolution domain is centered on the city of Amsterdam (domain 4). The next domain, at 500m resolution, covers the Randstad (domain 3). The whole of the Netherlands is covered at 2.5 km resoluton (domain 2). The outer domain (at 12.5 km resolution) covers a large part of northern Europe.&lt;/p&gt;
&lt;h3 id=&quot;detailed-description-of-the-area&quot;&gt;Detailed description of the area&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;683&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5ravkEZ1j4jjCjDN5tiBsg-80e2a088.C-zlwhQn_Z8i0eN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Algemene hoogtekaart Nederland (AHN) (source: &lt;a href=&quot;https://ahn.arcgisonline.nl/ahnviewer/&quot;&gt;https://ahn.arcgisonline.nl/ahnviewer/&lt;/a&gt; )&lt;/p&gt;
&lt;p&gt;Typically, the land surface description of the area included with the model comes in a much coarser resolution than what is needed for urban weather forecasts. Therefore, the next step is adding detail to the description of the area. The accuracy of land surface parameters, including topography, land use, vegetation cover, and soil type, influence the modeled land surface processes and characteristics of the atmospheric boundary layer (lowest part of the atmosphere). These variables greatly influence the model performance and directly determine surface parameters such as albedo, emissivity, roughness, porosity and thermal conductivity of the soil. Examples of data sources that were used in this project include NDVI (vegetation) maps (available from e.g. Landsat 7 ETM+ or Digitale Kleuren Luchtfoto Nederland (DKLN)), accurate information on the location and shape of the buildings (&lt;a href=&quot;https://www.kadaster.nl/web/artikel/productartikel/TOP10NL.htm&quot;&gt;TOP10NL&lt;/a&gt;), accurate building heights (&lt;a href=&quot;http://www.ahn.nl/&quot;&gt;AHN&lt;/a&gt;), landuse classes (&lt;a href=&quot;https://www.kadaster.nl/web/artikel/productartikel/TOP10NL.htm&quot;&gt;TOP10NL&lt;/a&gt;) and soil types (&lt;a href=&quot;http://www.wur.nl/nl/show/Grondsoortenkaart.htm&quot;&gt;Grondsoortenkaart&lt;/a&gt;), all at very high resolution.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;777&quot; height=&quot;1099&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_6ynQLyvXu9mL_cDoCskRpg-1aa525bc.D6hX8VJ-_Z1jFey3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1458&quot; height=&quot;626&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_DXkFBTKvVf41QPIuf7PLWA-aa597f3c.BhtW1B8J_Z1MWKj9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Soil types (left, source: ALTERRA ) and land use classes (right)&lt;/p&gt;
&lt;h3 id=&quot;finetuning&quot;&gt;Finetuning&lt;/h3&gt;
&lt;p&gt;Three things remain to be done. Firstly, the sea surface temperatures and river temperatures that follow from the global model that are used as boundary conditions are not very accurate. For a city near the coast, such as Amsterdam, this affects the forecasted temperature. Therefore, we manually set these to more accurate values as obtained from &lt;a href=&quot;https://www.rijkswaterstaat.nl/apps/geoservices/rwsnl/awd.php?mode=html&amp;#x26;projecttype=watertemperatuur&quot;&gt;Rijkswaterstaat&lt;/a&gt;. Secondly, we need to make sure that the heat in the buildings is retained between forecast runs in order to have a more accurate representation of the urban heat island effect. Thirdly, results may be improved even further by assimilating (crowd-sourced) local weather observations into the initial conditions of the regional forecast run (currently this is still an area of research in the ERA-URBAN project and not implemented for the &lt;a href=&quot;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&quot;&gt;operational forecast&lt;/a&gt;). Finally, to automate the whole workflow and automatically create a weather forecast at a daily basis we need a workflow engine. Here we adopted &lt;a href=&quot;https://cylc.github.io/cylc/&quot;&gt;Cylc&lt;/a&gt;, but of course others can be used as well.&lt;/p&gt;
&lt;h3 id=&quot;check-out-the-end-result&quot;&gt;Check out the end result!&lt;/h3&gt;
&lt;p&gt;An example of a 2-day forecast on the 500-m domain of a hot summer day in June 2017 is included in the figure below. For a live daily forecast on all four domains, please visit &lt;a href=&quot;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&quot;&gt;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&lt;/a&gt; (available during the northern hemisphere summer months).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1024&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_QMUb9qjiCmHbWME3fqD-Ow-14d2ff44.BWglpMn__YgSn8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Example temperature forecast for the 500m (left) and 100m (right) domain. Daily temperature forecast for all domains is available via &lt;a href=&quot;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&quot;&gt;http://www.met.wur.nl/Summerinthecity/pages/dailyforecasts.html&lt;/a&gt; during the summer months.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/0_Px3hBxi00hpR5Pdn-8e42a317.BX2XWcOV.jpg" medium="image"/><author>Ronald van Haren</author></item><item><title>Reading News, visually.</title><link>https://blog2.esciencecenter.nl/posts/2017-08-07---reading-news-visually</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-08-07---reading-news-visually</guid><description>&lt;h2 id=&quot;the-storyteller-application-gives-you-a-different-perspective-on-the-news&quot;&gt;The StoryTeller application gives you a different perspective on the news&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3134&quot; height=&quot;853&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_36VvqJkQdxzrbozNMfi0og-054975ba.1mYNRAnh_2RpM1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A screenshot from the StoryTeller application. Shown here is a co-participation graph for entities that participate in events together with Apple_inc.&lt;/p&gt;
&lt;p&gt;When I started working with the Computational Linguistics group of the &lt;a href=&quot;https://www.vu.nl/en/&quot;&gt;VU University Amsterdam&lt;/a&gt; two years ago, I didn’t know much about Natural Language Processing. I used to think that communicating human beings were pretty understandable, especially in everyday news reporting. I’ve since learned that I was terribly wrong.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Computers do not understand us.&lt;/strong&gt; Human language is so abstract and full of context, innuendo and cultural references, that to an observer without the same background (the computer, in this case) we are nearly impossible to understand.&lt;/p&gt;
&lt;h3 id=&quot;shaka-when-the-walls-fell&quot;&gt;Shaka, when the walls fell.&lt;/h3&gt;
&lt;p&gt;As an example of an exploration of cultural differences and understanding language, I’d like to point you to an episode of &lt;a href=&quot;https://en.wikipedia.org/wiki/Star_Trek:_The_Next_Generation&quot;&gt;Star Trek: The next Generation&lt;/a&gt; called “ &lt;a href=&quot;http://memory-alpha.wikia.com/wiki/Darmok_(episode)&quot;&gt;Darmok&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;This scene from “Darmok” illustrates the difficulty of ‘speaking’ with someone that does not share your cultural references and language structure.&lt;/p&gt;
&lt;p&gt;In this episode, the English-speaking captain of the star ship Enterprise is forced to communicate with an alien race with a completely different language. The aliens’ words are translated to English, but they make no sense at all because they are completely speaking in metaphors.&lt;/p&gt;
&lt;p&gt;Since this is an episodic series, the impasse is of course resolved eventually, but the point is well made.&lt;/p&gt;
&lt;p&gt;Human(oid) communication is a very difficult problem indeed.&lt;/p&gt;
&lt;h3 id=&quot;natural-language-processing&quot;&gt;Natural Language Processing&lt;/h3&gt;
&lt;p&gt;This is where science must find a solution. If we ever want computers to answer complex queries from humans (or even make us a cup of Earl Grey on voice command), we have to make computers and people understand each other.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.8013&quot;&gt;Great&lt;/a&gt; &lt;a href=&quot;https://arxiv.org/abs/1301.3781&quot;&gt;strides&lt;/a&gt; &lt;a href=&quot;http://dl.acm.org/citation.cfm?doid=2133806.2133826&quot;&gt;have&lt;/a&gt; already been made, but many challenges persist. One of those challenges is event-based data like news stories. While literary works are usually well researched works of knowledge or stories with a well defined structure, the news is fraught with an extra layer of challenges because of its time-based nature. The facts of today might be the fake news of tomorrow, and opinions of politicians and other prominent speakers may shift over the course of time. &lt;a href=&quot;https://www.esciencecenter.nl/project/mining-shifting-concepts-through-time-shico&quot;&gt;Even concepts themselves are not as stable as you might think.&lt;/a&gt; The news and its complexities is the chosen topic of research for the group of professor &lt;a href=&quot;http://vossen.info/&quot;&gt;Piek Vossen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5iintDhL1d_w8f-yQbn_4Q-e4f84195.DAyteGwC_OlqHm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;newsreader&quot;&gt;NewsReader&lt;/h3&gt;
&lt;p&gt;Enter the &lt;a href=&quot;http://www.newsreader-project.eu/&quot;&gt;NewsReader&lt;/a&gt; project, a European-funded multi-partner research project that aims to help humanity overcome at least some of the challenges as described above. To help improve the communication between computers and people, a software pipeline was constructed. This pipeline is a collection of software packages dealing with specific parts of human language, which can be connected to form a more complete picture of stories in newspapers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;390&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_71JalaUtdVxaYOSUEWuIZg-54f4ab0a.ZwXFsmHL_1X0gSb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A visual representation of the NewsReader pipeline.&lt;/p&gt;
&lt;p&gt;The newsreader pipeline extracts what happened to whom, when and where from billions of news stories, company databases and biographies and stores them in a structured database, enabling more precise search over this immense stack of information. It supports multiple languages (English, Spanish, Italian and Dutch) and allows its users to find complex interconnections between participants, events and perspectives on these events.&lt;/p&gt;
&lt;p&gt;Before I joined the project, however, a new and exciting challenge appeared. The output of the pipeline was too complex to understand &lt;em&gt;for humans.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;word-soup&quot;&gt;Word soup&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1362&quot; height=&quot;675&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Qjqiyw5Yu6w4fii1ZR0bUg-0508871e.CMb5Zefo_1U5wFb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://compsocsci.blogspot.nl/2012/06/word-cloud-of-knight-news-challenge.html&quot;&gt;http://compsocsci.blogspot.nl/2012/06/word-cloud-of-knight-news-challenge.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A term usually applied to the inane utterings of politicians &lt;a href=&quot;http://theslot.jezebel.com/kellyanne-conway-is-losing-her-hold-on-talking-head-pro-1792391189&quot;&gt;or their representatives&lt;/a&gt;, it quite accurately describes the issues with scientific output in computational linguistics. At least to us humans, English speaking humans, or me alone, depending on how narrow this particular selection is made. &lt;em&gt;On second thought, let me explain.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Before new users start to make sense of the output of the NewsReader pipeline, they encounter an enormous mass of words, arranged in mentions (instances of events that are mentioned in the news) and their attributes. Dates, cited persons, authors, event participants, labels, groups, perspectives etc. All neatly arranged in a computer-readable data structure. Needless to say, I didn’t understand any of its significance until it was explained to me.&lt;/p&gt;
&lt;h3 id=&quot;climax-events-and-storylines&quot;&gt;Climax events and Storylines&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;555&quot; height=&quot;279&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0fj2wCG0ht98nXmD8Mex7g-228f3eaa.9hfTASoW_1eeHE4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The pipeline spews forth a slurry of events and their mentions in the news, but fortunately there is now some structure to the data. Stories have been defined by defining a ‘climax’ event, and connecting it to other events through their participants, labels, groups and other metadata. These stories should follow the ancient structure of all human stories, at the very least since the first recorded epic of &lt;a href=&quot;https://en.wikipedia.org/wiki/Gilgamesh&quot;&gt;Gilgamesh&lt;/a&gt;. Incidentally, (and probably not very coincidentally) this epic tale was also a large part of the resolution of that Star Trek episode I linked earlier.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2108&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8Qyv2CP7bZOqCAUNG3cN-A-6f9e66a0._WSetTem_NFDlx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Tablet V of the epic of Gilgamesh. The tablet dates back to the old Babylonian period, 2003–1595 BCE.&lt;/p&gt;
&lt;p&gt;To detect climax events, the software uses multiple Natural Language Processing modules including &lt;a href=&quot;https://en.wikipedia.org/wiki/Entity_linking&quot;&gt;named entity recognition and linking&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Semantic_role_labeling&quot;&gt;semantic role labeling&lt;/a&gt;, &lt;a href=&quot;https://nlp.stanford.edu/projects/time.shtml&quot;&gt;time expression detection and normalization&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Coreference&quot;&gt;nominal and event coreference&lt;/a&gt;. Processing a single news article results in the semantic interpretation of mentions of events, participants and their time anchoring in a sequence of text.&lt;/p&gt;
&lt;p&gt;Where the pipeline of NewsReader finds climax events, it will first look for events that are part of the same storyline as the largest climax event of the selected data, and link them to this climax event in a story. It will do so in a greedy fashion, until it can find no more that it can link. It will then move to the next biggest climax event that is left in the pool and continue its operation. This creates a set of stories, linked by single events with a number of participants, citations, authors and perspectives.&lt;/p&gt;
&lt;h3 id=&quot;movie-narrative-charts&quot;&gt;Movie narrative charts&lt;/h3&gt;
&lt;p&gt;Very early on in the project, we realized that one visualization would not be enough. The complexity of the connections between events, actors and mentions was just too great to capture in a single image. Especially if that image had to be algorithmically constructed instead of painstakingly hand-crafted. While we used the legendary Randall Munroe’s Movie narrative Charts (see image) as a source of inpiration for one of our visualizations, we knew that we could never fit as much information in the image automatically.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1263&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__ne2tqSBUv5I1KFuXPDrDA-dacd3b38.B-6bwIMC_1yVjRV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;XKCD Movie narrative charts. The inspiration for our co-participation graph.&lt;/p&gt;
&lt;p&gt;We therefore decided on three different visualizations in different tabs (or views), which were linked through filters and selections.&lt;/p&gt;
&lt;h3 id=&quot;visualize-and-conquer&quot;&gt;Visualize and conquer!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(Hold on to your horses, a link will be provided soon… I just need to explain a little more…)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The first of our chosen visualizations is a variation on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Bubble_chart&quot;&gt;bubble chart&lt;/a&gt;. It shows events on a timeline, with the size (and color, for distinctiveness) of the bubbles as a measure of their importance. Every line in the chart is a story, with a topic (on the left side) and event labels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;404&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mTk32781mRhMXdCFQTRkKQ-552bd841.VrQXSB2q_ZSbdx2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The event-centric view of StoryTeller offers multiple storylines and their events on a timeline. In this case, the Brexit dataset of the Financial Times was visualized.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Too much is shown at once. We know.&lt;/strong&gt; Luckily we have the handy tool of interaction to help us. From this view, we can filter on stories, intervals and (relative) importance of events.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9r2npvA19E3vStVd11x8Xw-8285db95.BfZTBmdO_16bGPx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An example of a filtered view on the event-centric graph.&lt;/p&gt;
&lt;h3 id=&quot;more-interested-in-who-was-present-or-who-was-mentioned&quot;&gt;More interested in who was present or who was mentioned?&lt;/h3&gt;
&lt;p&gt;(&lt;em&gt;or colorful spaghetti?&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;That’s what the relations tab is for. This is also where the previously mentioned xkcd comes in handy. We see participants on the left and single mentions on the right. Colorful lines are drawn through events with actors that appear in these events simultaneously.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1527&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yNm0Tga2bAk4eEdXZSRldw-22520cf0.Dy4FIOgV_MOJUW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The relations tab of StoryTeller&lt;/p&gt;
&lt;p&gt;This graph can of course also be filtered, here we see all events linked to both the United kingdom and David Cameron.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1458&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kZ8BZDWLLQNXggIAcBSqoA-5c5ca8e2.DpU22r7l_Z1WpgTC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-about-these-perspectives-you-mentioned-at-the-start&quot;&gt;What about these perspectives you mentioned at the start?&lt;/h3&gt;
&lt;p&gt;This is the last tab of our web-app. Here a user can visually find (and filter on) events with sentiments (negative, neutral or positive), events which mention the past or present, events that the original speaker was certain or uncertain about etc. We can also filter on specific citations by people and authors of articles.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1521&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ScNi5P6Kwq4xqrMLPfD4xA-80bc236d.2aR3zwnB_Z2oU3TA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;try-it&quot;&gt;Try it!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(please do allow for a few moments for the page to load, the amount of data in here is quite … big)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://nlesc.github.io/UncertaintyVisualization/&quot;&gt;&lt;strong&gt;StoryTeller for pre-brexit-referendum news data&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;ugh-too-much-work-dont-you-have-a-video&quot;&gt;Ugh, too much work, don’t you have a video?&lt;/h3&gt;
&lt;p&gt;Sure, here is Dr. &lt;a href=&quot;http://vu-nl.academia.edu/TommasoCaselli&quot;&gt;Tomasso Caselli&lt;/a&gt;, a researcher working with Piek Vossen, explaining StoryTeller step by step at our &lt;a href=&quot;https://blog.esciencecenter.nl/what-is-the-impact-of-visualization-on-science-5d16bb6dd844&quot;&gt;visualization event&lt;/a&gt; in Rotterdam!&lt;/p&gt;
&lt;h3 id=&quot;ok-cool-so-how-did-you-make-this-can-i-use-it-can-i-cannibalize-your-code-use-it-to-take-over-the-world&quot;&gt;Ok, cool, so how did you make this? Can I use it? Can I cannibalize your code? Use it to take over the world?&lt;/h3&gt;
&lt;p&gt;Whoa! Yes! All of the software we develop at the eScience Center is open source, with a very permissive attribution-only licence. So go ahead and try it out.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/NLeSC/UncertaintyVisualization/&quot;&gt;&lt;strong&gt;source code&lt;/strong&gt;&lt;/a&gt; is written in Javascript, with &lt;a href=&quot;https://angularjs.org/&quot;&gt;AngularJS 1.0&lt;/a&gt;. It makes heavy use of the &lt;a href=&quot;https://dc-js.github.io/dc.js/&quot;&gt;DC.js library&lt;/a&gt;, which uses &lt;a href=&quot;https://d3js.org/&quot;&gt;D3&lt;/a&gt; for visualization and &lt;a href=&quot;http://crossfilter.github.io/crossfilter/&quot;&gt;Crossfilter&lt;/a&gt; for the filtering code. We applied some Angular sauce and customized quite a bit of code of course. Many (if not all) of the graphs in StoryTeller are custom work loosely based on the DC.js examples.&lt;/p&gt;
&lt;p&gt;If you are going to use it, awesome! I’d appreciate it if you send me a message if you encounter any issues. It’s meant to be quite readable and useable, so if it’s not, I’d like to know. Don’t hesitate to make an issue on Github either. I promise I’ll be nice:)&lt;/p&gt;</description><pubDate>Mon, 07 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;the-storyteller-application-gives-you-a-different-perspective-on-the-news&quot;&gt;The StoryTeller application gives you a different perspective on the news&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3134&quot; height=&quot;853&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_36VvqJkQdxzrbozNMfi0og-054975ba.1mYNRAnh_2RpM1.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A screenshot from the StoryTeller application. Shown here is a co-participation graph for entities that participate in events together with Apple_inc.&lt;/p&gt;
&lt;p&gt;When I started working with the Computational Linguistics group of the &lt;a href=&quot;https://www.vu.nl/en/&quot;&gt;VU University Amsterdam&lt;/a&gt; two years ago, I didn’t know much about Natural Language Processing. I used to think that communicating human beings were pretty understandable, especially in everyday news reporting. I’ve since learned that I was terribly wrong.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Computers do not understand us.&lt;/strong&gt; Human language is so abstract and full of context, innuendo and cultural references, that to an observer without the same background (the computer, in this case) we are nearly impossible to understand.&lt;/p&gt;
&lt;h3 id=&quot;shaka-when-the-walls-fell&quot;&gt;Shaka, when the walls fell.&lt;/h3&gt;
&lt;p&gt;As an example of an exploration of cultural differences and understanding language, I’d like to point you to an episode of &lt;a href=&quot;https://en.wikipedia.org/wiki/Star_Trek:_The_Next_Generation&quot;&gt;Star Trek: The next Generation&lt;/a&gt; called “ &lt;a href=&quot;http://memory-alpha.wikia.com/wiki/Darmok_(episode)&quot;&gt;Darmok&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;This scene from “Darmok” illustrates the difficulty of ‘speaking’ with someone that does not share your cultural references and language structure.&lt;/p&gt;
&lt;p&gt;In this episode, the English-speaking captain of the star ship Enterprise is forced to communicate with an alien race with a completely different language. The aliens’ words are translated to English, but they make no sense at all because they are completely speaking in metaphors.&lt;/p&gt;
&lt;p&gt;Since this is an episodic series, the impasse is of course resolved eventually, but the point is well made.&lt;/p&gt;
&lt;p&gt;Human(oid) communication is a very difficult problem indeed.&lt;/p&gt;
&lt;h3 id=&quot;natural-language-processing&quot;&gt;Natural Language Processing&lt;/h3&gt;
&lt;p&gt;This is where science must find a solution. If we ever want computers to answer complex queries from humans (or even make us a cup of Earl Grey on voice command), we have to make computers and people understand each other.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.8013&quot;&gt;Great&lt;/a&gt; &lt;a href=&quot;https://arxiv.org/abs/1301.3781&quot;&gt;strides&lt;/a&gt; &lt;a href=&quot;http://dl.acm.org/citation.cfm?doid=2133806.2133826&quot;&gt;have&lt;/a&gt; already been made, but many challenges persist. One of those challenges is event-based data like news stories. While literary works are usually well researched works of knowledge or stories with a well defined structure, the news is fraught with an extra layer of challenges because of its time-based nature. The facts of today might be the fake news of tomorrow, and opinions of politicians and other prominent speakers may shift over the course of time. &lt;a href=&quot;https://www.esciencecenter.nl/project/mining-shifting-concepts-through-time-shico&quot;&gt;Even concepts themselves are not as stable as you might think.&lt;/a&gt; The news and its complexities is the chosen topic of research for the group of professor &lt;a href=&quot;http://vossen.info/&quot;&gt;Piek Vossen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_5iintDhL1d_w8f-yQbn_4Q-e4f84195.DAyteGwC_OlqHm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;newsreader&quot;&gt;NewsReader&lt;/h3&gt;
&lt;p&gt;Enter the &lt;a href=&quot;http://www.newsreader-project.eu/&quot;&gt;NewsReader&lt;/a&gt; project, a European-funded multi-partner research project that aims to help humanity overcome at least some of the challenges as described above. To help improve the communication between computers and people, a software pipeline was constructed. This pipeline is a collection of software packages dealing with specific parts of human language, which can be connected to form a more complete picture of stories in newspapers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;390&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_71JalaUtdVxaYOSUEWuIZg-54f4ab0a.ZwXFsmHL_1X0gSb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A visual representation of the NewsReader pipeline.&lt;/p&gt;
&lt;p&gt;The newsreader pipeline extracts what happened to whom, when and where from billions of news stories, company databases and biographies and stores them in a structured database, enabling more precise search over this immense stack of information. It supports multiple languages (English, Spanish, Italian and Dutch) and allows its users to find complex interconnections between participants, events and perspectives on these events.&lt;/p&gt;
&lt;p&gt;Before I joined the project, however, a new and exciting challenge appeared. The output of the pipeline was too complex to understand &lt;em&gt;for humans.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;word-soup&quot;&gt;Word soup&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1362&quot; height=&quot;675&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Qjqiyw5Yu6w4fii1ZR0bUg-0508871e.CMb5Zefo_1U5wFb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://compsocsci.blogspot.nl/2012/06/word-cloud-of-knight-news-challenge.html&quot;&gt;http://compsocsci.blogspot.nl/2012/06/word-cloud-of-knight-news-challenge.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A term usually applied to the inane utterings of politicians &lt;a href=&quot;http://theslot.jezebel.com/kellyanne-conway-is-losing-her-hold-on-talking-head-pro-1792391189&quot;&gt;or their representatives&lt;/a&gt;, it quite accurately describes the issues with scientific output in computational linguistics. At least to us humans, English speaking humans, or me alone, depending on how narrow this particular selection is made. &lt;em&gt;On second thought, let me explain.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Before new users start to make sense of the output of the NewsReader pipeline, they encounter an enormous mass of words, arranged in mentions (instances of events that are mentioned in the news) and their attributes. Dates, cited persons, authors, event participants, labels, groups, perspectives etc. All neatly arranged in a computer-readable data structure. Needless to say, I didn’t understand any of its significance until it was explained to me.&lt;/p&gt;
&lt;h3 id=&quot;climax-events-and-storylines&quot;&gt;Climax events and Storylines&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;555&quot; height=&quot;279&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_0fj2wCG0ht98nXmD8Mex7g-228f3eaa.9hfTASoW_1eeHE4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The pipeline spews forth a slurry of events and their mentions in the news, but fortunately there is now some structure to the data. Stories have been defined by defining a ‘climax’ event, and connecting it to other events through their participants, labels, groups and other metadata. These stories should follow the ancient structure of all human stories, at the very least since the first recorded epic of &lt;a href=&quot;https://en.wikipedia.org/wiki/Gilgamesh&quot;&gt;Gilgamesh&lt;/a&gt;. Incidentally, (and probably not very coincidentally) this epic tale was also a large part of the resolution of that Star Trek episode I linked earlier.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;2108&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_8Qyv2CP7bZOqCAUNG3cN-A-6f9e66a0._WSetTem_NFDlx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Tablet V of the epic of Gilgamesh. The tablet dates back to the old Babylonian period, 2003–1595 BCE.&lt;/p&gt;
&lt;p&gt;To detect climax events, the software uses multiple Natural Language Processing modules including &lt;a href=&quot;https://en.wikipedia.org/wiki/Entity_linking&quot;&gt;named entity recognition and linking&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Semantic_role_labeling&quot;&gt;semantic role labeling&lt;/a&gt;, &lt;a href=&quot;https://nlp.stanford.edu/projects/time.shtml&quot;&gt;time expression detection and normalization&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Coreference&quot;&gt;nominal and event coreference&lt;/a&gt;. Processing a single news article results in the semantic interpretation of mentions of events, participants and their time anchoring in a sequence of text.&lt;/p&gt;
&lt;p&gt;Where the pipeline of NewsReader finds climax events, it will first look for events that are part of the same storyline as the largest climax event of the selected data, and link them to this climax event in a story. It will do so in a greedy fashion, until it can find no more that it can link. It will then move to the next biggest climax event that is left in the pool and continue its operation. This creates a set of stories, linked by single events with a number of participants, citations, authors and perspectives.&lt;/p&gt;
&lt;h3 id=&quot;movie-narrative-charts&quot;&gt;Movie narrative charts&lt;/h3&gt;
&lt;p&gt;Very early on in the project, we realized that one visualization would not be enough. The complexity of the connections between events, actors and mentions was just too great to capture in a single image. Especially if that image had to be algorithmically constructed instead of painstakingly hand-crafted. While we used the legendary Randall Munroe’s Movie narrative Charts (see image) as a source of inpiration for one of our visualizations, we knew that we could never fit as much information in the image automatically.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1263&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__ne2tqSBUv5I1KFuXPDrDA-dacd3b38.B-6bwIMC_1yVjRV.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;XKCD Movie narrative charts. The inspiration for our co-participation graph.&lt;/p&gt;
&lt;p&gt;We therefore decided on three different visualizations in different tabs (or views), which were linked through filters and selections.&lt;/p&gt;
&lt;h3 id=&quot;visualize-and-conquer&quot;&gt;Visualize and conquer!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(Hold on to your horses, a link will be provided soon… I just need to explain a little more…)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The first of our chosen visualizations is a variation on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Bubble_chart&quot;&gt;bubble chart&lt;/a&gt;. It shows events on a timeline, with the size (and color, for distinctiveness) of the bubbles as a measure of their importance. Every line in the chart is a story, with a topic (on the left side) and event labels.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;404&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_mTk32781mRhMXdCFQTRkKQ-552bd841.VrQXSB2q_ZSbdx2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The event-centric view of StoryTeller offers multiple storylines and their events on a timeline. In this case, the Brexit dataset of the Financial Times was visualized.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Too much is shown at once. We know.&lt;/strong&gt; Luckily we have the handy tool of interaction to help us. From this view, we can filter on stories, intervals and (relative) importance of events.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;408&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9r2npvA19E3vStVd11x8Xw-8285db95.BfZTBmdO_16bGPx.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;An example of a filtered view on the event-centric graph.&lt;/p&gt;
&lt;h3 id=&quot;more-interested-in-who-was-present-or-who-was-mentioned&quot;&gt;More interested in who was present or who was mentioned?&lt;/h3&gt;
&lt;p&gt;(&lt;em&gt;or colorful spaghetti?&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;That’s what the relations tab is for. This is also where the previously mentioned xkcd comes in handy. We see participants on the left and single mentions on the right. Colorful lines are drawn through events with actors that appear in these events simultaneously.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1527&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_yNm0Tga2bAk4eEdXZSRldw-22520cf0.Dy4FIOgV_MOJUW.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The relations tab of StoryTeller&lt;/p&gt;
&lt;p&gt;This graph can of course also be filtered, here we see all events linked to both the United kingdom and David Cameron.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1458&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_kZ8BZDWLLQNXggIAcBSqoA-5c5ca8e2.DpU22r7l_Z1WpgTC.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;what-about-these-perspectives-you-mentioned-at-the-start&quot;&gt;What about these perspectives you mentioned at the start?&lt;/h3&gt;
&lt;p&gt;This is the last tab of our web-app. Here a user can visually find (and filter on) events with sentiments (negative, neutral or positive), events which mention the past or present, events that the original speaker was certain or uncertain about etc. We can also filter on specific citations by people and authors of articles.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1521&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ScNi5P6Kwq4xqrMLPfD4xA-80bc236d.2aR3zwnB_Z2oU3TA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;try-it&quot;&gt;Try it!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(please do allow for a few moments for the page to load, the amount of data in here is quite … big)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://nlesc.github.io/UncertaintyVisualization/&quot;&gt;&lt;strong&gt;StoryTeller for pre-brexit-referendum news data&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;ugh-too-much-work-dont-you-have-a-video&quot;&gt;Ugh, too much work, don’t you have a video?&lt;/h3&gt;
&lt;p&gt;Sure, here is Dr. &lt;a href=&quot;http://vu-nl.academia.edu/TommasoCaselli&quot;&gt;Tomasso Caselli&lt;/a&gt;, a researcher working with Piek Vossen, explaining StoryTeller step by step at our &lt;a href=&quot;https://blog.esciencecenter.nl/what-is-the-impact-of-visualization-on-science-5d16bb6dd844&quot;&gt;visualization event&lt;/a&gt; in Rotterdam!&lt;/p&gt;
&lt;h3 id=&quot;ok-cool-so-how-did-you-make-this-can-i-use-it-can-i-cannibalize-your-code-use-it-to-take-over-the-world&quot;&gt;Ok, cool, so how did you make this? Can I use it? Can I cannibalize your code? Use it to take over the world?&lt;/h3&gt;
&lt;p&gt;Whoa! Yes! All of the software we develop at the eScience Center is open source, with a very permissive attribution-only licence. So go ahead and try it out.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/NLeSC/UncertaintyVisualization/&quot;&gt;&lt;strong&gt;source code&lt;/strong&gt;&lt;/a&gt; is written in Javascript, with &lt;a href=&quot;https://angularjs.org/&quot;&gt;AngularJS 1.0&lt;/a&gt;. It makes heavy use of the &lt;a href=&quot;https://dc-js.github.io/dc.js/&quot;&gt;DC.js library&lt;/a&gt;, which uses &lt;a href=&quot;https://d3js.org/&quot;&gt;D3&lt;/a&gt; for visualization and &lt;a href=&quot;http://crossfilter.github.io/crossfilter/&quot;&gt;Crossfilter&lt;/a&gt; for the filtering code. We applied some Angular sauce and customized quite a bit of code of course. Many (if not all) of the graphs in StoryTeller are custom work loosely based on the DC.js examples.&lt;/p&gt;
&lt;p&gt;If you are going to use it, awesome! I’d appreciate it if you send me a message if you encounter any issues. It’s meant to be quite readable and useable, so if it’s not, I’d like to know. Don’t hesitate to make an issue on Github either. I promise I’ll be nice:)&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_5iintDhL1d_w8f-yQbn_4Q-e4f84195.DAyteGwC.png" medium="image"/><author>Maarten van Meersbergen</author></item><item><title>an ambition for the global astronomical community</title><link>https://blog2.esciencecenter.nl/posts/2017-07-17---an-ambition-for-the-global-astronomical-community</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-07-17---an-ambition-for-the-global-astronomical-community</guid><description>&lt;p&gt;&lt;em&gt;Making the data produced by the rejuvenated Westerbork Telescope more open for, and delivered faster to, the astronomical community&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v6hL19U41_yaZkrLwG4SQw-05f31b33.1nwC0oCW_1nvxos.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen, Dutch astrophysicist, ASTRON and University of Amsterdam&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography and text: Elodie Burrillon / HUCOPIX&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen (42) is a Dutch astrophysicist at ASTRON (The Netherlands Institute for Radio Astronomy) and University of Amsterdam. In 2015, Joeri received a &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;grant&lt;/a&gt; and in-kind expertise from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; for his project &lt;a href=&quot;https://www.esciencecenter.nl/project/aa-alert&quot;&gt;AA-ALERT&lt;/a&gt;, the Access and Acceleration of the Apertif Legacy Exploration of the Radio Transient Sky.&lt;/p&gt;
&lt;p&gt;By collaborating with the eScience Center, Joeri’s team aims to make the new and enormous amount of data produced by the rejuvenated Westerbork telescope more open and delivered faster to everyone — and specifically to contribute to a better understanding of cosmic explosions.&lt;/p&gt;
&lt;h2 id=&quot;curiosity-above-all&quot;&gt;Curiosity above all&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NRwWKhu8LM2-8meuJWeyXA-71dfc0b0.BrwPo0Rs_Z1dXPyH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri: “I’ve always wanted to know how the things in the sky work”&lt;/p&gt;
&lt;p&gt;Joeri: “I have always been very curious. As a child, I wanted to understand how animals function, how to make a big fire, how the things in the sky work. I remember liking astronomy when I was 17, but I was also drawn to other sciences. I am just inquisitive and want to know what makes things tick.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Oofaa_2o6RdBa7HX8my6wQ-4420e1c6.BIEQ5C4q_yXlz2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen and Jisk Attema next to one of the radio telescopes at Westerbork&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Vyvmhe_o15Bk_kOHHzVMxA-f64e56c5.DfoFQ6IS_ZaGq12.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen on one of the 12 radio telescopes in Westerbork&lt;/p&gt;
&lt;h2 id=&quot;ending-up-at-astron&quot;&gt;Ending up at ASTRON&lt;/h2&gt;
&lt;p&gt;“After doing my PhD in astronomy in The Netherlands and spending a few years as a postdoc in Canada and the USA, I came back to The Netherlands ten years ago. I would say that ending up at ASTRON was a result of hard work but also a lot of luck: In my own country, just after finishing two postdocs, they were looking for astronomers to help build a huge radio telescope (LOFAR), with exactly the expertise I had been developing overseas.”&lt;/p&gt;
&lt;h2 id=&quot;being-an-astronomer&quot;&gt;Being an astronomer&lt;/h2&gt;
&lt;p&gt;“As an astronomer, as in many scientific disciplines, you can focus on the theory, on observations, or on instrumentation. I enjoy that I do all three. Sometimes I work for months on a theory paper, sometimes I get my boots muddy at the &lt;a href=&quot;http://www.lofar.org/&quot;&gt;LOFAR telescope&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EcK0IlFnAaYprphLu5qsqg-2df32d37.Dkd4n6dO_1r8IG4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Signals received by the radio telescopes at Westerbork are transported via cables to the server room&lt;/p&gt;
&lt;p&gt;“Our instruments involve a lot of computer science and high-performance computing, so often I am busy with the machines in the telescope server rooms. In addition, there are of course also the months I spend on attracting funding, or on the outreach I do. Plus the mentoring of a sizeable group of students and postdocs. That variety of tasks and skills I enjoy very much.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VdcjByeH8U4HoTHjseiQPw-f89f081a.DJq8c5K6_20qsgN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-biggest-challenge&quot;&gt;The biggest challenge&lt;/h2&gt;
&lt;p&gt;“I think that the biggest challenge I ever had to overcome was getting &lt;a href=&quot;https://www.astron.nl/r-d-laboratory/arts/arts-apertif-radio-transient-system-apertif&quot;&gt;ARTS&lt;/a&gt;, the real-time system on &lt;a href=&quot;https://www.astron.nl/general/apertif/apertif&quot;&gt;Apertif&lt;/a&gt;, built. The idea behind this project is to rejuvenate the Westerbork Telescope, making it a radio telescope with a 40 times bigger field of view than before, better than any other radio telescope. But the Dutch astronomical community runs many other world-class projects clamoring for resources. So, convincing all stakeholders (funding agencies, astronomers, politicians, technicians) to free up funding and person power took much energy and time. We made the first plans in 2010, and we are building it now.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The rejuvenated radio telescope will have a 40 times bigger field of view, better than any other radio telescope&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“I’m proud that ASTRON is the only institute in the world with two of the biggest radio telescopes — LOFAR and the Westerbork Telescope. And we are glueing these together through a real-time GPU supercomputing system.”&lt;/p&gt;
&lt;h2 id=&quot;the-aa-alert-project&quot;&gt;The AA-ALERT project&lt;/h2&gt;
&lt;p&gt;With Apertif accepted, Joeri could have been satisfied: there was now a real-time system, and an ERC award for a dedicated team of expert astronomers to help carry out the survey, &lt;a href=&quot;http://www.alert.eu/&quot;&gt;ALERT&lt;/a&gt;. But he had an ambition for the global radio astronomical community: making these new data more open, and delivered faster.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FSqQLwReq50QI7b2jsrMuA-2d80cecd.CBN5QNJ2_ljtc9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri: “Together with the eScience Center we teach new reflexes to an old telescope”&lt;/p&gt;
&lt;p&gt;In 2015, Joeri received a grant from the eScience Center for his project AA-ALERT - the Access and Acceleration of the Apertif Legacy Exploration of the Radio Transient Sky. The team has a twofold aim: better access to the data produced by the Westerbork Telescope, and accelerated processing of this data.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using our data shouldn’t be reserved to experts&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“All our data is already open to everyone in principle, but to make it more open to everyone in fact, they need to be easily able to get and use it — using our data shouldn’t be reserved to experts.”&lt;/p&gt;
&lt;p&gt;“This is the first half of the project: making the data more accessible to all. The second half concerns the acceleration of the decision-making. Apertif continuously produces so much data — more than the entire internet of The Netherlands, all the time — that it would be crazy to keep it all. So every second we have to decide ‘keep it’ or ‘throw it away’. So it’s a lot like building a new reflex for this telescope, telling it what to do.”&lt;/p&gt;
&lt;h3 id=&quot;collaborate-with-the-escience-center&quot;&gt;Collaborate with the eScience Center&lt;/h3&gt;
&lt;p&gt;“Collaborating with the eScience Center on this AA-ALERT project was, to me, almost obvious. Someone like eScience Research Engineer &lt;a href=&quot;https://www.esciencecenter.nl/profile/alessio-sclocco-msc&quot;&gt;Alessio Sclocco&lt;/a&gt; worked with us on ARTS, at ASTRON, before he got a position at the eScience Center. The GPU acceleration he has been working on, only a handful of people in the country can do it. I actually wanted to hire him myself when he finished his PhD, but the eScience Center got him.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_HSGLvDEUvbXpYkjtWrzHjg-13689641.Cb1ktoBZ_1L3wjY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Jisk Attema is an eScience Coordinator and works with Joeri on the AA-ALERT project&lt;/p&gt;
&lt;p&gt;“In the meantime, &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-jisk-attema&quot;&gt;Jisk Attema&lt;/a&gt; makes sure that, after a telescope reflex decision, astronomers can look at the relevant data for our science goals; understanding cosmic explosions. So you can imagine that what I value most about the eScience Center is the high level of expertise. Would I recommend working with the eScience Center? Well, a wholehearted ‘yes’!”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_u77RmAaDkHh-UWSxZoV-xQ-b332c78f._zR4XI4c_1lcK9e.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</description><pubDate>Mon, 17 Jul 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Making the data produced by the rejuvenated Westerbork Telescope more open for, and delivered faster to, the astronomical community&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_v6hL19U41_yaZkrLwG4SQw-05f31b33.1nwC0oCW_1nvxos.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen, Dutch astrophysicist, ASTRON and University of Amsterdam&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography and text: Elodie Burrillon / HUCOPIX&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen (42) is a Dutch astrophysicist at ASTRON (The Netherlands Institute for Radio Astronomy) and University of Amsterdam. In 2015, Joeri received a &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;grant&lt;/a&gt; and in-kind expertise from the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;eScience Center&lt;/a&gt; for his project &lt;a href=&quot;https://www.esciencecenter.nl/project/aa-alert&quot;&gt;AA-ALERT&lt;/a&gt;, the Access and Acceleration of the Apertif Legacy Exploration of the Radio Transient Sky.&lt;/p&gt;
&lt;p&gt;By collaborating with the eScience Center, Joeri’s team aims to make the new and enormous amount of data produced by the rejuvenated Westerbork telescope more open and delivered faster to everyone — and specifically to contribute to a better understanding of cosmic explosions.&lt;/p&gt;
&lt;h2 id=&quot;curiosity-above-all&quot;&gt;Curiosity above all&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_NRwWKhu8LM2-8meuJWeyXA-71dfc0b0.BrwPo0Rs_Z1dXPyH.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri: “I’ve always wanted to know how the things in the sky work”&lt;/p&gt;
&lt;p&gt;Joeri: “I have always been very curious. As a child, I wanted to understand how animals function, how to make a big fire, how the things in the sky work. I remember liking astronomy when I was 17, but I was also drawn to other sciences. I am just inquisitive and want to know what makes things tick.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Oofaa_2o6RdBa7HX8my6wQ-4420e1c6.BIEQ5C4q_yXlz2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen and Jisk Attema next to one of the radio telescopes at Westerbork&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Vyvmhe_o15Bk_kOHHzVMxA-f64e56c5.DfoFQ6IS_ZaGq12.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri van Leeuwen on one of the 12 radio telescopes in Westerbork&lt;/p&gt;
&lt;h2 id=&quot;ending-up-at-astron&quot;&gt;Ending up at ASTRON&lt;/h2&gt;
&lt;p&gt;“After doing my PhD in astronomy in The Netherlands and spending a few years as a postdoc in Canada and the USA, I came back to The Netherlands ten years ago. I would say that ending up at ASTRON was a result of hard work but also a lot of luck: In my own country, just after finishing two postdocs, they were looking for astronomers to help build a huge radio telescope (LOFAR), with exactly the expertise I had been developing overseas.”&lt;/p&gt;
&lt;h2 id=&quot;being-an-astronomer&quot;&gt;Being an astronomer&lt;/h2&gt;
&lt;p&gt;“As an astronomer, as in many scientific disciplines, you can focus on the theory, on observations, or on instrumentation. I enjoy that I do all three. Sometimes I work for months on a theory paper, sometimes I get my boots muddy at the &lt;a href=&quot;http://www.lofar.org/&quot;&gt;LOFAR telescope&lt;/a&gt;.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_EcK0IlFnAaYprphLu5qsqg-2df32d37.Dkd4n6dO_1r8IG4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Signals received by the radio telescopes at Westerbork are transported via cables to the server room&lt;/p&gt;
&lt;p&gt;“Our instruments involve a lot of computer science and high-performance computing, so often I am busy with the machines in the telescope server rooms. In addition, there are of course also the months I spend on attracting funding, or on the outreach I do. Plus the mentoring of a sizeable group of students and postdocs. That variety of tasks and skills I enjoy very much.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;1080&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_VdcjByeH8U4HoTHjseiQPw-f89f081a.DJq8c5K6_20qsgN.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-biggest-challenge&quot;&gt;The biggest challenge&lt;/h2&gt;
&lt;p&gt;“I think that the biggest challenge I ever had to overcome was getting &lt;a href=&quot;https://www.astron.nl/r-d-laboratory/arts/arts-apertif-radio-transient-system-apertif&quot;&gt;ARTS&lt;/a&gt;, the real-time system on &lt;a href=&quot;https://www.astron.nl/general/apertif/apertif&quot;&gt;Apertif&lt;/a&gt;, built. The idea behind this project is to rejuvenate the Westerbork Telescope, making it a radio telescope with a 40 times bigger field of view than before, better than any other radio telescope. But the Dutch astronomical community runs many other world-class projects clamoring for resources. So, convincing all stakeholders (funding agencies, astronomers, politicians, technicians) to free up funding and person power took much energy and time. We made the first plans in 2010, and we are building it now.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The rejuvenated radio telescope will have a 40 times bigger field of view, better than any other radio telescope&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“I’m proud that ASTRON is the only institute in the world with two of the biggest radio telescopes — LOFAR and the Westerbork Telescope. And we are glueing these together through a real-time GPU supercomputing system.”&lt;/p&gt;
&lt;h2 id=&quot;the-aa-alert-project&quot;&gt;The AA-ALERT project&lt;/h2&gt;
&lt;p&gt;With Apertif accepted, Joeri could have been satisfied: there was now a real-time system, and an ERC award for a dedicated team of expert astronomers to help carry out the survey, &lt;a href=&quot;http://www.alert.eu/&quot;&gt;ALERT&lt;/a&gt;. But he had an ambition for the global radio astronomical community: making these new data more open, and delivered faster.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FSqQLwReq50QI7b2jsrMuA-2d80cecd.CBN5QNJ2_ljtc9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Joeri: “Together with the eScience Center we teach new reflexes to an old telescope”&lt;/p&gt;
&lt;p&gt;In 2015, Joeri received a grant from the eScience Center for his project AA-ALERT - the Access and Acceleration of the Apertif Legacy Exploration of the Radio Transient Sky. The team has a twofold aim: better access to the data produced by the Westerbork Telescope, and accelerated processing of this data.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using our data shouldn’t be reserved to experts&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“All our data is already open to everyone in principle, but to make it more open to everyone in fact, they need to be easily able to get and use it — using our data shouldn’t be reserved to experts.”&lt;/p&gt;
&lt;p&gt;“This is the first half of the project: making the data more accessible to all. The second half concerns the acceleration of the decision-making. Apertif continuously produces so much data — more than the entire internet of The Netherlands, all the time — that it would be crazy to keep it all. So every second we have to decide ‘keep it’ or ‘throw it away’. So it’s a lot like building a new reflex for this telescope, telling it what to do.”&lt;/p&gt;
&lt;h3 id=&quot;collaborate-with-the-escience-center&quot;&gt;Collaborate with the eScience Center&lt;/h3&gt;
&lt;p&gt;“Collaborating with the eScience Center on this AA-ALERT project was, to me, almost obvious. Someone like eScience Research Engineer &lt;a href=&quot;https://www.esciencecenter.nl/profile/alessio-sclocco-msc&quot;&gt;Alessio Sclocco&lt;/a&gt; worked with us on ARTS, at ASTRON, before he got a position at the eScience Center. The GPU acceleration he has been working on, only a handful of people in the country can do it. I actually wanted to hire him myself when he finished his PhD, but the eScience Center got him.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_HSGLvDEUvbXpYkjtWrzHjg-13689641.Cb1ktoBZ_1L3wjY.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Jisk Attema is an eScience Coordinator and works with Joeri on the AA-ALERT project&lt;/p&gt;
&lt;p&gt;“In the meantime, &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-jisk-attema&quot;&gt;Jisk Attema&lt;/a&gt; makes sure that, after a telescope reflex decision, astronomers can look at the relevant data for our science goals; understanding cosmic explosions. So you can imagine that what I value most about the eScience Center is the high level of expertise. Would I recommend working with the eScience Center? Well, a wholehearted ‘yes’!”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_u77RmAaDkHh-UWSxZoV-xQ-b332c78f._zR4XI4c_1lcK9e.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_NRwWKhu8LM2-8meuJWeyXA-71dfc0b0.BrwPo0Rs.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>binge-watching science on youtube the good, the epic and the brilliant</title><link>https://blog2.esciencecenter.nl/posts/2017-07-03---binge-watching-science-on-youtube-the-good-the-epic-and-the-brilliant</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-07-03---binge-watching-science-on-youtube-the-good-the-epic-and-the-brilliant</guid><description>&lt;h2 id=&quot;with-some-help-its-algorithms-can-be-trained-to-find-you-the-good-stuff&quot;&gt;With some help, its algorithms can be trained to find you the good stuff&lt;/h2&gt;
&lt;p&gt;A decade ago, my favorite TV channel used to be the Discovery channel. I spent hours watching shows like How it’s made, Mythbusters and Scrapheap challenge. Since it’s my job, I count myself lucky that my fascination with science and engineering and their newest applications has never ceased, but for the enthusiast like me, the Discovery channel (and any other TV channels) have never captured my interest since their focus (at least here in the Netherlands) has shifted more towards reality shows like Pawn Stars and Deadliest Catch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For you, the science enthusiast&lt;/strong&gt;, in the age of on-demand video there might not be a better place to find the content you’re looking for than YouTube.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;927&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KqrRv97yYgVsXKx5zHlCCw-e8b70083.az--8FQZ_VQnvc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Even if you’re not too interested popular science, you could learn something from these channels. They are very effective at pitching science to a broad audience. Additionally, it could be very informative to watch what’s going on in a neighboring (or even entirely different) field. At the eScience Center we work together with scientists from many different fields of science. Such collaborations often lead to creative and inspirating solutions — so we highly recommend looking across the fence every once in a while to see what’s happening in other fields!&lt;/p&gt;
&lt;h3 id=&quot;youtube-you-say&quot;&gt;YouTube you say?&lt;/h3&gt;
&lt;p&gt;Isn’t that where all of these weird vloggers tell tales of their daily lives? Isn’t that where gamers post their lets-play video’s and whatnot, and all the content is aimed at children?&lt;/p&gt;
&lt;p&gt;Nay, YouTube offers so much more, if you only know where to look, and if you train &lt;a href=&quot;http://dl.acm.org/citation.cfm?id=1367618&quot;&gt;its algorithms&lt;/a&gt; to find you the stuff you want to see. To help you train your personalized algorithm, here’s a peek at my science-subscription list.&lt;/p&gt;
&lt;h3 id=&quot;broad-topic-channels&quot;&gt;Broad-topic channels&lt;/h3&gt;
&lt;p&gt;Want to know about all of the awesome new scientific discoveries, but not in too much detail? These might be the channels you’re looking for, and also a great way to start your YouTube algorithm training. If you want to know more after watching these videos, you can always go deeper later.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCZYTClx2T1of7BRZ86-8fow&quot;&gt;SciShow&lt;/a&gt; is a great choice in this category. It offers videos on a very wide range of topics. As an example … if you happen to have children that are going through puberty, I feel for you. This video might help:&lt;/p&gt;
&lt;p&gt;Want broad, but a little more explanation? &lt;a href=&quot;https://www.youtube.com/channel/UCHnyfMqiRRG1u-2MsSQLbXA&quot;&gt;Veritasium&lt;/a&gt; might be more your choice.&lt;/p&gt;
&lt;h3 id=&quot;the-food-for-thought&quot;&gt;The food-for-thought&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q&quot;&gt;Kurtzgezagt&lt;/a&gt;, meticulously crafted animation, videos about new discoveries or insights, and a lot of thought about their implications for the future. If you enjoy TV series like &lt;a href=&quot;https://en.wikipedia.org/wiki/Black_Mirror&quot;&gt;black mirror&lt;/a&gt;, this is a channel for you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/user/CGPGrey&quot;&gt;CGP grey&lt;/a&gt; also animates his videos, mostly with his exceptional stick figures, and explains some complicated things that you might not have realized were difficult to explain in the first place. He’s also the author of the video all of us coffee addicts should rally behind:&lt;/p&gt;
&lt;h3 id=&quot;die-hard-theoretical-science&quot;&gt;Die-hard theoretical science&lt;/h3&gt;
&lt;p&gt;Math is very die-hard in my opinion, and so is chemistry. Want to know why imaginary numbers are way more awesome than you were taught at school? watch this video series by welch labs:&lt;/p&gt;
&lt;p&gt;Want to know more about the applications of math and why math is awesome in general, go to the &lt;a href=&quot;https://www.youtube.com/channel/UCoxcjq-8xIDTYp3uz647V5A&quot;&gt;numberphile&lt;/a&gt; channel. Or, for a more visualization and math combined package deal, the &lt;a href=&quot;https://www.youtube.com/channel/UC1_uAIS3r8Vu6JjXWvastJg&quot;&gt;3blue1brown&lt;/a&gt; channel.&lt;/p&gt;
&lt;p&gt;Chemistry more your thing? Want a well spoken English professor to show you some awesome things about chemistry you didn’t know (and were afraid to ask)? &lt;a href=&quot;https://www.youtube.com/user/periodicvideos&quot;&gt;Periodic videos&lt;/a&gt; might be your starting point.&lt;/p&gt;
&lt;p&gt;Or are you more into &lt;a href=&quot;https://www.youtube.com/user/sixtysymbols&quot;&gt;Physics?&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/channel/UCUHW94eEFW7hkUMVaZz4eDg&quot;&gt;Hand-drawn Physics?&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/channel/UC2bkHVIDjXS7sgrgjFtzOXQ&quot;&gt;Engineering?&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-little-more-space-in-your-life&quot;&gt;A little more space in your life?&lt;/h3&gt;
&lt;p&gt;I love rocket launches, so I watch every new launch on &lt;a href=&quot;https://www.youtube.com/channel/UCtI0Hodo5o5dUb67FeUjDeA&quot;&gt;SpaceX&lt;/a&gt; ’s channel religiously. The way they record their launches (and landings!) just captivates me every time, and the explanations in their hosted webcasts are very enlightening and inspiring.&lt;/p&gt;
&lt;p&gt;More space? SciShow has a &lt;a href=&quot;https://www.youtube.com/channel/UCrMePiHCWG4Vwqv3t7W9EFg&quot;&gt;dedicated space channel&lt;/a&gt; which explains all about the stuff the human race does up there.&lt;/p&gt;
&lt;h3 id=&quot;oh-nothing-about-the-humanities-then&quot;&gt;Oh, nothing about the humanities then…&lt;/h3&gt;
&lt;p&gt;Ha! of course there’s tons of stuff here too! Want to know about World history? Please look no further:&lt;/p&gt;
&lt;p&gt;More depth? Extra Credits has you covered! This channel made by game developers has some truly excellently researched content.&lt;/p&gt;
&lt;h3 id=&quot;computers-and-computer-science-more-your-thing&quot;&gt;Computers and Computer Science more your thing?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UC9-y-6csu5WGm29I7JiwpnA&quot;&gt;Computerphile!&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;but-im-strapped-on-time-also-show-me-some-actual-science&quot;&gt;But I’m strapped on time… also, show me some ACTUAL science…&lt;/h3&gt;
&lt;p&gt;No worries my friend! &lt;a href=&quot;https://www.youtube.com/user/keeroyz&quot;&gt;Two minute papers&lt;/a&gt; has you covered! videos made about actual scientific papers, with links to peer-reviewed science to boot.&lt;/p&gt;
&lt;p&gt;The papers covered are mostly about machine learning and visualization, so if you are me, this channel is a gold mine.&lt;/p&gt;
&lt;h3 id=&quot;ok-ok-&quot;&gt;Ok ok …&lt;/h3&gt;
&lt;p&gt;Now that your algorithm is trained properly, you will discover many more channels, I’m sure. And maybe I’ve missed quite a lot of cool science here. If you find something I &lt;em&gt;have&lt;/em&gt; to see, please let me know in the comments. Like you, I’m always looking for more science in my life:)&lt;/p&gt;</description><pubDate>Mon, 03 Jul 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;with-some-help-its-algorithms-can-be-trained-to-find-you-the-good-stuff&quot;&gt;With some help, its algorithms can be trained to find you the good stuff&lt;/h2&gt;
&lt;p&gt;A decade ago, my favorite TV channel used to be the Discovery channel. I spent hours watching shows like How it’s made, Mythbusters and Scrapheap challenge. Since it’s my job, I count myself lucky that my fascination with science and engineering and their newest applications has never ceased, but for the enthusiast like me, the Discovery channel (and any other TV channels) have never captured my interest since their focus (at least here in the Netherlands) has shifted more towards reality shows like Pawn Stars and Deadliest Catch.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For you, the science enthusiast&lt;/strong&gt;, in the age of on-demand video there might not be a better place to find the content you’re looking for than YouTube.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2400&quot; height=&quot;927&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KqrRv97yYgVsXKx5zHlCCw-e8b70083.az--8FQZ_VQnvc.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Even if you’re not too interested popular science, you could learn something from these channels. They are very effective at pitching science to a broad audience. Additionally, it could be very informative to watch what’s going on in a neighboring (or even entirely different) field. At the eScience Center we work together with scientists from many different fields of science. Such collaborations often lead to creative and inspirating solutions — so we highly recommend looking across the fence every once in a while to see what’s happening in other fields!&lt;/p&gt;
&lt;h3 id=&quot;youtube-you-say&quot;&gt;YouTube you say?&lt;/h3&gt;
&lt;p&gt;Isn’t that where all of these weird vloggers tell tales of their daily lives? Isn’t that where gamers post their lets-play video’s and whatnot, and all the content is aimed at children?&lt;/p&gt;
&lt;p&gt;Nay, YouTube offers so much more, if you only know where to look, and if you train &lt;a href=&quot;http://dl.acm.org/citation.cfm?id=1367618&quot;&gt;its algorithms&lt;/a&gt; to find you the stuff you want to see. To help you train your personalized algorithm, here’s a peek at my science-subscription list.&lt;/p&gt;
&lt;h3 id=&quot;broad-topic-channels&quot;&gt;Broad-topic channels&lt;/h3&gt;
&lt;p&gt;Want to know about all of the awesome new scientific discoveries, but not in too much detail? These might be the channels you’re looking for, and also a great way to start your YouTube algorithm training. If you want to know more after watching these videos, you can always go deeper later.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCZYTClx2T1of7BRZ86-8fow&quot;&gt;SciShow&lt;/a&gt; is a great choice in this category. It offers videos on a very wide range of topics. As an example … if you happen to have children that are going through puberty, I feel for you. This video might help:&lt;/p&gt;
&lt;p&gt;Want broad, but a little more explanation? &lt;a href=&quot;https://www.youtube.com/channel/UCHnyfMqiRRG1u-2MsSQLbXA&quot;&gt;Veritasium&lt;/a&gt; might be more your choice.&lt;/p&gt;
&lt;h3 id=&quot;the-food-for-thought&quot;&gt;The food-for-thought&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCsXVk37bltHxD1rDPwtNM8Q&quot;&gt;Kurtzgezagt&lt;/a&gt;, meticulously crafted animation, videos about new discoveries or insights, and a lot of thought about their implications for the future. If you enjoy TV series like &lt;a href=&quot;https://en.wikipedia.org/wiki/Black_Mirror&quot;&gt;black mirror&lt;/a&gt;, this is a channel for you.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/user/CGPGrey&quot;&gt;CGP grey&lt;/a&gt; also animates his videos, mostly with his exceptional stick figures, and explains some complicated things that you might not have realized were difficult to explain in the first place. He’s also the author of the video all of us coffee addicts should rally behind:&lt;/p&gt;
&lt;h3 id=&quot;die-hard-theoretical-science&quot;&gt;Die-hard theoretical science&lt;/h3&gt;
&lt;p&gt;Math is very die-hard in my opinion, and so is chemistry. Want to know why imaginary numbers are way more awesome than you were taught at school? watch this video series by welch labs:&lt;/p&gt;
&lt;p&gt;Want to know more about the applications of math and why math is awesome in general, go to the &lt;a href=&quot;https://www.youtube.com/channel/UCoxcjq-8xIDTYp3uz647V5A&quot;&gt;numberphile&lt;/a&gt; channel. Or, for a more visualization and math combined package deal, the &lt;a href=&quot;https://www.youtube.com/channel/UC1_uAIS3r8Vu6JjXWvastJg&quot;&gt;3blue1brown&lt;/a&gt; channel.&lt;/p&gt;
&lt;p&gt;Chemistry more your thing? Want a well spoken English professor to show you some awesome things about chemistry you didn’t know (and were afraid to ask)? &lt;a href=&quot;https://www.youtube.com/user/periodicvideos&quot;&gt;Periodic videos&lt;/a&gt; might be your starting point.&lt;/p&gt;
&lt;p&gt;Or are you more into &lt;a href=&quot;https://www.youtube.com/user/sixtysymbols&quot;&gt;Physics?&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/channel/UCUHW94eEFW7hkUMVaZz4eDg&quot;&gt;Hand-drawn Physics?&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/channel/UC2bkHVIDjXS7sgrgjFtzOXQ&quot;&gt;Engineering?&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;a-little-more-space-in-your-life&quot;&gt;A little more space in your life?&lt;/h3&gt;
&lt;p&gt;I love rocket launches, so I watch every new launch on &lt;a href=&quot;https://www.youtube.com/channel/UCtI0Hodo5o5dUb67FeUjDeA&quot;&gt;SpaceX&lt;/a&gt; ’s channel religiously. The way they record their launches (and landings!) just captivates me every time, and the explanations in their hosted webcasts are very enlightening and inspiring.&lt;/p&gt;
&lt;p&gt;More space? SciShow has a &lt;a href=&quot;https://www.youtube.com/channel/UCrMePiHCWG4Vwqv3t7W9EFg&quot;&gt;dedicated space channel&lt;/a&gt; which explains all about the stuff the human race does up there.&lt;/p&gt;
&lt;h3 id=&quot;oh-nothing-about-the-humanities-then&quot;&gt;Oh, nothing about the humanities then…&lt;/h3&gt;
&lt;p&gt;Ha! of course there’s tons of stuff here too! Want to know about World history? Please look no further:&lt;/p&gt;
&lt;p&gt;More depth? Extra Credits has you covered! This channel made by game developers has some truly excellently researched content.&lt;/p&gt;
&lt;h3 id=&quot;computers-and-computer-science-more-your-thing&quot;&gt;Computers and Computer Science more your thing?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/channel/UC9-y-6csu5WGm29I7JiwpnA&quot;&gt;Computerphile!&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;but-im-strapped-on-time-also-show-me-some-actual-science&quot;&gt;But I’m strapped on time… also, show me some ACTUAL science…&lt;/h3&gt;
&lt;p&gt;No worries my friend! &lt;a href=&quot;https://www.youtube.com/user/keeroyz&quot;&gt;Two minute papers&lt;/a&gt; has you covered! videos made about actual scientific papers, with links to peer-reviewed science to boot.&lt;/p&gt;
&lt;p&gt;The papers covered are mostly about machine learning and visualization, so if you are me, this channel is a gold mine.&lt;/p&gt;
&lt;h3 id=&quot;ok-ok-&quot;&gt;Ok ok …&lt;/h3&gt;
&lt;p&gt;Now that your algorithm is trained properly, you will discover many more channels, I’m sure. And maybe I’ve missed quite a lot of cool science here. If you find something I &lt;em&gt;have&lt;/em&gt; to see, please let me know in the comments. Like you, I’m always looking for more science in my life:)&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_KqrRv97yYgVsXKx5zHlCCw-e8b70083.az--8FQZ.png" medium="image"/><author>Maarten van Meersbergen</author></item><item><title>what is the impact of visualization on science</title><link>https://blog2.esciencecenter.nl/posts/2017-06-21---what-is-the-impact-of-visualization-on-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-06-21---what-is-the-impact-of-visualization-on-science</guid><description>&lt;p&gt;Scientific visualization impacts all research disciplines. Understanding our past, dealing with the challenges of climate change, discovering dark matter, and analyzing human behavior are all areas where scientific visualization is applied to gain scientific insight.&lt;/p&gt;
&lt;p&gt;On 20 June 2017 we invited a diverse group of scientists to Rotterdam to show how they apply visualization technologies — from archaeology to astronomy. We recorded all presentations for you, which you can find below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;653&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KaZi1Mej2bsU6Gjvb8X0fw-61d072c6.BwX03uq4_2ihsYA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction-to-scientific-visualization-from-archaeology-to-astronomy&quot;&gt;Introduction to “Scientific Visualization: From Archaeology to Astronomy”&lt;/h2&gt;
&lt;p&gt;Willem van Hage (Netherlands eScience Center)&lt;/p&gt;
&lt;h2 id=&quot;from-information-visualization-to-visual-analytics-combining-the-strengths-of-man-and-machine&quot;&gt;From Information Visualization to Visual Analytics: Combining the strengths of man and machine&lt;/h2&gt;
&lt;p&gt;Jack van Wijk (Eindhoven University of Technology)&lt;/p&gt;
&lt;p&gt;Information Visualization concerns the use of interactive computer graphics to obtain insight in large amounts of abstract data, like tables, hierarchies, and networks. The aim is to exploit the unique capabilities of the human visual system to detect patterns, structures, and irregularities, and thereby to enable experts to analyze big and messy data. In this talk Jack gives an overview, illustrated with examples of work from Eindhoven, and trends and challenges are discussed. The use of familiar representations in combination with fluent interaction is often highly effective, as well as integration of methods from statistics, machine learning, and data mining.&lt;/p&gt;
&lt;h2 id=&quot;context-aware-selection-techniques-and-visual-storytelling&quot;&gt;Context-Aware Selection Techniques and Visual Storytelling&lt;/h2&gt;
&lt;p&gt;Lingyun Yu (University of Groningen)&lt;/p&gt;
&lt;p&gt;Exploratory data visualization and analysis is a fundamental element of many visualization systems. It provides domain experts with tools to study unknown datasets, an activity during which the data is examined more closely to discover interesting or unexpected patterns. One essential tool for exploratory visualization is the ability to select different subsets of the dataset, based on the current state of the exploration and/or one’s own intuition. Lingyun presents a family of interactive Context-Aware Selection Techniques for the analysis of large 3D scientific datasets. She also briefly discusses how selection can be part of interactive visual storytelling.&lt;/p&gt;
&lt;h2 id=&quot;visualization-of-large-scale-cellular-simulations-of-blood&quot;&gt;Visualization of large-scale cellular simulations of blood&lt;/h2&gt;
&lt;p&gt;Gábor Závodszky (University of Amsterdam) &amp;#x26; Paul Melis (SURFsara)&lt;/p&gt;
&lt;p&gt;Blood is a complex suspension constituted of various components suspended in plasma. Red blood cells are the major component and determine blood rheology. Platelets form the link between transport dynamics and several vital biochemical processes. Their collective behaviour can provide explanation to the most fundamental transport phenomena in blood, such as the non-Newtonian viscosity, the margination of platelets, the Fåhræus effect, or the appearance of a cell-free layer. The knowledge of the emergent complex rheology is gaining importance due to the spreading application of micro-medical devices in numerous clinical applications during the last years. The open questions are often targeted by cellular level simulations. In this talk Gábor and Paul focus on the evaluation of the output of such large-scale cellular level computations. Usually, it is infeasible to describe the overall behaviour of the system with single parameters and thus visualisation techniques can provide significant help in processing results, for example to select regions of interest, separate specific events, or to shed light on higher level correlations.&lt;/p&gt;
&lt;h2 id=&quot;interactive-visual-exloration-of-the-spatial-and-temporal-human-brain-transcriptome&quot;&gt;Interactive visual exloration of the spatial and temporal human brain transcriptome&lt;/h2&gt;
&lt;p&gt;Boudewijn Lelieveldt (Leiden University Medical Center)&lt;/p&gt;
&lt;p&gt;The Allen Institute for Brain Science was established in 2003, and over the past decade, it has grown into a world-leading neuroscience institution by launching a number of publicly available atlases of “where and when during development genes are expressed in the brain”. This presentation is a short introduction on the Allen Brain atlas: “What is it, and what can you do with it in the context of neuroimaging research?”.&lt;/p&gt;
&lt;p&gt;BrainScope.nl is also presented: a web portal for fast, interactive visual exploration of the Allen Atlases of the adult and developing human brain transcriptome. Through a novel methodology to explore high-dimensional data (dual t-SNE), BrainScope.nl enables the linked, all-in-one visualization of genes and samples across the whole brain and genome, and across developmental stages. Boudewijn shows that densities in t-SNE scatter plots of the spatial samples coincide with anatomical regions, and that densities in t-SNE scatter plots of the genes represent gene co-expression modules that are significantly enriched for biological functions. Boudewijn also shows that the topography of the gene t-SNE maps reflect brain region-specific gene functions, enabling hypothesis and data driven research.&lt;/p&gt;
&lt;p&gt;Boudewijn demonstrates the discovery potential of BrainScope.nl through three examples: (i) analysis of cell type specific gene sets, (ii) analysis of a set of stable gene co-expression modules across the adult human donors and (iii) analysis of the evolution of co-expression of oligodendrocyte specific genes over developmental stages. Brainscope is publicly accessible at &lt;a href=&quot;http://www.brainscope.nl/&quot;&gt;www.brainscope.nl&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;visualising-a-billion-stars&quot;&gt;Visualising a billion stars&lt;/h2&gt;
&lt;p&gt;Maarten Breddels (University of Groningen)&lt;/p&gt;
&lt;p&gt;With large astronomical catalogues containing more than a billion stars becoming common, we are preparing for methods to visualize and explore these large datasets. Data volumes of this size requires different visualization techniques, since scatter plots become too slow and meaningless due to overplotting. Maarten solves the performance and visualization issue using binned statistics, e.g. histograms, density maps, and volume rendering in 3d. The calculation of statistics on N-dimensional grids is handled by Python library called vaex, which Maarten introduces. It can process at least a billion samples per second, to produce for instance the mean of a quantity on a regular grid. This statistics can be calculated for any mathematical expression on the data and can be on the full dataset or subsets, specified by queries/selections.&lt;/p&gt;
&lt;p&gt;However, to visualize higher dimensional data in the notebook interactively, no suitable solution existed. This led to the development of ipyvolume, which can render 3d volumes and up to a million glyphs (scatter plots and quiver) in the Jupyter notebook as a widget. With the browser as a platform these 3d plots can also be embedded in static html files. This allows for sharing with colleagues, rendering on your tablet (paperless office), outreach, press release material, etc. Full screen stereo rendering allows for a virtual reality experience using your phone and Google Cardboard, a minor investment compared to other VR head mountables. Overlaying 3d quiver plots on a 3d volume rendering allows exploring a 6d (or higher) space.&lt;/p&gt;
&lt;p&gt;Vaex and ipyvolume can be used together to explore and visualize any large tabular data set, or separately to calculate statistics, and render 3d plots in the notebook and outside.&lt;/p&gt;
&lt;h2 id=&quot;painting-in-hydrodynamic-models&quot;&gt;Painting in Hydrodynamic Models&lt;/h2&gt;
&lt;p&gt;Fedor Baart (Deltares)&lt;/p&gt;
&lt;p&gt;The emergence of interactive art has blurred the line between computer graphics, natural user interfaces and art. Here we apply this artistic method to computer models. This presentation shows the transformation of a simple flow visualisation into an interactive painting. This interactive painting is used as an aesthetically representation of the environment, but also to solve real world problems. The beauty of the flow of water is shown with examples from oceans, seas, bays, and rivers.&lt;/p&gt;
&lt;h2 id=&quot;golden-agents-in-virtual-interiors-visualizing-uncertainties-in-the-spatial-humanities&quot;&gt;Golden Agents in Virtual Interiors. Visualizing Uncertainties in the Spatial Humanities&lt;/h2&gt;
&lt;p&gt;Charles van den Heuvel (Huygens ING / University of Amsterdam)&lt;/p&gt;
&lt;p&gt;The NWO-Large Infrastructure project &lt;em&gt;Golden Agents. Creative Industries and the Making of the Dutch Golden Age&lt;/em&gt; combines SW and multi-agent technologies to support analyses of interactions between various branches and between the production and consumption of the creative industries. Here Charles presents the plans for a new project for creating multilayered maps and multidimensional spaces as a virtual research environment on top of the knowledge graph.Visualizing uncertainties in the interfaces between these maps and virtual spaces is not only necessary for this project but for the spatial humanities in general.&lt;/p&gt;
&lt;h2 id=&quot;3d-archaeology-in-rome&quot;&gt;3D Archaeology in Rome&lt;/h2&gt;
&lt;p&gt;Maurice de Kleijn (VU University Amsterdam)&lt;/p&gt;
&lt;p&gt;The use of 3D technologies in archaeology has grown enormously over the past couple of decades. Nowadays, archaeologists use these technologies to record, present, analyse and reconstruct archaeological sites. Since the tools archaeologists apply mostly originate from other domains, the developments in the archaeological use of 3D technologies are characterized as technology-driven rather than methodology-driven. The recent trend of Free and Open Source Software (FOSS) and the technological improvements of digital infrastructures are changing this, allowing future innovations to be truly driven by archaeological needs.&lt;/p&gt;
&lt;p&gt;Maurice discusses the advantages of approaching 3D technologies as an 3D GIS infrastructure, taking into account sustainability and different Information Technology literacy levels of the users. He does so by presenting the development of the FOSS-based 3D GIS for Mapping the Via Appia. Based on insights from this project, a research strategy for the development of future 3D GIS projects in archaeology is proposed.&lt;/p&gt;
&lt;h2 id=&quot;whats-your-story-morning-glory&quot;&gt;What’s Your Story, Morning Glory?&lt;/h2&gt;
&lt;p&gt;Tommaso Caselli (VU University Amsterdam)&lt;/p&gt;
&lt;p&gt;StoryTeller visualises event-structures generated by the NewsReader software as structured stories. StoryTeller can show actor-centric, event-centric, and source-centric storylines, allowing to explore large collections of documents. In StoryTeller events are ordered in time, and connected to approximate a story pattern. The model behind StoryTeller assumes the existence of a climax event, a critical turning point in an event sequence. Starting from it, a story is reconstructed by connecting events which are conditional, i.e. precede, and consequential to, i.e. follow, the climax event. Users can interact selecting and zooming into elements of their choice, generating their story.&lt;/p&gt;
&lt;h2 id=&quot;closing-remarks&quot;&gt;Closing remarks&lt;/h2&gt;
&lt;p&gt;Wilco Hazeleger (Netherlands eScience Center)&lt;/p&gt;</description><pubDate>Wed, 21 Jun 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Scientific visualization impacts all research disciplines. Understanding our past, dealing with the challenges of climate change, discovering dark matter, and analyzing human behavior are all areas where scientific visualization is applied to gain scientific insight.&lt;/p&gt;
&lt;p&gt;On 20 June 2017 we invited a diverse group of scientists to Rotterdam to show how they apply visualization technologies — from archaeology to astronomy. We recorded all presentations for you, which you can find below.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1920&quot; height=&quot;653&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KaZi1Mej2bsU6Gjvb8X0fw-61d072c6.BwX03uq4_2ihsYA.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;introduction-to-scientific-visualization-from-archaeology-to-astronomy&quot;&gt;Introduction to “Scientific Visualization: From Archaeology to Astronomy”&lt;/h2&gt;
&lt;p&gt;Willem van Hage (Netherlands eScience Center)&lt;/p&gt;
&lt;h2 id=&quot;from-information-visualization-to-visual-analytics-combining-the-strengths-of-man-and-machine&quot;&gt;From Information Visualization to Visual Analytics: Combining the strengths of man and machine&lt;/h2&gt;
&lt;p&gt;Jack van Wijk (Eindhoven University of Technology)&lt;/p&gt;
&lt;p&gt;Information Visualization concerns the use of interactive computer graphics to obtain insight in large amounts of abstract data, like tables, hierarchies, and networks. The aim is to exploit the unique capabilities of the human visual system to detect patterns, structures, and irregularities, and thereby to enable experts to analyze big and messy data. In this talk Jack gives an overview, illustrated with examples of work from Eindhoven, and trends and challenges are discussed. The use of familiar representations in combination with fluent interaction is often highly effective, as well as integration of methods from statistics, machine learning, and data mining.&lt;/p&gt;
&lt;h2 id=&quot;context-aware-selection-techniques-and-visual-storytelling&quot;&gt;Context-Aware Selection Techniques and Visual Storytelling&lt;/h2&gt;
&lt;p&gt;Lingyun Yu (University of Groningen)&lt;/p&gt;
&lt;p&gt;Exploratory data visualization and analysis is a fundamental element of many visualization systems. It provides domain experts with tools to study unknown datasets, an activity during which the data is examined more closely to discover interesting or unexpected patterns. One essential tool for exploratory visualization is the ability to select different subsets of the dataset, based on the current state of the exploration and/or one’s own intuition. Lingyun presents a family of interactive Context-Aware Selection Techniques for the analysis of large 3D scientific datasets. She also briefly discusses how selection can be part of interactive visual storytelling.&lt;/p&gt;
&lt;h2 id=&quot;visualization-of-large-scale-cellular-simulations-of-blood&quot;&gt;Visualization of large-scale cellular simulations of blood&lt;/h2&gt;
&lt;p&gt;Gábor Závodszky (University of Amsterdam) &amp;#x26; Paul Melis (SURFsara)&lt;/p&gt;
&lt;p&gt;Blood is a complex suspension constituted of various components suspended in plasma. Red blood cells are the major component and determine blood rheology. Platelets form the link between transport dynamics and several vital biochemical processes. Their collective behaviour can provide explanation to the most fundamental transport phenomena in blood, such as the non-Newtonian viscosity, the margination of platelets, the Fåhræus effect, or the appearance of a cell-free layer. The knowledge of the emergent complex rheology is gaining importance due to the spreading application of micro-medical devices in numerous clinical applications during the last years. The open questions are often targeted by cellular level simulations. In this talk Gábor and Paul focus on the evaluation of the output of such large-scale cellular level computations. Usually, it is infeasible to describe the overall behaviour of the system with single parameters and thus visualisation techniques can provide significant help in processing results, for example to select regions of interest, separate specific events, or to shed light on higher level correlations.&lt;/p&gt;
&lt;h2 id=&quot;interactive-visual-exloration-of-the-spatial-and-temporal-human-brain-transcriptome&quot;&gt;Interactive visual exloration of the spatial and temporal human brain transcriptome&lt;/h2&gt;
&lt;p&gt;Boudewijn Lelieveldt (Leiden University Medical Center)&lt;/p&gt;
&lt;p&gt;The Allen Institute for Brain Science was established in 2003, and over the past decade, it has grown into a world-leading neuroscience institution by launching a number of publicly available atlases of “where and when during development genes are expressed in the brain”. This presentation is a short introduction on the Allen Brain atlas: “What is it, and what can you do with it in the context of neuroimaging research?”.&lt;/p&gt;
&lt;p&gt;BrainScope.nl is also presented: a web portal for fast, interactive visual exploration of the Allen Atlases of the adult and developing human brain transcriptome. Through a novel methodology to explore high-dimensional data (dual t-SNE), BrainScope.nl enables the linked, all-in-one visualization of genes and samples across the whole brain and genome, and across developmental stages. Boudewijn shows that densities in t-SNE scatter plots of the spatial samples coincide with anatomical regions, and that densities in t-SNE scatter plots of the genes represent gene co-expression modules that are significantly enriched for biological functions. Boudewijn also shows that the topography of the gene t-SNE maps reflect brain region-specific gene functions, enabling hypothesis and data driven research.&lt;/p&gt;
&lt;p&gt;Boudewijn demonstrates the discovery potential of BrainScope.nl through three examples: (i) analysis of cell type specific gene sets, (ii) analysis of a set of stable gene co-expression modules across the adult human donors and (iii) analysis of the evolution of co-expression of oligodendrocyte specific genes over developmental stages. Brainscope is publicly accessible at &lt;a href=&quot;http://www.brainscope.nl/&quot;&gt;www.brainscope.nl&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;visualising-a-billion-stars&quot;&gt;Visualising a billion stars&lt;/h2&gt;
&lt;p&gt;Maarten Breddels (University of Groningen)&lt;/p&gt;
&lt;p&gt;With large astronomical catalogues containing more than a billion stars becoming common, we are preparing for methods to visualize and explore these large datasets. Data volumes of this size requires different visualization techniques, since scatter plots become too slow and meaningless due to overplotting. Maarten solves the performance and visualization issue using binned statistics, e.g. histograms, density maps, and volume rendering in 3d. The calculation of statistics on N-dimensional grids is handled by Python library called vaex, which Maarten introduces. It can process at least a billion samples per second, to produce for instance the mean of a quantity on a regular grid. This statistics can be calculated for any mathematical expression on the data and can be on the full dataset or subsets, specified by queries/selections.&lt;/p&gt;
&lt;p&gt;However, to visualize higher dimensional data in the notebook interactively, no suitable solution existed. This led to the development of ipyvolume, which can render 3d volumes and up to a million glyphs (scatter plots and quiver) in the Jupyter notebook as a widget. With the browser as a platform these 3d plots can also be embedded in static html files. This allows for sharing with colleagues, rendering on your tablet (paperless office), outreach, press release material, etc. Full screen stereo rendering allows for a virtual reality experience using your phone and Google Cardboard, a minor investment compared to other VR head mountables. Overlaying 3d quiver plots on a 3d volume rendering allows exploring a 6d (or higher) space.&lt;/p&gt;
&lt;p&gt;Vaex and ipyvolume can be used together to explore and visualize any large tabular data set, or separately to calculate statistics, and render 3d plots in the notebook and outside.&lt;/p&gt;
&lt;h2 id=&quot;painting-in-hydrodynamic-models&quot;&gt;Painting in Hydrodynamic Models&lt;/h2&gt;
&lt;p&gt;Fedor Baart (Deltares)&lt;/p&gt;
&lt;p&gt;The emergence of interactive art has blurred the line between computer graphics, natural user interfaces and art. Here we apply this artistic method to computer models. This presentation shows the transformation of a simple flow visualisation into an interactive painting. This interactive painting is used as an aesthetically representation of the environment, but also to solve real world problems. The beauty of the flow of water is shown with examples from oceans, seas, bays, and rivers.&lt;/p&gt;
&lt;h2 id=&quot;golden-agents-in-virtual-interiors-visualizing-uncertainties-in-the-spatial-humanities&quot;&gt;Golden Agents in Virtual Interiors. Visualizing Uncertainties in the Spatial Humanities&lt;/h2&gt;
&lt;p&gt;Charles van den Heuvel (Huygens ING / University of Amsterdam)&lt;/p&gt;
&lt;p&gt;The NWO-Large Infrastructure project &lt;em&gt;Golden Agents. Creative Industries and the Making of the Dutch Golden Age&lt;/em&gt; combines SW and multi-agent technologies to support analyses of interactions between various branches and between the production and consumption of the creative industries. Here Charles presents the plans for a new project for creating multilayered maps and multidimensional spaces as a virtual research environment on top of the knowledge graph.Visualizing uncertainties in the interfaces between these maps and virtual spaces is not only necessary for this project but for the spatial humanities in general.&lt;/p&gt;
&lt;h2 id=&quot;3d-archaeology-in-rome&quot;&gt;3D Archaeology in Rome&lt;/h2&gt;
&lt;p&gt;Maurice de Kleijn (VU University Amsterdam)&lt;/p&gt;
&lt;p&gt;The use of 3D technologies in archaeology has grown enormously over the past couple of decades. Nowadays, archaeologists use these technologies to record, present, analyse and reconstruct archaeological sites. Since the tools archaeologists apply mostly originate from other domains, the developments in the archaeological use of 3D technologies are characterized as technology-driven rather than methodology-driven. The recent trend of Free and Open Source Software (FOSS) and the technological improvements of digital infrastructures are changing this, allowing future innovations to be truly driven by archaeological needs.&lt;/p&gt;
&lt;p&gt;Maurice discusses the advantages of approaching 3D technologies as an 3D GIS infrastructure, taking into account sustainability and different Information Technology literacy levels of the users. He does so by presenting the development of the FOSS-based 3D GIS for Mapping the Via Appia. Based on insights from this project, a research strategy for the development of future 3D GIS projects in archaeology is proposed.&lt;/p&gt;
&lt;h2 id=&quot;whats-your-story-morning-glory&quot;&gt;What’s Your Story, Morning Glory?&lt;/h2&gt;
&lt;p&gt;Tommaso Caselli (VU University Amsterdam)&lt;/p&gt;
&lt;p&gt;StoryTeller visualises event-structures generated by the NewsReader software as structured stories. StoryTeller can show actor-centric, event-centric, and source-centric storylines, allowing to explore large collections of documents. In StoryTeller events are ordered in time, and connected to approximate a story pattern. The model behind StoryTeller assumes the existence of a climax event, a critical turning point in an event sequence. Starting from it, a story is reconstructed by connecting events which are conditional, i.e. precede, and consequential to, i.e. follow, the climax event. Users can interact selecting and zooming into elements of their choice, generating their story.&lt;/p&gt;
&lt;h2 id=&quot;closing-remarks&quot;&gt;Closing remarks&lt;/h2&gt;
&lt;p&gt;Wilco Hazeleger (Netherlands eScience Center)&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_KaZi1Mej2bsU6Gjvb8X0fw-61d072c6.BwX03uq4.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>a license to science</title><link>https://blog2.esciencecenter.nl/posts/2017-05-23---a-license-to-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-05-23---a-license-to-science</guid><description>&lt;p&gt;The Beastie Boys were &lt;a href=&quot;https://en.wikipedia.org/wiki/Licensed_to_Ill&quot;&gt;Licensed to Ill&lt;/a&gt;, James Bond had a &lt;a href=&quot;https://en.wikipedia.org/wiki/Licence_to_Kill&quot;&gt;licence to kill&lt;/a&gt;. I want a license to science.&lt;/p&gt;
&lt;p&gt;Science, it is said, is standing on the shoulders of giants. We scientists design experiments, collect data, determine facts, and then we publish our findings in the scientific literature, so that others can read about them and build upon them.&lt;/p&gt;
&lt;p&gt;As our technologies for doing science become more advanced, we do more experiments, and our experiments yield more data. We use computers and specialised software to help deal with the data deluge, and we use the internet to share our data and also our software. In some fields this has been happening for a long time, in others it’s a more recent development, but increasingly all science is becoming what we call &lt;a href=&quot;https://en.wikipedia.org/wiki/E-Science&quot;&gt;eScience&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is important to realize that sharing software and data brings with it a new element of scientific practice: the law.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_xp0qkMsh77QMu93QaIOGoQ-2dd1ef0f.CHuOl5FW_NInLM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;XKCD #14. Creator Randall Munroe licensed this comic under the CC-BY-NC 2.5 license, thus giving me explicit permission to use it in this blog post.&lt;/p&gt;
&lt;h2 id=&quot;legal-trouble&quot;&gt;Legal Trouble&lt;/h2&gt;
&lt;p&gt;Traditional science is legally pretty easy. Simple facts are not protected by any laws. So, if you read something in a paper, you are free to use it as the basis of an argument in your own paper, and if someone calculates and publishes the value of pi, then you are free to use that to calculate the circumference of a circle.&lt;/p&gt;
&lt;p&gt;eScience, with its exchange of software and data, is a bit more complicated. Software is covered by copyright law, and data sets may be as well. Also, in some countries, data sets are covered by database rights. These rights magically appear the moment the software or data set is created, and by default they make it illegal for anyone who isn’t the owner to change the software, incorporate it into another program, or to use the data set as part of another one. The shoulders of eScience giants have fences around them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The shoulders of eScience giants have fences around them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At the Netherlands eScience Center, we sometimes run into these fences. Someone publishes some software or a data set on the internet, intending to share it, but does not put a license on it. Without a license, the default legal protections apply. At best we can perhaps download the software and run it to see if we get the same result, or download the data and look at it. But we cannot modify the software, or combine it with other software to make something new and innovative, and we cannot combine the data with other data to make a new data set to publish.&lt;/p&gt;
&lt;p&gt;Instead, we’ll have to use another program (with perhaps less of a scientific pedigree), write something ourselves, or just not do the science we want to do. So, we do more work, and you, the author, miss an opportunity for collaboration and/or a citation. Obviously, that’s not an optimal solution. If you license your work, rather than just putting it up on the web without a license, then people can actually build on it. A license is like a gate in the fence.&lt;/p&gt;
&lt;h2 id=&quot;licensing-your-work&quot;&gt;Licensing your work&lt;/h2&gt;
&lt;p&gt;Of course, this may raise some questions. Do I need a lawyer? What’s in it for me? Where do I start?&lt;/p&gt;
&lt;h3 id=&quot;about-that-lawyer&quot;&gt;About that lawyer&lt;/h3&gt;
&lt;p&gt;While licensing copyrights and database rights is a legal activity, you don’t need a lawyer. We make many decisions with potential legal implications every day, and most of us don’t need a lawyer to not, say, violate any traffic laws, break into someone’s house, or commit a murder. (James Bond excepted, but then again, he’s got a license…) For both software and data, there are several standard licenses available that have been written by lawyers, that are widely accepted, and that can be used by anyone.&lt;/p&gt;
&lt;h3 id=&quot;why-licensing-is-good-for-you&quot;&gt;Why licensing is good for you&lt;/h3&gt;
&lt;p&gt;Why would you add a license? First, these licenses contain a disclaimer, making it clear to anyone using your software or data that if it breaks, they get to keep both pieces, and that it’s up to them to glue them back together. A big bold text saying that the author doesn’t guarantee anything and disclaims all liability is very useful if someone decides to use your software for a self-driving car or a medical device.&lt;/p&gt;
&lt;p&gt;Second, attribution. If someone shares a copy of your program or data, or uses it as part of another program or data set, then they’re required to include your license and your note saying that you wrote it.&lt;/p&gt;
&lt;p&gt;Note that there is no requirement to cite any of your papers in the standard licenses. This would be difficult to do for technical reasons, and in the end your published papers don’t have such a legal requirement either. For software or data, it’s a good idea to put a request in the documentation to cite the paper you wrote about it, with a reference of course. You should do so! But be aware that this does not carry any legal weight.&lt;/p&gt;
&lt;p&gt;Third, impact. Scientific impact is all about how many people build on your work, and if you don’t give them permission to do so, then that number will be low indeed.&lt;/p&gt;
&lt;p&gt;Of course, there may be situations in which you do not want people to use your software or data at all, or only if they ask you nicely first and promise to not share with anyone. In that case, Open Source and Open Access is not what you want. However, rather than putting your software or data online without a license, you should then just keep it to yourself entirely.&lt;/p&gt;
&lt;h3 id=&quot;picking-a-license&quot;&gt;Picking a license&lt;/h3&gt;
&lt;p&gt;So where to start? First, you can only license copyrights and database rights you actually own. If you created your work as part of your job, then your employer (e.g. university) probably owns those rights. In that case, you should talk to your boss or your technology transfer office or similar department to find out whether you need permission to license your work on behalf of them. If you incorporated work created by others into your program or data set, then you’ll need to take into account the licenses of those works as well. The details of that are too much for this blog post; you’ll want to look into &lt;a href=&quot;https://www.google.com/#q=license+compatibility&quot;&gt;license compatibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For software, the fine people at &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; have made a &lt;a href=&quot;https://choosealicense.com/&quot;&gt;license selection tool&lt;/a&gt;. At the Netherlands eScience Center, we use the Apache License 2.0 by default. This license gives everyone as much freedom as possible to use and combine our software, while still requiring attribution. As we are a publicly funded organization, we want to allow people to build non- &lt;a href=&quot;https://en.wikipedia.org/wiki/Free_software&quot;&gt;free software&lt;/a&gt; using our code as well, so we try to avoid &lt;a href=&quot;https://en.wikipedia.org/wiki/Copyleft&quot;&gt;copyleft&lt;/a&gt; licenses such as the GNU General Public License (GPL) when we reuse software. However, if there is no good alternative, we’ll go with the GPL rather than rewriting something from scratch.&lt;/p&gt;
&lt;p&gt;If you are licensing a data set, a &lt;a href=&quot;https://creativecommons.org/&quot;&gt;Creative Commons (CC)&lt;/a&gt; license is a good choice. There are several different CC licenses, with different terms, and the Creative Commons website has a &lt;a href=&quot;https://creativecommons.org/choose/&quot;&gt;handy tool to help you choose&lt;/a&gt;. Make sure to use version 4.0 of your chosen license, as lower versions do not take into account database rights. At the eScience Center, we use the CC Attribution 4.0 license (CC-BY-4.0) by default. Like the Apache License, this license gives everyone as much freedom as possible to use the data sets we make, and combine them with others, but ensures that we’ll get attributed when they do. We also sometimes use other licenses, for instance if we’ve included someone else’s data and their license requires us to do so.&lt;/p&gt;
&lt;p&gt;Which license to choose is up to you in the end, or up to your employer if they own the rights to your program or data set, and have a policy on this. But when you publish a program or a data set, please make sure it has a proper license! Thanks!&lt;/p&gt;</description><pubDate>Tue, 23 May 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The Beastie Boys were &lt;a href=&quot;https://en.wikipedia.org/wiki/Licensed_to_Ill&quot;&gt;Licensed to Ill&lt;/a&gt;, James Bond had a &lt;a href=&quot;https://en.wikipedia.org/wiki/Licence_to_Kill&quot;&gt;licence to kill&lt;/a&gt;. I want a license to science.&lt;/p&gt;
&lt;p&gt;Science, it is said, is standing on the shoulders of giants. We scientists design experiments, collect data, determine facts, and then we publish our findings in the scientific literature, so that others can read about them and build upon them.&lt;/p&gt;
&lt;p&gt;As our technologies for doing science become more advanced, we do more experiments, and our experiments yield more data. We use computers and specialised software to help deal with the data deluge, and we use the internet to share our data and also our software. In some fields this has been happening for a long time, in others it’s a more recent development, but increasingly all science is becoming what we call &lt;a href=&quot;https://en.wikipedia.org/wiki/E-Science&quot;&gt;eScience&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is important to realize that sharing software and data brings with it a new element of scientific practice: the law.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;499&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_xp0qkMsh77QMu93QaIOGoQ-2dd1ef0f.CHuOl5FW_NInLM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;XKCD #14. Creator Randall Munroe licensed this comic under the CC-BY-NC 2.5 license, thus giving me explicit permission to use it in this blog post.&lt;/p&gt;
&lt;h2 id=&quot;legal-trouble&quot;&gt;Legal Trouble&lt;/h2&gt;
&lt;p&gt;Traditional science is legally pretty easy. Simple facts are not protected by any laws. So, if you read something in a paper, you are free to use it as the basis of an argument in your own paper, and if someone calculates and publishes the value of pi, then you are free to use that to calculate the circumference of a circle.&lt;/p&gt;
&lt;p&gt;eScience, with its exchange of software and data, is a bit more complicated. Software is covered by copyright law, and data sets may be as well. Also, in some countries, data sets are covered by database rights. These rights magically appear the moment the software or data set is created, and by default they make it illegal for anyone who isn’t the owner to change the software, incorporate it into another program, or to use the data set as part of another one. The shoulders of eScience giants have fences around them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The shoulders of eScience giants have fences around them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At the Netherlands eScience Center, we sometimes run into these fences. Someone publishes some software or a data set on the internet, intending to share it, but does not put a license on it. Without a license, the default legal protections apply. At best we can perhaps download the software and run it to see if we get the same result, or download the data and look at it. But we cannot modify the software, or combine it with other software to make something new and innovative, and we cannot combine the data with other data to make a new data set to publish.&lt;/p&gt;
&lt;p&gt;Instead, we’ll have to use another program (with perhaps less of a scientific pedigree), write something ourselves, or just not do the science we want to do. So, we do more work, and you, the author, miss an opportunity for collaboration and/or a citation. Obviously, that’s not an optimal solution. If you license your work, rather than just putting it up on the web without a license, then people can actually build on it. A license is like a gate in the fence.&lt;/p&gt;
&lt;h2 id=&quot;licensing-your-work&quot;&gt;Licensing your work&lt;/h2&gt;
&lt;p&gt;Of course, this may raise some questions. Do I need a lawyer? What’s in it for me? Where do I start?&lt;/p&gt;
&lt;h3 id=&quot;about-that-lawyer&quot;&gt;About that lawyer&lt;/h3&gt;
&lt;p&gt;While licensing copyrights and database rights is a legal activity, you don’t need a lawyer. We make many decisions with potential legal implications every day, and most of us don’t need a lawyer to not, say, violate any traffic laws, break into someone’s house, or commit a murder. (James Bond excepted, but then again, he’s got a license…) For both software and data, there are several standard licenses available that have been written by lawyers, that are widely accepted, and that can be used by anyone.&lt;/p&gt;
&lt;h3 id=&quot;why-licensing-is-good-for-you&quot;&gt;Why licensing is good for you&lt;/h3&gt;
&lt;p&gt;Why would you add a license? First, these licenses contain a disclaimer, making it clear to anyone using your software or data that if it breaks, they get to keep both pieces, and that it’s up to them to glue them back together. A big bold text saying that the author doesn’t guarantee anything and disclaims all liability is very useful if someone decides to use your software for a self-driving car or a medical device.&lt;/p&gt;
&lt;p&gt;Second, attribution. If someone shares a copy of your program or data, or uses it as part of another program or data set, then they’re required to include your license and your note saying that you wrote it.&lt;/p&gt;
&lt;p&gt;Note that there is no requirement to cite any of your papers in the standard licenses. This would be difficult to do for technical reasons, and in the end your published papers don’t have such a legal requirement either. For software or data, it’s a good idea to put a request in the documentation to cite the paper you wrote about it, with a reference of course. You should do so! But be aware that this does not carry any legal weight.&lt;/p&gt;
&lt;p&gt;Third, impact. Scientific impact is all about how many people build on your work, and if you don’t give them permission to do so, then that number will be low indeed.&lt;/p&gt;
&lt;p&gt;Of course, there may be situations in which you do not want people to use your software or data at all, or only if they ask you nicely first and promise to not share with anyone. In that case, Open Source and Open Access is not what you want. However, rather than putting your software or data online without a license, you should then just keep it to yourself entirely.&lt;/p&gt;
&lt;h3 id=&quot;picking-a-license&quot;&gt;Picking a license&lt;/h3&gt;
&lt;p&gt;So where to start? First, you can only license copyrights and database rights you actually own. If you created your work as part of your job, then your employer (e.g. university) probably owns those rights. In that case, you should talk to your boss or your technology transfer office or similar department to find out whether you need permission to license your work on behalf of them. If you incorporated work created by others into your program or data set, then you’ll need to take into account the licenses of those works as well. The details of that are too much for this blog post; you’ll want to look into &lt;a href=&quot;https://www.google.com/#q=license+compatibility&quot;&gt;license compatibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For software, the fine people at &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; have made a &lt;a href=&quot;https://choosealicense.com/&quot;&gt;license selection tool&lt;/a&gt;. At the Netherlands eScience Center, we use the Apache License 2.0 by default. This license gives everyone as much freedom as possible to use and combine our software, while still requiring attribution. As we are a publicly funded organization, we want to allow people to build non- &lt;a href=&quot;https://en.wikipedia.org/wiki/Free_software&quot;&gt;free software&lt;/a&gt; using our code as well, so we try to avoid &lt;a href=&quot;https://en.wikipedia.org/wiki/Copyleft&quot;&gt;copyleft&lt;/a&gt; licenses such as the GNU General Public License (GPL) when we reuse software. However, if there is no good alternative, we’ll go with the GPL rather than rewriting something from scratch.&lt;/p&gt;
&lt;p&gt;If you are licensing a data set, a &lt;a href=&quot;https://creativecommons.org/&quot;&gt;Creative Commons (CC)&lt;/a&gt; license is a good choice. There are several different CC licenses, with different terms, and the Creative Commons website has a &lt;a href=&quot;https://creativecommons.org/choose/&quot;&gt;handy tool to help you choose&lt;/a&gt;. Make sure to use version 4.0 of your chosen license, as lower versions do not take into account database rights. At the eScience Center, we use the CC Attribution 4.0 license (CC-BY-4.0) by default. Like the Apache License, this license gives everyone as much freedom as possible to use the data sets we make, and combine them with others, but ensures that we’ll get attributed when they do. We also sometimes use other licenses, for instance if we’ve included someone else’s data and their license requires us to do so.&lt;/p&gt;
&lt;p&gt;Which license to choose is up to you in the end, or up to your employer if they own the rights to your program or data set, and have a policy on this. But when you publish a program or a data set, please make sure it has a proper license! Thanks!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_xp0qkMsh77QMu93QaIOGoQ-2dd1ef0f.CHuOl5FW.jpeg" medium="image"/><author>Lourens Veen</author></item><item><title>how can network analysis lead to a new way of studying court decisions</title><link>https://blog2.esciencecenter.nl/posts/2017-04-03---how-can-network-analysis-lead-to-a-new-way-of-studying-court-decisions</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-04-03---how-can-network-analysis-lead-to-a-new-way-of-studying-court-decisions</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_JEZ2M9ijnm67xFJzxR07dQ-ade48b6c.R0fvX5Oi_ZGFiGb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gijs van Dijck, Professor of Private Law, Maastricht University&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography and text: Elodie Burrillon / HUCOPIX&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Gijs van Dijck is a young professor of Private Law at Maastricht University. For the last six months, he has been working with Dafne van Kuppevelt, eScience Research Engineer at the eScience Center, on the project “Case Law Analytics”. The aim is to develop a technology that assists the legal community in analyzing case law. Here is the story of their collaboration.&lt;/p&gt;
&lt;h2 id=&quot;a-law-specialist-with-an-innovative-mind&quot;&gt;A law specialist with an innovative mind&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_O421VeY14sI-N9KSC8YOcw-a5701c4b.B_K8gxo7_Z2eN68j.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gijs started his PhD in Private Law 14 years ago. He continued working as a researcher because he enjoys the freedom to explore and discover new things that mean something to the field. For all these years, he has been acquiring experience as an empirical legal scholar, and since September 2016 he is working as a professor at Maastricht University.&lt;/p&gt;
&lt;p&gt;Three years ago, Gijs stumbled across an article where network analysis was applied in a legal context. He realized then the enormous potential of this technology for his field: it could lead a new way of studying court decisions by legal academics, lawyers, legal advisers, and law students. But Gijs is a legal scholar, and not a computer scientist.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The legal community is no pioneer in the field of technology and analytics. But this project is something that could transform the field — Gijs&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_p9mNWFc7cJUG1k7HY7DLRQ-ade969a0.DNcBMKAE_Z1u7GPt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When he heard about the eScience Center, it seemed like the perfect way to work on this promising research. With a grant that would bring him both financial support and expertise, he could start developing his idea on a small level, with the help of an eScience Research Engineer who would develop the appropriate technology.&lt;/p&gt;
&lt;p&gt;In May 2016, he applied for an eScience grant. Here is in essence what his project would be about:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Case synthesis is the method commonly applied by legal researchers and law students when analyzing court decisions. The analysis of court decisions commonly relies on human analysis, without software or other technical aid. Consequently, case law is analyzed based on a relatively small number of cases. In contrast, the law produces numerous cases. This project aims to develop a technology that assists the legal community in analyzing case law.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;a-tale-of-two-fields&quot;&gt;A tale of two fields&lt;/h2&gt;
&lt;p&gt;A couple of months after his application, Gijs was pleased to learn that his proposal was accepted: “The granting procedure went all very fast and smooth with the eScience Center. From the beginning, they were very positive and collaborative — and I think this is representative of the mentality of the whole center: they really look for opportunities rather than for limitations.”&lt;/p&gt;
&lt;p&gt;Dafne van Kuppevelt is an eScience Research Engineer, and she started working with Gijs in September 2016. Being a computer science expert, she knew little about law. Gijs is legal scholar, and he knew little about data science. But step by step, they understood the practices, constraints and vocabulary of each other’s field.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_du_XlpPdiICNo3gYdu-MbQ-3b13f6ca.DtjDn9Tu_BjEC4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gijs van Dijck (left) and Dafne van Kuppevelt (right)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I listen to what the needs for the legal research community are, and I try to translate that into the technical possibilities — Dafne&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gijs: “We are collaborating, but from different backgrounds and with different expertises. And that’s what I really like. She’s there to help the field but from her independent, own way. And it’s not like she’s stuck in her own field; she’s also interested in what we are doing and how to answer research questions that are relevant.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WpLnnca8RlE3Q8tuIzsJkQ-7c0d66ec.CxfJRza0_ZMsxuy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“This is a really nice collaboration. I really like this setup of assigning an eScience Research Engineer. And it’s very efficient not only thanks to Dafne, but also thanks to all the team of eScience Research Engineers who can help her at any time, if need be. Another point that I like very much is the sustainability aspect: the eScience Center tries to build tools that others can use, too.”&lt;/p&gt;
&lt;h2 id=&quot;disruptive-results&quot;&gt;Disruptive results&lt;/h2&gt;
&lt;p&gt;Dafne developed a visualization tool that now enables legal researchers to analyze a network of cases linked to each other via their citations.&lt;/p&gt;
&lt;p&gt;The advantages are twofold: the network allows researchers to analyze a huge amount of cases in a very short amount of time, and it also enables them to discover new things that they would have difficulties to otherwise notice.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We are at the beginning of a very big thing. So much that everything we develop becomes relevant - this is very exciting — Gijs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fifteen students of Gijs are currently working on these networks, and with only little experience in the field they can already see things that legal experts would miss. Gijs: “One master student was discussing cases the other day with an expert in the field, and after running a network analysis on the data set for a few minutes, he could point out some cases that the expert had missed. It’s quite amazing to see how, thanks to this tool, a student can, in some ways, outperform the expert.”&lt;/p&gt;
&lt;p&gt;Now that the front-end of the software is up and running, Dafne and Gijs will be working on improving the back-end, by extending the visualisation tool by adding an automated search option.&lt;/p&gt;
&lt;p&gt;But the results are already there, and Gijs’ colleagues are already amazed by the possibilities of this tool.&lt;/p&gt;
&lt;p&gt;If Gijs would work again with the eScience Center?&lt;/p&gt;
&lt;p&gt;“That’s for sure”, he says. “I’m really glad they’re here and I hope it can continue after the end of the project (in September 2017). This is exactly what I needed. And I think this is what research needs.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gBe4KwF7sFmjj_aYk1jg5g-8bc6403d.DofEBKjd_29ToGU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Are you interested in the Netherlands eScience Center’s funding opportunities, have a look at &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;https://www.esciencecenter.nl/funding&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;More about the “Case Law Analytics” project here: &lt;a href=&quot;https://www.esciencecenter.nl/project/case-law-analytics&quot;&gt;https://www.esciencecenter.nl/project/case-law-analytics&lt;/a&gt;&lt;/p&gt;</description><pubDate>Mon, 03 Apr 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_JEZ2M9ijnm67xFJzxR07dQ-ade48b6c.R0fvX5Oi_ZGFiGb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gijs van Dijck, Professor of Private Law, Maastricht University&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography and text: Elodie Burrillon / HUCOPIX&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Gijs van Dijck is a young professor of Private Law at Maastricht University. For the last six months, he has been working with Dafne van Kuppevelt, eScience Research Engineer at the eScience Center, on the project “Case Law Analytics”. The aim is to develop a technology that assists the legal community in analyzing case law. Here is the story of their collaboration.&lt;/p&gt;
&lt;h2 id=&quot;a-law-specialist-with-an-innovative-mind&quot;&gt;A law specialist with an innovative mind&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_O421VeY14sI-N9KSC8YOcw-a5701c4b.B_K8gxo7_Z2eN68j.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gijs started his PhD in Private Law 14 years ago. He continued working as a researcher because he enjoys the freedom to explore and discover new things that mean something to the field. For all these years, he has been acquiring experience as an empirical legal scholar, and since September 2016 he is working as a professor at Maastricht University.&lt;/p&gt;
&lt;p&gt;Three years ago, Gijs stumbled across an article where network analysis was applied in a legal context. He realized then the enormous potential of this technology for his field: it could lead a new way of studying court decisions by legal academics, lawyers, legal advisers, and law students. But Gijs is a legal scholar, and not a computer scientist.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The legal community is no pioneer in the field of technology and analytics. But this project is something that could transform the field — Gijs&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_p9mNWFc7cJUG1k7HY7DLRQ-ade969a0.DNcBMKAE_Z1u7GPt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When he heard about the eScience Center, it seemed like the perfect way to work on this promising research. With a grant that would bring him both financial support and expertise, he could start developing his idea on a small level, with the help of an eScience Research Engineer who would develop the appropriate technology.&lt;/p&gt;
&lt;p&gt;In May 2016, he applied for an eScience grant. Here is in essence what his project would be about:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Case synthesis is the method commonly applied by legal researchers and law students when analyzing court decisions. The analysis of court decisions commonly relies on human analysis, without software or other technical aid. Consequently, case law is analyzed based on a relatively small number of cases. In contrast, the law produces numerous cases. This project aims to develop a technology that assists the legal community in analyzing case law.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;a-tale-of-two-fields&quot;&gt;A tale of two fields&lt;/h2&gt;
&lt;p&gt;A couple of months after his application, Gijs was pleased to learn that his proposal was accepted: “The granting procedure went all very fast and smooth with the eScience Center. From the beginning, they were very positive and collaborative — and I think this is representative of the mentality of the whole center: they really look for opportunities rather than for limitations.”&lt;/p&gt;
&lt;p&gt;Dafne van Kuppevelt is an eScience Research Engineer, and she started working with Gijs in September 2016. Being a computer science expert, she knew little about law. Gijs is legal scholar, and he knew little about data science. But step by step, they understood the practices, constraints and vocabulary of each other’s field.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_du_XlpPdiICNo3gYdu-MbQ-3b13f6ca.DtjDn9Tu_BjEC4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Gijs van Dijck (left) and Dafne van Kuppevelt (right)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I listen to what the needs for the legal research community are, and I try to translate that into the technical possibilities — Dafne&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gijs: “We are collaborating, but from different backgrounds and with different expertises. And that’s what I really like. She’s there to help the field but from her independent, own way. And it’s not like she’s stuck in her own field; she’s also interested in what we are doing and how to answer research questions that are relevant.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_WpLnnca8RlE3Q8tuIzsJkQ-7c0d66ec.CxfJRza0_ZMsxuy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“This is a really nice collaboration. I really like this setup of assigning an eScience Research Engineer. And it’s very efficient not only thanks to Dafne, but also thanks to all the team of eScience Research Engineers who can help her at any time, if need be. Another point that I like very much is the sustainability aspect: the eScience Center tries to build tools that others can use, too.”&lt;/p&gt;
&lt;h2 id=&quot;disruptive-results&quot;&gt;Disruptive results&lt;/h2&gt;
&lt;p&gt;Dafne developed a visualization tool that now enables legal researchers to analyze a network of cases linked to each other via their citations.&lt;/p&gt;
&lt;p&gt;The advantages are twofold: the network allows researchers to analyze a huge amount of cases in a very short amount of time, and it also enables them to discover new things that they would have difficulties to otherwise notice.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We are at the beginning of a very big thing. So much that everything we develop becomes relevant - this is very exciting — Gijs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fifteen students of Gijs are currently working on these networks, and with only little experience in the field they can already see things that legal experts would miss. Gijs: “One master student was discussing cases the other day with an expert in the field, and after running a network analysis on the data set for a few minutes, he could point out some cases that the expert had missed. It’s quite amazing to see how, thanks to this tool, a student can, in some ways, outperform the expert.”&lt;/p&gt;
&lt;p&gt;Now that the front-end of the software is up and running, Dafne and Gijs will be working on improving the back-end, by extending the visualisation tool by adding an automated search option.&lt;/p&gt;
&lt;p&gt;But the results are already there, and Gijs’ colleagues are already amazed by the possibilities of this tool.&lt;/p&gt;
&lt;p&gt;If Gijs would work again with the eScience Center?&lt;/p&gt;
&lt;p&gt;“That’s for sure”, he says. “I’m really glad they’re here and I hope it can continue after the end of the project (in September 2017). This is exactly what I needed. And I think this is what research needs.”&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gBe4KwF7sFmjj_aYk1jg5g-8bc6403d.DofEBKjd_29ToGU.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Are you interested in the Netherlands eScience Center’s funding opportunities, have a look at &lt;a href=&quot;https://www.esciencecenter.nl/funding&quot;&gt;https://www.esciencecenter.nl/funding&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;More about the “Case Law Analytics” project here: &lt;a href=&quot;https://www.esciencecenter.nl/project/case-law-analytics&quot;&gt;https://www.esciencecenter.nl/project/case-law-analytics&lt;/a&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_O421VeY14sI-N9KSC8YOcw-a5701c4b.B_K8gxo7.jpeg" medium="image"/><author>eScience Editorial Team</author></item><item><title>mcfly time series classification made easy</title><link>https://blog2.esciencecenter.nl/posts/2017-03-20---mcfly-time-series-classification-made-easy</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-03-20---mcfly-time-series-classification-made-easy</guid><description>&lt;h2 id=&quot;a-deep-learning-approach-for-time-series&quot;&gt;A deep learning approach for time series&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sT8uHuUVZ-7OnowqXugn0A-1d0ef40a.DqXzp4St_1R50V3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Deep learning is hot. It is the state-of-the-art method for object recognition in &lt;a href=&quot;https://techcrunch.com/2016/10/01/how-deep-learning-allowed-computers-to-see/&quot;&gt;images&lt;/a&gt; and video, and was an important component of the AI system that &lt;a href=&quot;https://research.googleblog.com/2016/01/alphago-mastering-ancient-game-of-go.html&quot;&gt;beat the best human player in GO&lt;/a&gt;. Deep learning can even be used to imitate human creativity by training it to &lt;a href=&quot;http://karpathy.github.io/2015/05/21/rnn-effectiveness/&quot;&gt;write Shakespeare poems&lt;/a&gt; or &lt;a href=&quot;http://bachbot.com/#/?_k=af67i3&quot;&gt;compose Bach chorales&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With all these success stories in the news, you might wonder what deep learning can do for you if you are no expert in machine learning. We have good news: our Python package mcfly might help you explore the power of deep learning, without having to be an expert on the topic!&lt;/p&gt;
&lt;h3 id=&quot;the-power-of-deep-learning&quot;&gt;The power of deep learning&lt;/h3&gt;
&lt;p&gt;Deep learning works well on raw data. Take for example the task of object recognition in an image: in traditional methods, you would first manually define features of the images (edges, corners, etc) and then use for example logistic regression to decide what object is in the image. In deep learning, the input of the model are raw pixels, and the model &lt;em&gt;learns&lt;/em&gt; what features are important. Moreover, it combines low level features (edges, corners) to learn higher level features (squares, circles) and even higher level concepts (faces, text). In this way, it can solve more general problems than a model based on hand-crafted features.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1145&quot; height=&quot;538&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ejsgqmu3zfJCWIDqI39QRA-619f2c59.PPXRepgX_Z24Efwt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In traditional computer vision methods, you have to extract features to feed into the classifier.&lt;/p&gt;
&lt;h3 id=&quot;starting-with-deep-learning&quot;&gt;Starting with deep learning&lt;/h3&gt;
&lt;p&gt;It seems therefore that Deep Learning could be a very low-barrier method to try out on your data: you don’t have to spend time on creating good features from your data. Unfortunately, for beginners it is not always clear how to start with deep learning, and what specific choices for the algorithm they should make for their specific data. Of course it is a good idea to learn the fundamentals of Machine Learning and Neural Networks (for example through the blog of &lt;a href=&quot;https://medium.com/@ageitgey/machine-learning-is-fun-80ea3ec3c471#.bm3dpwuc1&quot;&gt;Adam Geitgey&lt;/a&gt;). However, there are infinitely many different algorithm choices to make for the Deep Learning model. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The number of layers in the network (also called the depth of the network)&lt;/li&gt;
&lt;li&gt;The type of layers (there are many types, like Convolutional, Recurrent and Fully Connected layers)&lt;/li&gt;
&lt;li&gt;The size of each layer (this influences how many parameters the model has)&lt;/li&gt;
&lt;li&gt;The learning rate (how strong does the learning algorithm adjust its parameters when it sees new training data?)&lt;/li&gt;
&lt;li&gt;Regularization options (how do we make sure the model is not overfitted on the training data?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For computer vision (images, video) there are several tools that provide pre-trained models that you can use as a starting point for your own problem. &lt;a href=&quot;http://caffe.berkeleyvision.org/&quot;&gt;Caffe&lt;/a&gt; is an example of such a Deep Learning framework, specifically for computer vision tasks. What about other types of data?&lt;/p&gt;
&lt;h3 id=&quot;time-series-classification&quot;&gt;Time series classification&lt;/h3&gt;
&lt;p&gt;At the Netherlands eScience Center we regularly collaborate with scientists on projects that involve some type of time series data. For example, we want to &lt;a href=&quot;https://www.esciencecenter.nl/project/classifying-activity-types&quot;&gt;classify activity types from accelerometer data&lt;/a&gt;. Or &lt;a href=&quot;https://www.esciencecenter.nl/project/diagnosis-of-active-epilepsy-in-resource-poor-setting&quot;&gt;diagnose epilepsy with consumer-grade EEG devices&lt;/a&gt;. These are examples of time series classification tasks: we have excerpts of (multi-channel) time series data that are associated with a class label, such as the activity type (sleeping, walking, exercising, etc). If we have enough annotated data, we could use a deep learning model to learn how to classify new data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;256&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3DcHZvmP6ioaLNK0Z-_o9g-152ab3f3.DX18xiYN_Z19a3h9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Why did we call our tool mcfly? Because of Back to the Future, a movie with many layers in which Marty Mcfly travels through time!&lt;/p&gt;
&lt;p&gt;To accommodate for time series classification use cases, we developed a software package called &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;mcfly&lt;/a&gt;. It is a wrapper around &lt;a href=&quot;https://keras.io/&quot;&gt;Keras&lt;/a&gt;, a deep learning framework in Python. Although Keras is a very powerful and user-friendly library, it does require you to define exactly the architecture of the model you want to use, and to provide all hyper-parameters. Mcfly makes life easier. It performs a search over suitable architectures and possible hyper-parameters to find the best performing model for you. Since the resulting models are simply Keras models, it is definitely possible to modify these models to explore all functionalities that Keras has to offer.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;939&quot; height=&quot;414&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9E4fZeHXzho-_sktSY0jpA-08cc2e40.yybEsz6c_Z2lleEk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Left the python code to define a model in Keras, right the python code to let mcfly find the model for you.&lt;/p&gt;
&lt;p&gt;For a more in depth introduction to deep learning, follow the online Stanford course on &lt;a href=&quot;http://cs231n.github.io/&quot;&gt;Convolutional Neural Networks for Visual Recognition.&lt;/a&gt; If all the material on deep learning is overwhelming, don’t worry! Maybe &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;mcfly&lt;/a&gt; is just the push you needed to try out Deep Learning for your problem.&lt;/p&gt;
&lt;p&gt;So try mcfly out on your own data! You can download mcfly from our &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;github page&lt;/a&gt;, or through &lt;a href=&quot;https://pypi.python.org/pypi/mcfly/1.0.0&quot;&gt;PyPi&lt;/a&gt;. To get started with mcfly, we developed an &lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial/blob/master/notebooks/tutorial/tutorial.ipynb&quot;&gt;iPython notebook&lt;/a&gt; with a tutorial. Have you used mcfly? We would love to hear about your experiences!&lt;/p&gt;</description><pubDate>Mon, 20 Mar 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;a-deep-learning-approach-for-time-series&quot;&gt;A deep learning approach for time series&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1280&quot; height=&quot;480&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_sT8uHuUVZ-7OnowqXugn0A-1d0ef40a.DqXzp4St_1R50V3.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Deep learning is hot. It is the state-of-the-art method for object recognition in &lt;a href=&quot;https://techcrunch.com/2016/10/01/how-deep-learning-allowed-computers-to-see/&quot;&gt;images&lt;/a&gt; and video, and was an important component of the AI system that &lt;a href=&quot;https://research.googleblog.com/2016/01/alphago-mastering-ancient-game-of-go.html&quot;&gt;beat the best human player in GO&lt;/a&gt;. Deep learning can even be used to imitate human creativity by training it to &lt;a href=&quot;http://karpathy.github.io/2015/05/21/rnn-effectiveness/&quot;&gt;write Shakespeare poems&lt;/a&gt; or &lt;a href=&quot;http://bachbot.com/#/?_k=af67i3&quot;&gt;compose Bach chorales&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With all these success stories in the news, you might wonder what deep learning can do for you if you are no expert in machine learning. We have good news: our Python package mcfly might help you explore the power of deep learning, without having to be an expert on the topic!&lt;/p&gt;
&lt;h3 id=&quot;the-power-of-deep-learning&quot;&gt;The power of deep learning&lt;/h3&gt;
&lt;p&gt;Deep learning works well on raw data. Take for example the task of object recognition in an image: in traditional methods, you would first manually define features of the images (edges, corners, etc) and then use for example logistic regression to decide what object is in the image. In deep learning, the input of the model are raw pixels, and the model &lt;em&gt;learns&lt;/em&gt; what features are important. Moreover, it combines low level features (edges, corners) to learn higher level features (squares, circles) and even higher level concepts (faces, text). In this way, it can solve more general problems than a model based on hand-crafted features.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1145&quot; height=&quot;538&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Ejsgqmu3zfJCWIDqI39QRA-619f2c59.PPXRepgX_Z24Efwt.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In traditional computer vision methods, you have to extract features to feed into the classifier.&lt;/p&gt;
&lt;h3 id=&quot;starting-with-deep-learning&quot;&gt;Starting with deep learning&lt;/h3&gt;
&lt;p&gt;It seems therefore that Deep Learning could be a very low-barrier method to try out on your data: you don’t have to spend time on creating good features from your data. Unfortunately, for beginners it is not always clear how to start with deep learning, and what specific choices for the algorithm they should make for their specific data. Of course it is a good idea to learn the fundamentals of Machine Learning and Neural Networks (for example through the blog of &lt;a href=&quot;https://medium.com/@ageitgey/machine-learning-is-fun-80ea3ec3c471#.bm3dpwuc1&quot;&gt;Adam Geitgey&lt;/a&gt;). However, there are infinitely many different algorithm choices to make for the Deep Learning model. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The number of layers in the network (also called the depth of the network)&lt;/li&gt;
&lt;li&gt;The type of layers (there are many types, like Convolutional, Recurrent and Fully Connected layers)&lt;/li&gt;
&lt;li&gt;The size of each layer (this influences how many parameters the model has)&lt;/li&gt;
&lt;li&gt;The learning rate (how strong does the learning algorithm adjust its parameters when it sees new training data?)&lt;/li&gt;
&lt;li&gt;Regularization options (how do we make sure the model is not overfitted on the training data?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For computer vision (images, video) there are several tools that provide pre-trained models that you can use as a starting point for your own problem. &lt;a href=&quot;http://caffe.berkeleyvision.org/&quot;&gt;Caffe&lt;/a&gt; is an example of such a Deep Learning framework, specifically for computer vision tasks. What about other types of data?&lt;/p&gt;
&lt;h3 id=&quot;time-series-classification&quot;&gt;Time series classification&lt;/h3&gt;
&lt;p&gt;At the Netherlands eScience Center we regularly collaborate with scientists on projects that involve some type of time series data. For example, we want to &lt;a href=&quot;https://www.esciencecenter.nl/project/classifying-activity-types&quot;&gt;classify activity types from accelerometer data&lt;/a&gt;. Or &lt;a href=&quot;https://www.esciencecenter.nl/project/diagnosis-of-active-epilepsy-in-resource-poor-setting&quot;&gt;diagnose epilepsy with consumer-grade EEG devices&lt;/a&gt;. These are examples of time series classification tasks: we have excerpts of (multi-channel) time series data that are associated with a class label, such as the activity type (sleeping, walking, exercising, etc). If we have enough annotated data, we could use a deep learning model to learn how to classify new data.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;256&quot; height=&quot;144&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_3DcHZvmP6ioaLNK0Z-_o9g-152ab3f3.DX18xiYN_Z19a3h9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Why did we call our tool mcfly? Because of Back to the Future, a movie with many layers in which Marty Mcfly travels through time!&lt;/p&gt;
&lt;p&gt;To accommodate for time series classification use cases, we developed a software package called &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;mcfly&lt;/a&gt;. It is a wrapper around &lt;a href=&quot;https://keras.io/&quot;&gt;Keras&lt;/a&gt;, a deep learning framework in Python. Although Keras is a very powerful and user-friendly library, it does require you to define exactly the architecture of the model you want to use, and to provide all hyper-parameters. Mcfly makes life easier. It performs a search over suitable architectures and possible hyper-parameters to find the best performing model for you. Since the resulting models are simply Keras models, it is definitely possible to modify these models to explore all functionalities that Keras has to offer.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;939&quot; height=&quot;414&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_9E4fZeHXzho-_sktSY0jpA-08cc2e40.yybEsz6c_Z2lleEk.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Left the python code to define a model in Keras, right the python code to let mcfly find the model for you.&lt;/p&gt;
&lt;p&gt;For a more in depth introduction to deep learning, follow the online Stanford course on &lt;a href=&quot;http://cs231n.github.io/&quot;&gt;Convolutional Neural Networks for Visual Recognition.&lt;/a&gt; If all the material on deep learning is overwhelming, don’t worry! Maybe &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;mcfly&lt;/a&gt; is just the push you needed to try out Deep Learning for your problem.&lt;/p&gt;
&lt;p&gt;So try mcfly out on your own data! You can download mcfly from our &lt;a href=&quot;https://github.com/NLeSC/mcfly&quot;&gt;github page&lt;/a&gt;, or through &lt;a href=&quot;https://pypi.python.org/pypi/mcfly/1.0.0&quot;&gt;PyPi&lt;/a&gt;. To get started with mcfly, we developed an &lt;a href=&quot;https://github.com/NLeSC/mcfly-tutorial/blob/master/notebooks/tutorial/tutorial.ipynb&quot;&gt;iPython notebook&lt;/a&gt; with a tutorial. Have you used mcfly? We would love to hear about your experiences!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_Ejsgqmu3zfJCWIDqI39QRA-619f2c59.PPXRepgX.png" medium="image"/><author>Dafne van Kuppevelt</author></item><item><title>Reproducible Science The Common Workflow Language</title><link>https://blog2.esciencecenter.nl/posts/2017-03-13---reproducible-science-the-common-workflow-language</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-03-13---reproducible-science-the-common-workflow-language</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2308&quot; height=&quot;1070&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_96JM9gX9m59kS6_fLFcSxg-241fed94.DkOx2r68_cFHQ6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the eWaterCycle forecast workflow, as produced by Cylc&lt;/p&gt;
&lt;p&gt;Why standards are more important than software, and how these will help to make science more reproducible.&lt;/p&gt;
&lt;p&gt;This blog is in part based on a &lt;a href=&quot;https://doi.org/10.6084/m9.figshare.4746931.v1&quot;&gt;paper available as a preprint on figshare&lt;/a&gt;, as inspired by &lt;a href=&quot;http://rolfhut.nl/2016/07/27/why-scientists-should-write-blogs-instead-of-articles/&quot;&gt;this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the Netherlands eScience Center we cooperate with scientists from all disciplines on projects. &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;A lot of projects&lt;/a&gt;. At any given time the 35 or so engineers of the eScience Center are involved in over 50 projects. This large portfolio of projects give us a unique view: we see common problems faced across disciplines.&lt;/p&gt;
&lt;p&gt;One example of such a common problem is to manage workflows. More often than not, scientists will use software to do at least some part of their research. Invariably this involves multiple steps. First do some pre-processing on the data, then run some analysis or simulation, produce a plot, etc. Doing these steps by hand is tedious, error prone, and often hard to reproduce exactly. If you cannot reliably reproduce your result, is it still science?&lt;/p&gt;
&lt;p&gt;Luckily, workflow management systems exist to help out. The problems faced are common across most disciplines: reliably and reproducibly run a number of processes in a row (or perhaps a slightly more complex graph). For some strange reason this does not lead to one or a handful of commonly used workflow systems. Instead, it leads to hundreds! See for example &lt;a href=&quot;https://github.com/common-workflow-language/common-workflow-language/wiki/Existing-Workflow-systems&quot;&gt;this list&lt;/a&gt;. As many projects start from existing software using different workflow systems, choosing one or even a few will be impossible for us, and we may end up using a different workflow system for each project. This will, among others, greatly reduce the re-usability of the software we develop at the eScience Center.&lt;/p&gt;
&lt;h3 id=&quot;so-now-what&quot;&gt;So, now what?&lt;/h3&gt;
&lt;p&gt;Instead of trying to find (or, worse, try to build!) the One True Workflow Management System, instead we plan to use standards for workflows. If we have a good format for describing a workflow that is portable across workflow systems, we should then be able to use whatever workflow system is best for the given problem, without having to re-write all the workflows every time.&lt;/p&gt;
&lt;p&gt;Trying to choose a good workflow description language standard turned out to be much easier than choose between all the workflow systems. As far as we could find, there is only one: &lt;a href=&quot;http://www.commonwl.org/&quot;&gt;The Common Workflow Language&lt;/a&gt; (CWL). CWL is a &lt;a href=&quot;https://en.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; -based workflow specification language. It explicitly supports using containers (&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; for now, &lt;a href=&quot;https://www.opencontainers.org/&quot;&gt;open containers&lt;/a&gt; when available), and should make it easy to migrate workflows between workflow system if needed. To show how a CWL workflow typically looks, here is a simple CWL example, running &lt;code&gt;echo&lt;/code&gt;, with a single string input:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cwlVersion&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CommandLineTool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;baseCommand&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; echo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  message&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    inputBinding&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      position&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;outputs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; []&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More elaborate examples become increasingly complex, but even a &lt;a href=&quot;https://github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl&quot;&gt;complicated workflow&lt;/a&gt; is much easier to read then, say, an xml workflow representation, or some binary format.&lt;/p&gt;
&lt;p&gt;Of course, a format itself does not help if it is then not also supported by workflow management systems. Some, like &lt;a href=&quot;https://arvados.org/&quot;&gt;Arvados&lt;/a&gt;, and &lt;a href=&quot;https://github.com/BD2KGenomics/toil&quot;&gt;Toil&lt;/a&gt; fully support CWL already. Some, like the well known &lt;a href=&quot;https://galaxyproject.org/&quot;&gt;Galaxy&lt;/a&gt; and &lt;a href=&quot;http://taverna.incubator.apache.org/&quot;&gt;Taverna&lt;/a&gt; workflow engines, are currently working on implementing support. We hope and expect more will follow. For example, we are hoping Europe’s multi-billion &lt;a href=&quot;http://ec.europa.eu/research/openscience/index.cfm?pg=open-science-cloud%29&quot;&gt;European Open Science Cloud&lt;/a&gt; will support CWL explicitly. We ourselves plan to add CWL support to &lt;a href=&quot;http://nlesc.github.io/Xenon/&quot;&gt;Xenon&lt;/a&gt;, our middleware abstraction library.&lt;/p&gt;
&lt;h3 id=&quot;escience-center-workflow-roadmap&quot;&gt;eScience Center Workflow Roadmap&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1420&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pM42ttzN8djK227GKWtc4g-1fed2da5.BLN8ffvG_Z22xtV9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Netherlands eScience Center Workflow Roadmap, with a CWL based workflow with support for containers in the middle.&lt;/p&gt;
&lt;p&gt;With CWL as the centerpiece of our workflow world, we can now start to envision a small ecosystem around it. We will need different interfaces to create and run workflows. Some projects are better suited to using a &lt;em&gt;graphical user interface&lt;/em&gt; (GUI) to click together a workflow. Some will need a &lt;em&gt;scripting interface&lt;/em&gt;, a notebook like environment to create workflows using code. Sometimes a scientist does not need to see the workflow at all, and we can hide it completely behind an &lt;em&gt;application frontend&lt;/em&gt;, for example a website that can run some analysis for a scientist, where the analysis itself is then implemented as a CWL workflow.&lt;/p&gt;
&lt;p&gt;After having created or submitted a workflow, we also need some way to actually run this workflow. We should take care to select the best implementation for the target infrastructure. For a laptop you want the simplest possible system and get started quickly. For servers, clusters, supercomputers, and clouds we need increasingly complex implementations, perhaps tailor-made for a single platform.&lt;/p&gt;
&lt;p&gt;To make the impact of our work as large as possible, we will contribute any generic software or tools we build back to the community. We are already using CWL in a few projects, and hope to increase this number greatly in the course of 2017. Stay tuned for updates here, and in the meantime pay a visit to the &lt;a href=&quot;http://www.commonwl.org/&quot;&gt;CWL website&lt;/a&gt;. We would love to hear your experiences with CWL!&lt;/p&gt;</description><pubDate>Mon, 13 Mar 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2308&quot; height=&quot;1070&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_96JM9gX9m59kS6_fLFcSxg-241fed94.DkOx2r68_cFHQ6.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the eWaterCycle forecast workflow, as produced by Cylc&lt;/p&gt;
&lt;p&gt;Why standards are more important than software, and how these will help to make science more reproducible.&lt;/p&gt;
&lt;p&gt;This blog is in part based on a &lt;a href=&quot;https://doi.org/10.6084/m9.figshare.4746931.v1&quot;&gt;paper available as a preprint on figshare&lt;/a&gt;, as inspired by &lt;a href=&quot;http://rolfhut.nl/2016/07/27/why-scientists-should-write-blogs-instead-of-articles/&quot;&gt;this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the Netherlands eScience Center we cooperate with scientists from all disciplines on projects. &lt;a href=&quot;https://www.esciencecenter.nl/projects&quot;&gt;A lot of projects&lt;/a&gt;. At any given time the 35 or so engineers of the eScience Center are involved in over 50 projects. This large portfolio of projects give us a unique view: we see common problems faced across disciplines.&lt;/p&gt;
&lt;p&gt;One example of such a common problem is to manage workflows. More often than not, scientists will use software to do at least some part of their research. Invariably this involves multiple steps. First do some pre-processing on the data, then run some analysis or simulation, produce a plot, etc. Doing these steps by hand is tedious, error prone, and often hard to reproduce exactly. If you cannot reliably reproduce your result, is it still science?&lt;/p&gt;
&lt;p&gt;Luckily, workflow management systems exist to help out. The problems faced are common across most disciplines: reliably and reproducibly run a number of processes in a row (or perhaps a slightly more complex graph). For some strange reason this does not lead to one or a handful of commonly used workflow systems. Instead, it leads to hundreds! See for example &lt;a href=&quot;https://github.com/common-workflow-language/common-workflow-language/wiki/Existing-Workflow-systems&quot;&gt;this list&lt;/a&gt;. As many projects start from existing software using different workflow systems, choosing one or even a few will be impossible for us, and we may end up using a different workflow system for each project. This will, among others, greatly reduce the re-usability of the software we develop at the eScience Center.&lt;/p&gt;
&lt;h3 id=&quot;so-now-what&quot;&gt;So, now what?&lt;/h3&gt;
&lt;p&gt;Instead of trying to find (or, worse, try to build!) the One True Workflow Management System, instead we plan to use standards for workflows. If we have a good format for describing a workflow that is portable across workflow systems, we should then be able to use whatever workflow system is best for the given problem, without having to re-write all the workflows every time.&lt;/p&gt;
&lt;p&gt;Trying to choose a good workflow description language standard turned out to be much easier than choose between all the workflow systems. As far as we could find, there is only one: &lt;a href=&quot;http://www.commonwl.org/&quot;&gt;The Common Workflow Language&lt;/a&gt; (CWL). CWL is a &lt;a href=&quot;https://en.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; -based workflow specification language. It explicitly supports using containers (&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; for now, &lt;a href=&quot;https://www.opencontainers.org/&quot;&gt;open containers&lt;/a&gt; when available), and should make it easy to migrate workflows between workflow system if needed. To show how a CWL workflow typically looks, here is a simple CWL example, running &lt;code&gt;echo&lt;/code&gt;, with a single string input:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cwlVersion&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; v1&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;class:&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; CommandLineTool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;baseCommand&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; echo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;inputs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  message&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    inputBinding&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      position&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;outputs&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; []&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More elaborate examples become increasingly complex, but even a &lt;a href=&quot;https://github.com/common-workflow-language/workflows/blob/master/workflows/lobSTR/lobSTR-workflow.cwl&quot;&gt;complicated workflow&lt;/a&gt; is much easier to read then, say, an xml workflow representation, or some binary format.&lt;/p&gt;
&lt;p&gt;Of course, a format itself does not help if it is then not also supported by workflow management systems. Some, like &lt;a href=&quot;https://arvados.org/&quot;&gt;Arvados&lt;/a&gt;, and &lt;a href=&quot;https://github.com/BD2KGenomics/toil&quot;&gt;Toil&lt;/a&gt; fully support CWL already. Some, like the well known &lt;a href=&quot;https://galaxyproject.org/&quot;&gt;Galaxy&lt;/a&gt; and &lt;a href=&quot;http://taverna.incubator.apache.org/&quot;&gt;Taverna&lt;/a&gt; workflow engines, are currently working on implementing support. We hope and expect more will follow. For example, we are hoping Europe’s multi-billion &lt;a href=&quot;http://ec.europa.eu/research/openscience/index.cfm?pg=open-science-cloud%29&quot;&gt;European Open Science Cloud&lt;/a&gt; will support CWL explicitly. We ourselves plan to add CWL support to &lt;a href=&quot;http://nlesc.github.io/Xenon/&quot;&gt;Xenon&lt;/a&gt;, our middleware abstraction library.&lt;/p&gt;
&lt;h3 id=&quot;escience-center-workflow-roadmap&quot;&gt;eScience Center Workflow Roadmap&lt;/h3&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1420&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pM42ttzN8djK227GKWtc4g-1fed2da5.BLN8ffvG_Z22xtV9.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Netherlands eScience Center Workflow Roadmap, with a CWL based workflow with support for containers in the middle.&lt;/p&gt;
&lt;p&gt;With CWL as the centerpiece of our workflow world, we can now start to envision a small ecosystem around it. We will need different interfaces to create and run workflows. Some projects are better suited to using a &lt;em&gt;graphical user interface&lt;/em&gt; (GUI) to click together a workflow. Some will need a &lt;em&gt;scripting interface&lt;/em&gt;, a notebook like environment to create workflows using code. Sometimes a scientist does not need to see the workflow at all, and we can hide it completely behind an &lt;em&gt;application frontend&lt;/em&gt;, for example a website that can run some analysis for a scientist, where the analysis itself is then implemented as a CWL workflow.&lt;/p&gt;
&lt;p&gt;After having created or submitted a workflow, we also need some way to actually run this workflow. We should take care to select the best implementation for the target infrastructure. For a laptop you want the simplest possible system and get started quickly. For servers, clusters, supercomputers, and clouds we need increasingly complex implementations, perhaps tailor-made for a single platform.&lt;/p&gt;
&lt;p&gt;To make the impact of our work as large as possible, we will contribute any generic software or tools we build back to the community. We are already using CWL in a few projects, and hope to increase this number greatly in the course of 2017. Stay tuned for updates here, and in the meantime pay a visit to the &lt;a href=&quot;http://www.commonwl.org/&quot;&gt;CWL website&lt;/a&gt;. We would love to hear your experiences with CWL!&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_pM42ttzN8djK227GKWtc4g-1fed2da5.BLN8ffvG.png" medium="image"/><author>Niels Drost</author></item><item><title>Five reasons why the eScience Center blog helps science</title><link>https://blog2.esciencecenter.nl/posts/2017-03-02---five-reasons-why-the-escience-center-blog-helps-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-03-02---five-reasons-why-the-escience-center-blog-helps-science</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;875&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FsiN9x7UpByRq7voZnb7eg-c73b4bd5.CKKzlv0u_Z1LKjDQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We think it is important that as many academic researchers as possible benefit from what we do.&lt;/p&gt;
&lt;p&gt;We think it is important that as many academic researchers as possible benefit from &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;what we do&lt;/a&gt;. We put time and effort in spreading the knowledge and digital tools we develop — to digitally enhance research beyond the walls of the eScience Center.&lt;/p&gt;
&lt;p&gt;We use different means to that end: spreading our knowledge and the digital tools we develop by organizing events, writing papers, giving presentations and trainings, publishing our software and methods on our &lt;a href=&quot;http://estep.esciencecenter.nl/&quot;&gt;eScience Technology Platform&lt;/a&gt; and so on.&lt;/p&gt;
&lt;p&gt;Our blog is now the latest addition to that effort.&lt;/p&gt;
&lt;h2 id=&quot;why-a-blog&quot;&gt;Why a blog?&lt;/h2&gt;
&lt;p&gt;I think blog posts have some unique qualities, that can play a significant role in our goal to spread knowledge and the re-use of digital tools.&lt;/p&gt;
&lt;p&gt;I have to say thanks to Rolf Hut and Titus Brown, who both wrote inspiring blogs on the added value of blogs for scientific research:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;*The top 10 reasons why blog posts are better than scientific papers&lt;br&gt;
*by C. Titus Brown:&lt;a href=&quot;http://ivory.idyll.org/blog/2017-top-ten-reasons-blog-posts.html&quot;&gt;http://ivory.idyll.org/blog/2017-top-ten-reasons-blog-posts.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;*Why scientists should write blogs instead of articles&lt;br&gt;
*By Rolf Hut: &lt;a href=&quot;http://rolfhut.nl/2016/07/27/why-scientists-should-write-blogs-instead-of-articles/&quot;&gt;http://rolfhut.nl/2016/07/27/why-scientists-should-write-blogs-instead-of-articles/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have boiled this and my own thoughts down to five reasons why I think blog posts support our goal of spreading knowledge and the re-use of digital tools.&lt;/p&gt;
&lt;h3 id=&quot;reason-1-quick-updates-on-new-developments&quot;&gt;Reason #1: Quick updates on new developments&lt;/h3&gt;
&lt;p&gt;If you ask me, this is the most important reason to write blogs: they are readable, to the point, and timely (you can instantly publish new ideas or progress).&lt;/p&gt;
&lt;p&gt;Every Thursday we have lunch with the whole team and update each other in short (10 minute) talks on our work. That helps us to quickly grasp who is working on what with whom, and what the body of knowledge at the eScience Center is. It is also a quick way to get input from different experts and different perspectives.&lt;/p&gt;
&lt;p&gt;I am convinced that blogs on our work contribute in a similar way to a better understanding with (future) research partners of what our fields of expertise are, and how we work — managing expectations. It shows you how you can re-use knowledge or digital tools that we develop in research projects: What do we know, how do we work, and why do we think that is the way to go.&lt;/p&gt;
&lt;h3 id=&quot;reason-2-rich-content&quot;&gt;Reason #2: Rich content&lt;/h3&gt;
&lt;p&gt;References to &lt;a href=&quot;https://github.com/NLeSC/&quot;&gt;GitHub&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/netherlandsesciencecenter&quot;&gt;videos&lt;/a&gt;, our &lt;a href=&quot;http://estep.esciencecenter.nl/&quot;&gt;eScience Technology Platform&lt;/a&gt;, data sets — you name it. It’s all possible in a blog post. If we introduce a new tool, it’s a great place to quickly share our enthusiasm, a download link to the software, a screencapture, and link to other relevant blogs or websites.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;678&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KB2xSkgK6oQEdvwH3ECrZw-b9529570.BToqm78u_QrjaL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It would be difficult to enrich the above piece of text with a link to GitHub or a nice video, or maybe add some additional content after publication.&lt;/p&gt;
&lt;h3 id=&quot;reason-3-adding-additional-information-over-time&quot;&gt;Reason #3: Adding additional information over time&lt;/h3&gt;
&lt;p&gt;Maybe we write a blog, and one week later make major progress, or gain a new insight. Unlike the presentation you gave last week, the paper you got published or the interview you gave, a blog makes it easier to add and share that new information, or link to additional sources or newer blogs over time.&lt;/p&gt;
&lt;h3 id=&quot;reason-4-giving-and-receiving-feedback&quot;&gt;Reason #4: Giving and receiving feedback&lt;/h3&gt;
&lt;p&gt;Adding information to information in the form of feedback is also an important benefit of blogs, so here comes reason #4. Blogs are not a goal in itself — we want to hear your comments, know whether you learned something, want to add or share something, whether you got inspired.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;637&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_xoxpAr_2BRFETxplmLWutA-c1f98750.DiUQrpRK_Z2faoB5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our mission is to work together with researchers to develop the digital tools best suited to help them answer their research questions. In developing those digital tools it is essential to understand the struggles of researchers, to be able to look from the perspective of researchers. So let us know what you want to hear from us, whether you find our blogs useful.&lt;/p&gt;
&lt;h3 id=&quot;reason-5-accessibility&quot;&gt;Reason #5: Accessibility&lt;/h3&gt;
&lt;p&gt;A blog is easily accessible. First of all because it is free and open source. But also because it can easily be shared on social media or via email. Making it easy to find via Google as well. And a blog on a responsive website is easy to read on any device (unlike a PDF for example). Lastly, unlike symposia and presentations, which are one-time events, blogs stick around.&lt;/p&gt;
&lt;h2 id=&quot;starting-a-pilot&quot;&gt;Starting a pilot&lt;/h2&gt;
&lt;p&gt;So there you go, five reasons we think writing blogs will digitally enhance research. The reasons convinced us to start a pilot to write blog posts on some of our work — to see whether a blog is an effective medium to reach out to you: scientific researchers, research software engineers, science policy advisors, and anyone else working at the interface of science and digital technology. (And if you already have any ideas on relevant topics you want us to write about and/or (increasing) the effectiveness of our blogs, please place comments below!)&lt;/p&gt;
&lt;p&gt;The topics of the blog will vary, and we will try different formats to see what works both for you and for us. But if you feel you belong to one of the above groups, I believe you will benefit from at least some of our blog posts to come: We experience every day that digital technology can be a connecting element for different research disciplines. Just &lt;a href=&quot;http://eepurl.com/Szzyf&quot;&gt;sign up for our newsletter&lt;/a&gt; to stay up to date.&lt;/p&gt;
&lt;h2 id=&quot;who-will-be-writing-these-blogs&quot;&gt;Who will be writing these blogs?&lt;/h2&gt;
&lt;p&gt;Different people at the eScience Center will be writing blogs — we might update you on eScience tools we are developing, share our opinion on eScience matters from time to time, or our partner researcher might write guest posts about their scientific collaborations with us.&lt;/p&gt;
&lt;h2 id=&quot;a-few-last-questions-to-you&quot;&gt;A few last questions to you&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Let us know what you think&lt;/strong&gt; about our blogs — in the comment section or by sending an email to anyone you know at the eScience Center.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Follow us&lt;/strong&gt; on &lt;a href=&quot;https://twitter.com/eScienceCenter&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;http://esciencecenter.us8.list-manage.com/subscribe?u=a0a563ca342f1949246a9f92f&amp;#x26;id=31bfc2303d&quot;&gt;subscribe&lt;/a&gt; to our newsletter to stay up to date on news blog posts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Help us share&lt;/strong&gt; interesting blogs to your peers!&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Thu, 02 Mar 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;875&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_FsiN9x7UpByRq7voZnb7eg-c73b4bd5.CKKzlv0u_Z1LKjDQ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We think it is important that as many academic researchers as possible benefit from what we do.&lt;/p&gt;
&lt;p&gt;We think it is important that as many academic researchers as possible benefit from &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;what we do&lt;/a&gt;. We put time and effort in spreading the knowledge and digital tools we develop — to digitally enhance research beyond the walls of the eScience Center.&lt;/p&gt;
&lt;p&gt;We use different means to that end: spreading our knowledge and the digital tools we develop by organizing events, writing papers, giving presentations and trainings, publishing our software and methods on our &lt;a href=&quot;http://estep.esciencecenter.nl/&quot;&gt;eScience Technology Platform&lt;/a&gt; and so on.&lt;/p&gt;
&lt;p&gt;Our blog is now the latest addition to that effort.&lt;/p&gt;
&lt;h2 id=&quot;why-a-blog&quot;&gt;Why a blog?&lt;/h2&gt;
&lt;p&gt;I think blog posts have some unique qualities, that can play a significant role in our goal to spread knowledge and the re-use of digital tools.&lt;/p&gt;
&lt;p&gt;I have to say thanks to Rolf Hut and Titus Brown, who both wrote inspiring blogs on the added value of blogs for scientific research:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;*The top 10 reasons why blog posts are better than scientific papers&lt;br&gt;
*by C. Titus Brown:&lt;a href=&quot;http://ivory.idyll.org/blog/2017-top-ten-reasons-blog-posts.html&quot;&gt;http://ivory.idyll.org/blog/2017-top-ten-reasons-blog-posts.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;*Why scientists should write blogs instead of articles&lt;br&gt;
*By Rolf Hut: &lt;a href=&quot;http://rolfhut.nl/2016/07/27/why-scientists-should-write-blogs-instead-of-articles/&quot;&gt;http://rolfhut.nl/2016/07/27/why-scientists-should-write-blogs-instead-of-articles/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have boiled this and my own thoughts down to five reasons why I think blog posts support our goal of spreading knowledge and the re-use of digital tools.&lt;/p&gt;
&lt;h3 id=&quot;reason-1-quick-updates-on-new-developments&quot;&gt;Reason #1: Quick updates on new developments&lt;/h3&gt;
&lt;p&gt;If you ask me, this is the most important reason to write blogs: they are readable, to the point, and timely (you can instantly publish new ideas or progress).&lt;/p&gt;
&lt;p&gt;Every Thursday we have lunch with the whole team and update each other in short (10 minute) talks on our work. That helps us to quickly grasp who is working on what with whom, and what the body of knowledge at the eScience Center is. It is also a quick way to get input from different experts and different perspectives.&lt;/p&gt;
&lt;p&gt;I am convinced that blogs on our work contribute in a similar way to a better understanding with (future) research partners of what our fields of expertise are, and how we work — managing expectations. It shows you how you can re-use knowledge or digital tools that we develop in research projects: What do we know, how do we work, and why do we think that is the way to go.&lt;/p&gt;
&lt;h3 id=&quot;reason-2-rich-content&quot;&gt;Reason #2: Rich content&lt;/h3&gt;
&lt;p&gt;References to &lt;a href=&quot;https://github.com/NLeSC/&quot;&gt;GitHub&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/netherlandsesciencecenter&quot;&gt;videos&lt;/a&gt;, our &lt;a href=&quot;http://estep.esciencecenter.nl/&quot;&gt;eScience Technology Platform&lt;/a&gt;, data sets — you name it. It’s all possible in a blog post. If we introduce a new tool, it’s a great place to quickly share our enthusiasm, a download link to the software, a screencapture, and link to other relevant blogs or websites.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;678&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_KB2xSkgK6oQEdvwH3ECrZw-b9529570.BToqm78u_QrjaL.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It would be difficult to enrich the above piece of text with a link to GitHub or a nice video, or maybe add some additional content after publication.&lt;/p&gt;
&lt;h3 id=&quot;reason-3-adding-additional-information-over-time&quot;&gt;Reason #3: Adding additional information over time&lt;/h3&gt;
&lt;p&gt;Maybe we write a blog, and one week later make major progress, or gain a new insight. Unlike the presentation you gave last week, the paper you got published or the interview you gave, a blog makes it easier to add and share that new information, or link to additional sources or newer blogs over time.&lt;/p&gt;
&lt;h3 id=&quot;reason-4-giving-and-receiving-feedback&quot;&gt;Reason #4: Giving and receiving feedback&lt;/h3&gt;
&lt;p&gt;Adding information to information in the form of feedback is also an important benefit of blogs, so here comes reason #4. Blogs are not a goal in itself — we want to hear your comments, know whether you learned something, want to add or share something, whether you got inspired.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;637&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_xoxpAr_2BRFETxplmLWutA-c1f98750.DiUQrpRK_Z2faoB5.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our mission is to work together with researchers to develop the digital tools best suited to help them answer their research questions. In developing those digital tools it is essential to understand the struggles of researchers, to be able to look from the perspective of researchers. So let us know what you want to hear from us, whether you find our blogs useful.&lt;/p&gt;
&lt;h3 id=&quot;reason-5-accessibility&quot;&gt;Reason #5: Accessibility&lt;/h3&gt;
&lt;p&gt;A blog is easily accessible. First of all because it is free and open source. But also because it can easily be shared on social media or via email. Making it easy to find via Google as well. And a blog on a responsive website is easy to read on any device (unlike a PDF for example). Lastly, unlike symposia and presentations, which are one-time events, blogs stick around.&lt;/p&gt;
&lt;h2 id=&quot;starting-a-pilot&quot;&gt;Starting a pilot&lt;/h2&gt;
&lt;p&gt;So there you go, five reasons we think writing blogs will digitally enhance research. The reasons convinced us to start a pilot to write blog posts on some of our work — to see whether a blog is an effective medium to reach out to you: scientific researchers, research software engineers, science policy advisors, and anyone else working at the interface of science and digital technology. (And if you already have any ideas on relevant topics you want us to write about and/or (increasing) the effectiveness of our blogs, please place comments below!)&lt;/p&gt;
&lt;p&gt;The topics of the blog will vary, and we will try different formats to see what works both for you and for us. But if you feel you belong to one of the above groups, I believe you will benefit from at least some of our blog posts to come: We experience every day that digital technology can be a connecting element for different research disciplines. Just &lt;a href=&quot;http://eepurl.com/Szzyf&quot;&gt;sign up for our newsletter&lt;/a&gt; to stay up to date.&lt;/p&gt;
&lt;h2 id=&quot;who-will-be-writing-these-blogs&quot;&gt;Who will be writing these blogs?&lt;/h2&gt;
&lt;p&gt;Different people at the eScience Center will be writing blogs — we might update you on eScience tools we are developing, share our opinion on eScience matters from time to time, or our partner researcher might write guest posts about their scientific collaborations with us.&lt;/p&gt;
&lt;h2 id=&quot;a-few-last-questions-to-you&quot;&gt;A few last questions to you&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Let us know what you think&lt;/strong&gt; about our blogs — in the comment section or by sending an email to anyone you know at the eScience Center.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Follow us&lt;/strong&gt; on &lt;a href=&quot;https://twitter.com/eScienceCenter&quot;&gt;Twitter&lt;/a&gt; or &lt;a href=&quot;http://esciencecenter.us8.list-manage.com/subscribe?u=a0a563ca342f1949246a9f92f&amp;#x26;id=31bfc2303d&quot;&gt;subscribe&lt;/a&gt; to our newsletter to stay up to date on news blog posts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Help us share&lt;/strong&gt; interesting blogs to your peers!&lt;/li&gt;
&lt;/ul&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_KB2xSkgK6oQEdvwH3ECrZw-b9529570.BToqm78u.jpeg" medium="image"/><author>Lode Kulik</author></item><item><title>So I wanted to be a Research Software Engineer</title><link>https://blog2.esciencecenter.nl/posts/2017-02-28---so-i-wanted-to-be-a-research-software-engineer</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-28---so-i-wanted-to-be-a-research-software-engineer</guid><description>&lt;p&gt;Rewind to 2008. I loved science. I loved technology. I wanted to combine the two worlds. However, looking back, I must admit: It ain’t easy being a developer of scientific software (a.k.a. &lt;a href=&quot;https://www.software.ac.uk/blog/2016-11-17-not-so-brief-history-research-software-engineers&quot;&gt;research software engineer&lt;/a&gt;) and a scientist at the same time. In this blogpost, I am sharing the biggest challenges I encountered — and some of the solutions I found.&lt;/p&gt;
&lt;p&gt;Before I begin, some background about myself. I worked 8+ years as developer of software in the scientific disciplines of physical activity and sleep. A field that has made a radical shift to rely on wearable acceleration sensor data instead of traditional survey data. Some of my work includes: &lt;a href=&quot;http://jap.physiology.org/content/117/7/738.long&quot;&gt;automated signal calibration&lt;/a&gt;, &lt;a href=&quot;http://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0061691&quot;&gt;removing the gravitational component from acceleration signals&lt;/a&gt;, &lt;a href=&quot;http://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0022922&quot;&gt;estimating human energy expenditure&lt;/a&gt;, and &lt;a href=&quot;http://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0142533&quot;&gt;estimating human sleep&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;545&quot; height=&quot;362&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vjpqYnxIjZTm9CFdKmoajA-027fa581.BawMHgZ0_2dOQWM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The wrist worn accelerometer with which most of the data I worked with was collected. The accelerometer was selected because it comes with open source software (copyright: &lt;a href=&quot;https://www.geneactiv.org&quot;&gt;https://www.geneactiv.org&lt;/a&gt; GENEActiv TM)&lt;/p&gt;
&lt;h2 id=&quot;8-challenges-of-being-a-software-engineer-in-academia&quot;&gt;8 challenges of being a software engineer in academia&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Multi-tasking.&lt;/strong&gt; Over the years I had to multi-task between: (1) organising methodological studies, (2) collecting data on human participants, (3) cleaning, archiving and analysing the data, (4) developing and maintaining generic software, (5) writing scientific papers, (6) staying up to date with the field literature, (7) staying up to date with technology, (8) helping out with the analyses of other people’s data, and (9) exploring funding opportunities. It often felt as an impossible job to excel in everything.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scientific recognition.&lt;/strong&gt; Scientific journals that publish research based on research software do not always welcome the supporting methodological work for publication. Further, innovative scientific methods are not necessarily innovative technology. Therefore, there is often no obvious scientific journal to publish a new scientific method in: The science journal from the research community for which the methods are made often reject methodological papers as they are considered too technical, and technology journals, justifiably, do not see the technological novelty. Luckily, theme-free journals like the online open access journal &lt;a href=&quot;http://journals.plos.org/plosone/&quot;&gt;PLoSONE&lt;/a&gt; have come to existence to address this issue. Theme-free journals have the advantage that editors will not judge a manuscript based on its topic of research but based on the quality of the research regardless of whether it is technical, fundamental, or applied.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technology feedback.&lt;/strong&gt; Working among the scientists has been great for understanding their needs, and getting feedback on software functionality. However, working among the scientists requires an extra effort to find people willing and able to brainstorm about the technological aspects of the software. I did manage to find a small group of computer scientists for feedback, but truly collaborating on papers remained difficult as a result of major differences in interests and publication culture between academic fields.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Helpdesk.&lt;/strong&gt; When developing open source software you may not necessarily have the resources to set up an end-user helpdesk. Consequently, software users will contact the developer with all their queries, sometimes four or five times per week. There does not seem to be a simple solution to this challenge. Ignoring the queries would mean the possible end of the software and the end of its impact on science, answering all queries would require a lot of time, and building a community that answers each others’ questions only makes sense if there is more than one person in the community who fully understands the software and has a personal interest to dedicate time in helping scientists. Of course, there is always the option of offering support as a paid consultancy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency on commercial technology.&lt;/strong&gt; The majority of scientific technologies in my field are produced by commercial parties who are not always able to guarantee long term product support. For example, the sensor company &lt;a href=&quot;https://en.wikipedia.org/wiki/BodyMedia&quot;&gt;BodyMedia&lt;/a&gt; was sold to the company JawBone, which in turn stopped producing the sensors by which none of the scientific studies done with the these sensors in the past two decades can now be reproduced. Further, the existence of proprietary commercial software in this field has undermined scientific transparency also. As a consequence, a substantial part of the scientific work in the physical activity and sleep research community has been to empirically compare the data coming out of proprietary software. These comparisons are needed to verify compatibility of research results, needed to preserve methodological consistency. This situation may have made some scientists feel vulnerable and left in the dark.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technology myths.&lt;/strong&gt; In recent decades, hundreds of conference proceedings have been published by the technology research community with strong claims about the potential of machine learning for accelerometer data classification. Although, the enthusiasm of those publications is understandable form a computer science perspective, they did not live up to the requirements of the physical activity and sleep researchers: A large number of those optimistic statements were not accompanied by reproducible research, were limited to unrepresentative study populations, had a too low sample size, or had an unrealistically easy classification task. Not surprisingly technological research is not always taken serious by the scientists. A conclusion from this may be that a too positive pitch of your new scientific technology can decrease the trust of scientists in your work, especially if reality does not live up to the pitch. Therefore, a close collaboration between scientific technology developers and end-users seems essential.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Career path.&lt;/strong&gt; As a developer of scientific methods you tend to be sucked into a facilitating role because the goal of the work is to enhance the work of scientists. Their cooperation and approval of a method is needed for the success of the method. This makes it difficult to prove yourself as an independent scientist, because the more you focus on your own academic output the less time you have to listen to and help the scientist, which in turn is essential for your own output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Computing resources.&lt;/strong&gt; During my PhD research I had unlimited access to a computing cluster. It felt to me as having access was normal, while during my time as a post-doc at a different university I had to organise this myself. Senior scientists are not always aware of the need for computing infrastructure at the start of a project and it is important to know your infrastructure requirements and communicate them on time.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;354&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gacey_PXHSpAqnEH9H4CAQ-90b2a278.C733p5ib_Z28IMzO.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;BodyMedia’s proprietary software made scientists dependent on their services for reproducible research&lt;/p&gt;
&lt;h2 id=&quot;solutions&quot;&gt;Solutions?&lt;/h2&gt;
&lt;p&gt;In 2015 I joined the &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; as an &lt;a href=&quot;https://www.esciencecenter.nl/careers/escience-research-engineer&quot;&gt;eScience Research Engineer&lt;/a&gt;, which has addressed a number of the challenges mentioned in this blogpost for me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am exposed to a wide range of technologies and scientific challenges to learn from and be inspired by.&lt;/li&gt;
&lt;li&gt;Scientific software is recognized as scientifc output.&lt;/li&gt;
&lt;li&gt;The collaboration between research software engineers and scientists is at the core of each project.&lt;/li&gt;
&lt;li&gt;The work has made me aware that there are many scientific software developers facing the exact same challenges as I did. For example, organised in national organisations like the &lt;a href=&quot;https://www.dtls.nl/&quot;&gt;Dutch Techcentre for the Life Sciences&lt;/a&gt; and the international &lt;a href=&quot;https://www.software.ac.uk/research-software-engineers&quot;&gt;Research Software Engineer&lt;/a&gt; community.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;427&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CIx_bdUv8DDerZ7FKMLeFg-c21be9b9.C8xRPPQJ_Z2vtbNd.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Discussions between research software engineers (me in brown sweater on the right) and scientists about opportunities and challenges in improving data analytics in science ( ©Copyright: Hucopix, &lt;a href=&quot;http://hucopix.com&quot;&gt;http://hucopix.com&lt;/a&gt;, 2017)&lt;/p&gt;
&lt;p&gt;So, what did I want to say? It has taken almost a decade, but I think I found the perfect platform to make a broad and sustainable scientific impact using technology!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I am interested to hear about &lt;em&gt;your&lt;/em&gt; experiences. Don’t hesitate to leave a comment!&lt;/strong&gt;&lt;/p&gt;</description><pubDate>Tue, 28 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Rewind to 2008. I loved science. I loved technology. I wanted to combine the two worlds. However, looking back, I must admit: It ain’t easy being a developer of scientific software (a.k.a. &lt;a href=&quot;https://www.software.ac.uk/blog/2016-11-17-not-so-brief-history-research-software-engineers&quot;&gt;research software engineer&lt;/a&gt;) and a scientist at the same time. In this blogpost, I am sharing the biggest challenges I encountered — and some of the solutions I found.&lt;/p&gt;
&lt;p&gt;Before I begin, some background about myself. I worked 8+ years as developer of software in the scientific disciplines of physical activity and sleep. A field that has made a radical shift to rely on wearable acceleration sensor data instead of traditional survey data. Some of my work includes: &lt;a href=&quot;http://jap.physiology.org/content/117/7/738.long&quot;&gt;automated signal calibration&lt;/a&gt;, &lt;a href=&quot;http://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0061691&quot;&gt;removing the gravitational component from acceleration signals&lt;/a&gt;, &lt;a href=&quot;http://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0022922&quot;&gt;estimating human energy expenditure&lt;/a&gt;, and &lt;a href=&quot;http://journals.plos.org/plosone/article?id=10.1371%2Fjournal.pone.0142533&quot;&gt;estimating human sleep&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;545&quot; height=&quot;362&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vjpqYnxIjZTm9CFdKmoajA-027fa581.BawMHgZ0_2dOQWM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The wrist worn accelerometer with which most of the data I worked with was collected. The accelerometer was selected because it comes with open source software (copyright: &lt;a href=&quot;https://www.geneactiv.org&quot;&gt;https://www.geneactiv.org&lt;/a&gt; GENEActiv TM)&lt;/p&gt;
&lt;h2 id=&quot;8-challenges-of-being-a-software-engineer-in-academia&quot;&gt;8 challenges of being a software engineer in academia&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Multi-tasking.&lt;/strong&gt; Over the years I had to multi-task between: (1) organising methodological studies, (2) collecting data on human participants, (3) cleaning, archiving and analysing the data, (4) developing and maintaining generic software, (5) writing scientific papers, (6) staying up to date with the field literature, (7) staying up to date with technology, (8) helping out with the analyses of other people’s data, and (9) exploring funding opportunities. It often felt as an impossible job to excel in everything.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scientific recognition.&lt;/strong&gt; Scientific journals that publish research based on research software do not always welcome the supporting methodological work for publication. Further, innovative scientific methods are not necessarily innovative technology. Therefore, there is often no obvious scientific journal to publish a new scientific method in: The science journal from the research community for which the methods are made often reject methodological papers as they are considered too technical, and technology journals, justifiably, do not see the technological novelty. Luckily, theme-free journals like the online open access journal &lt;a href=&quot;http://journals.plos.org/plosone/&quot;&gt;PLoSONE&lt;/a&gt; have come to existence to address this issue. Theme-free journals have the advantage that editors will not judge a manuscript based on its topic of research but based on the quality of the research regardless of whether it is technical, fundamental, or applied.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technology feedback.&lt;/strong&gt; Working among the scientists has been great for understanding their needs, and getting feedback on software functionality. However, working among the scientists requires an extra effort to find people willing and able to brainstorm about the technological aspects of the software. I did manage to find a small group of computer scientists for feedback, but truly collaborating on papers remained difficult as a result of major differences in interests and publication culture between academic fields.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Helpdesk.&lt;/strong&gt; When developing open source software you may not necessarily have the resources to set up an end-user helpdesk. Consequently, software users will contact the developer with all their queries, sometimes four or five times per week. There does not seem to be a simple solution to this challenge. Ignoring the queries would mean the possible end of the software and the end of its impact on science, answering all queries would require a lot of time, and building a community that answers each others’ questions only makes sense if there is more than one person in the community who fully understands the software and has a personal interest to dedicate time in helping scientists. Of course, there is always the option of offering support as a paid consultancy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency on commercial technology.&lt;/strong&gt; The majority of scientific technologies in my field are produced by commercial parties who are not always able to guarantee long term product support. For example, the sensor company &lt;a href=&quot;https://en.wikipedia.org/wiki/BodyMedia&quot;&gt;BodyMedia&lt;/a&gt; was sold to the company JawBone, which in turn stopped producing the sensors by which none of the scientific studies done with the these sensors in the past two decades can now be reproduced. Further, the existence of proprietary commercial software in this field has undermined scientific transparency also. As a consequence, a substantial part of the scientific work in the physical activity and sleep research community has been to empirically compare the data coming out of proprietary software. These comparisons are needed to verify compatibility of research results, needed to preserve methodological consistency. This situation may have made some scientists feel vulnerable and left in the dark.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technology myths.&lt;/strong&gt; In recent decades, hundreds of conference proceedings have been published by the technology research community with strong claims about the potential of machine learning for accelerometer data classification. Although, the enthusiasm of those publications is understandable form a computer science perspective, they did not live up to the requirements of the physical activity and sleep researchers: A large number of those optimistic statements were not accompanied by reproducible research, were limited to unrepresentative study populations, had a too low sample size, or had an unrealistically easy classification task. Not surprisingly technological research is not always taken serious by the scientists. A conclusion from this may be that a too positive pitch of your new scientific technology can decrease the trust of scientists in your work, especially if reality does not live up to the pitch. Therefore, a close collaboration between scientific technology developers and end-users seems essential.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Career path.&lt;/strong&gt; As a developer of scientific methods you tend to be sucked into a facilitating role because the goal of the work is to enhance the work of scientists. Their cooperation and approval of a method is needed for the success of the method. This makes it difficult to prove yourself as an independent scientist, because the more you focus on your own academic output the less time you have to listen to and help the scientist, which in turn is essential for your own output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Computing resources.&lt;/strong&gt; During my PhD research I had unlimited access to a computing cluster. It felt to me as having access was normal, while during my time as a post-doc at a different university I had to organise this myself. Senior scientists are not always aware of the need for computing infrastructure at the start of a project and it is important to know your infrastructure requirements and communicate them on time.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;354&quot; height=&quot;500&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_gacey_PXHSpAqnEH9H4CAQ-90b2a278.C733p5ib_Z28IMzO.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;BodyMedia’s proprietary software made scientists dependent on their services for reproducible research&lt;/p&gt;
&lt;h2 id=&quot;solutions&quot;&gt;Solutions?&lt;/h2&gt;
&lt;p&gt;In 2015 I joined the &lt;a href=&quot;http://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; as an &lt;a href=&quot;https://www.esciencecenter.nl/careers/escience-research-engineer&quot;&gt;eScience Research Engineer&lt;/a&gt;, which has addressed a number of the challenges mentioned in this blogpost for me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am exposed to a wide range of technologies and scientific challenges to learn from and be inspired by.&lt;/li&gt;
&lt;li&gt;Scientific software is recognized as scientifc output.&lt;/li&gt;
&lt;li&gt;The collaboration between research software engineers and scientists is at the core of each project.&lt;/li&gt;
&lt;li&gt;The work has made me aware that there are many scientific software developers facing the exact same challenges as I did. For example, organised in national organisations like the &lt;a href=&quot;https://www.dtls.nl/&quot;&gt;Dutch Techcentre for the Life Sciences&lt;/a&gt; and the international &lt;a href=&quot;https://www.software.ac.uk/research-software-engineers&quot;&gt;Research Software Engineer&lt;/a&gt; community.
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;640&quot; height=&quot;427&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_CIx_bdUv8DDerZ7FKMLeFg-c21be9b9.C8xRPPQJ_Z2vtbNd.webp&quot; srcset=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Discussions between research software engineers (me in brown sweater on the right) and scientists about opportunities and challenges in improving data analytics in science ( ©Copyright: Hucopix, &lt;a href=&quot;http://hucopix.com&quot;&gt;http://hucopix.com&lt;/a&gt;, 2017)&lt;/p&gt;
&lt;p&gt;So, what did I want to say? It has taken almost a decade, but I think I found the perfect platform to make a broad and sustainable scientific impact using technology!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I am interested to hear about &lt;em&gt;your&lt;/em&gt; experiences. Don’t hesitate to leave a comment!&lt;/strong&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_vjpqYnxIjZTm9CFdKmoajA-027fa581.BawMHgZ0.jpeg" medium="image"/><author>Vincent van Hees</author></item><item><title>Reaching for the sky Wishes for the European Open Science Cloud</title><link>https://blog2.esciencecenter.nl/posts/2017-02-21---reaching-for-the-sky-wishes-for-the-european-open-science-cl</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-21---reaching-for-the-sky-wishes-for-the-european-open-science-cl</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;880&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1SX9Hrianxyy7q60kuWd5A-1530a87a.Bfd4lYp1_1uggPg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;‘The cloud’ is one of the hottest tech topics of our time. It’s therefore no surprise that European Commission has also jumped on the bandwagon. Big time! Last year, the European Commission launched the outline of a multi-year and multi-billion Euro plan for the development and implementation of a &lt;a href=&quot;http://europa.eu/rapid/press-release_IP-16-1408_en.htm&quot;&gt;European Open Science Cloud&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;an-all-encompassing-infrastructure&quot;&gt;An all-encompassing infrastructure&lt;/h3&gt;
&lt;p&gt;This ‘science cloud’ serves as a metaphor for an all-encompassing infrastructure, geared towards the scientific community. While the front-end or interface towards users should be user-friendly and service-oriented, the much more complex back-end should largely be hidden for end-users. Perhaps somewhat optimistically, the European Commission &lt;a href=&quot;http://europa.eu/rapid/press-release_IP-16-1408_en.htm&quot;&gt;describes&lt;/a&gt; this future Open Science Cloud as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“A virtual environment to store, share and re-use their [the scientists’] data across disciplines and borders. This will be underpinned by the European Data Infrastructure, deploying the high-bandwidth networks, large scale storage facilities and super-computer capacity necessary to effectively access and process large datasets stored in the cloud.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;making-it-work&quot;&gt;Making it work&lt;/h3&gt;
&lt;p&gt;However, the European Commission will only serve as ‘the glue’ for the European Open Science Cloud. Like many European projects, the actual design and implementation relies on the initiative and inputs from collaborative member states. Given the opportunities of a science cloud for the Dutch academic community, leading scientists, science policy makers and digital infrastructure partners came together in December 2016 for a workshop organized by &lt;a href=&quot;https://escience-platform.nl/&quot;&gt;ePLAN&lt;/a&gt; (the national Platform of eScience/Data Research Centers in The Netherlands). The goal? To discuss ideals, opinions and ambitions for making a European science cloud actually &lt;em&gt;work&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;questions-from-scientists&quot;&gt;Questions from scientists&lt;/h3&gt;
&lt;p&gt;The workshop resulted in a wide variety of suggestions, ranging from ethical and cultural issues to more technological topics. Although opinions varied, certainly not all scientists were fully convinced (yet?) of the actual benefits of an Open Science Cloud. Paraphrasing some of the questions from scientists (&lt;a href=&quot;https://twitter.com/search?f=images&amp;#x26;vertical=default&amp;#x26;q=%23ActualLivingScientist&amp;#x26;src=typd&quot;&gt;#actuallivingscientist&lt;/a&gt;) to the policy makers of the European Open Science Cloud:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do I get my work done &lt;em&gt;quicker&lt;/em&gt; using this European Cloud? It seems like a lot of extra work, on top of all the extra work I am already supposed to do.&lt;/li&gt;
&lt;li&gt;Will it really be &lt;em&gt;easier&lt;/em&gt; than current research practices? Will it work like a one-stop-shop with single sign-on instead of using a multitude of independent software, hardware and data solutions?&lt;/li&gt;
&lt;li&gt;Will it help me generate significantly &lt;em&gt;more and better&lt;/em&gt; scientific ouput, benefiting from cutting edge technology?&lt;/li&gt;
&lt;li&gt;Do I get &lt;em&gt;scientific recognition&lt;/em&gt; for uploading, describing and publishing my analyses, software code and research data for the rest of the world?&lt;/li&gt;
&lt;li&gt;Will my data be really &lt;em&gt;safer&lt;/em&gt; in the European Cloud than on my laptop or personal Dropbox folder?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More details? Read the full workshop report &lt;a href=&quot;https://escienceplatform.files.wordpress.com/2017/02/eplan_european_open_science_cloud_january2017.pdf&quot;&gt;here&lt;/a&gt; (Dutch only, sorry!).&lt;/p&gt;</description><pubDate>Tue, 21 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;880&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_1SX9Hrianxyy7q60kuWd5A-1530a87a.Bfd4lYp1_1uggPg.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;‘The cloud’ is one of the hottest tech topics of our time. It’s therefore no surprise that European Commission has also jumped on the bandwagon. Big time! Last year, the European Commission launched the outline of a multi-year and multi-billion Euro plan for the development and implementation of a &lt;a href=&quot;http://europa.eu/rapid/press-release_IP-16-1408_en.htm&quot;&gt;European Open Science Cloud&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;an-all-encompassing-infrastructure&quot;&gt;An all-encompassing infrastructure&lt;/h3&gt;
&lt;p&gt;This ‘science cloud’ serves as a metaphor for an all-encompassing infrastructure, geared towards the scientific community. While the front-end or interface towards users should be user-friendly and service-oriented, the much more complex back-end should largely be hidden for end-users. Perhaps somewhat optimistically, the European Commission &lt;a href=&quot;http://europa.eu/rapid/press-release_IP-16-1408_en.htm&quot;&gt;describes&lt;/a&gt; this future Open Science Cloud as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“A virtual environment to store, share and re-use their [the scientists’] data across disciplines and borders. This will be underpinned by the European Data Infrastructure, deploying the high-bandwidth networks, large scale storage facilities and super-computer capacity necessary to effectively access and process large datasets stored in the cloud.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;making-it-work&quot;&gt;Making it work&lt;/h3&gt;
&lt;p&gt;However, the European Commission will only serve as ‘the glue’ for the European Open Science Cloud. Like many European projects, the actual design and implementation relies on the initiative and inputs from collaborative member states. Given the opportunities of a science cloud for the Dutch academic community, leading scientists, science policy makers and digital infrastructure partners came together in December 2016 for a workshop organized by &lt;a href=&quot;https://escience-platform.nl/&quot;&gt;ePLAN&lt;/a&gt; (the national Platform of eScience/Data Research Centers in The Netherlands). The goal? To discuss ideals, opinions and ambitions for making a European science cloud actually &lt;em&gt;work&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&quot;questions-from-scientists&quot;&gt;Questions from scientists&lt;/h3&gt;
&lt;p&gt;The workshop resulted in a wide variety of suggestions, ranging from ethical and cultural issues to more technological topics. Although opinions varied, certainly not all scientists were fully convinced (yet?) of the actual benefits of an Open Science Cloud. Paraphrasing some of the questions from scientists (&lt;a href=&quot;https://twitter.com/search?f=images&amp;#x26;vertical=default&amp;#x26;q=%23ActualLivingScientist&amp;#x26;src=typd&quot;&gt;#actuallivingscientist&lt;/a&gt;) to the policy makers of the European Open Science Cloud:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do I get my work done &lt;em&gt;quicker&lt;/em&gt; using this European Cloud? It seems like a lot of extra work, on top of all the extra work I am already supposed to do.&lt;/li&gt;
&lt;li&gt;Will it really be &lt;em&gt;easier&lt;/em&gt; than current research practices? Will it work like a one-stop-shop with single sign-on instead of using a multitude of independent software, hardware and data solutions?&lt;/li&gt;
&lt;li&gt;Will it help me generate significantly &lt;em&gt;more and better&lt;/em&gt; scientific ouput, benefiting from cutting edge technology?&lt;/li&gt;
&lt;li&gt;Do I get &lt;em&gt;scientific recognition&lt;/em&gt; for uploading, describing and publishing my analyses, software code and research data for the rest of the world?&lt;/li&gt;
&lt;li&gt;Will my data be really &lt;em&gt;safer&lt;/em&gt; in the European Cloud than on my laptop or personal Dropbox folder?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;More details? Read the full workshop report &lt;a href=&quot;https://escienceplatform.files.wordpress.com/2017/02/eplan_european_open_science_cloud_january2017.pdf&quot;&gt;here&lt;/a&gt; (Dutch only, sorry!).&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_1SX9Hrianxyy7q60kuWd5A-1530a87a.Bfd4lYp1.jpeg" medium="image"/><author>Patrick Aerts</author></item><item><title>First Light! … again! Shiny new receivers for the Westerbork telescope.</title><link>https://blog2.esciencecenter.nl/posts/2017-02-09---first-light-again-shiny-new-receivers-for-the-westerbork</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-09---first-light-again-shiny-new-receivers-for-the-westerbork</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4288&quot; height=&quot;2848&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IW6Wn8RsaEyQRhYbFMMDkA-8d49b3c8.C5gQuTed_1vsSUG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Radio Telescopes at Westerbork by Johan Wieland&lt;/p&gt;
&lt;p&gt;Great news! The new and improved Westerbork telescope in the northeast of the Netherlands &lt;a href=&quot;http://www.astron.nl/first-image-apertif-new-life-westerbork-radio-telescope&quot;&gt;has seen first light&lt;/a&gt;! If you are into radio astronomy, or if you have visited the second world war nazi camp and monument at Westerbork, you may be familiar with this instrument, which was built in 1970. The telescope is situated right next to the former transit camp. During the Second World War, Romani and Dutch Jews were assembled there, for transport to other Nazi concentration camps. The famous Anne Frank (from the diary) was kept here for a while.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZOtMneXEYlp6asnBzuEojw-af2965fd.BqK_Wjy2_lMWTj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A rebuilt barrack at Dutch Nazi camp Westerbork. Anne Frank stayed in this barrack from August till early September 1944, before she was taken to Auschwitz and then Bergen-Belsen. Picture from Wikipedia, courtesy Blacknight&lt;/p&gt;
&lt;p&gt;Today, you can visit the remains of the camp, which now is a monument. From the site, you can see the telescope, or actually telescopes, because the instrument consists of 14 separate dishes, 25 meters in diameter each. The total distance between the dishes is 2.7 kilometers, or 1.7 miles if you insist on using archaic units. The telescope actually is pretty old already. In fact, it is older than I am (I was built in ‘75). Nevertheless, this instrument has helped doing great science, and has led to many remarkable discoveries.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Mix7BRS8y2WHMX1eQfWiRw-88ec3984.D9j5M3nI_ZJpvxM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Westerbork synthesis radio telescope. And typical Dutch weather:-) Picture made by me on a day the telescope was open for the public. Normally, cars are not allowed here, because they cause interference.&lt;/p&gt;
&lt;p&gt;Of course, technology does not stand still, and modern, more sensitive instruments were developed and built during the four decades (!) that this telescope has been operational. So, the beast was becoming a bit old and grumpy. Not to worry! We are Dutch, and don’t like to waste anything (some say we are cheapskates). So, recently, the receivers that are in the focal points of the dishes were upgraded with brand new ones. Originally, each dish contained only a single sensor, basically producing a single pixel. The new receiver, called APERTIF, actually is an array of sensors, called a Focal Plane Array (FPA). Compare it to a modern sensor in a camera, which produces several megapixels at once. So, this gives us more sensitivity, but especially a much larger window on the sky. We can see more at the same time. This is important if you want to make a survey, searching for objects that you don’t know yet, or which appear suddenly (like supernovae, pulsars, or signals from little green men).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1252&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pIoP_Vd-PXzaiskRPe9XeA-f89960ed.L51EjoUK_13zQ9o.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Focal Plane arrays rock! Picture courtesy ASTRON.&lt;/p&gt;
&lt;p&gt;So, why am I blogging about this? Well because it is cool, duh! And, because we at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; develop &lt;a href=&quot;https://www.esciencecenter.nl/project/aa-alert&quot;&gt;software to process the data&lt;/a&gt; generated by this instrument. To be more precise, we are working on &lt;a href=&quot;https://www.astron.nl/r-d-laboratory/arts/arts-apertif-radio-transient-system-apertif&quot;&gt;ARTS&lt;/a&gt;, the APERTIF radio transient system. We will, for instance, observe &lt;a href=&quot;https://en.wikipedia.org/wiki/Pulsar&quot;&gt;pulsars&lt;/a&gt;: neutron stars that are spinning quickly, emitting a beam like a light house. For some pulsars, the time between pulses is so constant that they are even more precise than an atomic clock! Pulsars are important for many reasons. One of them is that we hope to use them to detect gravitational waves, learning more about how the universe works.&lt;/p&gt;
&lt;p&gt;It is a privilege for us to write software that will help make these scientific discoveries happen! At the same time, it is a strange but beautiful thing that a site where so many bad things happened to so many people in the past now is one of the pinnacles of science.&lt;/p&gt;</description><pubDate>Thu, 09 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4288&quot; height=&quot;2848&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IW6Wn8RsaEyQRhYbFMMDkA-8d49b3c8.C5gQuTed_1vsSUG.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Radio Telescopes at Westerbork by Johan Wieland&lt;/p&gt;
&lt;p&gt;Great news! The new and improved Westerbork telescope in the northeast of the Netherlands &lt;a href=&quot;http://www.astron.nl/first-image-apertif-new-life-westerbork-radio-telescope&quot;&gt;has seen first light&lt;/a&gt;! If you are into radio astronomy, or if you have visited the second world war nazi camp and monument at Westerbork, you may be familiar with this instrument, which was built in 1970. The telescope is situated right next to the former transit camp. During the Second World War, Romani and Dutch Jews were assembled there, for transport to other Nazi concentration camps. The famous Anne Frank (from the diary) was kept here for a while.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;1050&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ZOtMneXEYlp6asnBzuEojw-af2965fd.BqK_Wjy2_lMWTj.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;A rebuilt barrack at Dutch Nazi camp Westerbork. Anne Frank stayed in this barrack from August till early September 1944, before she was taken to Auschwitz and then Bergen-Belsen. Picture from Wikipedia, courtesy Blacknight&lt;/p&gt;
&lt;p&gt;Today, you can visit the remains of the camp, which now is a monument. From the site, you can see the telescope, or actually telescopes, because the instrument consists of 14 separate dishes, 25 meters in diameter each. The total distance between the dishes is 2.7 kilometers, or 1.7 miles if you insist on using archaic units. The telescope actually is pretty old already. In fact, it is older than I am (I was built in ‘75). Nevertheless, this instrument has helped doing great science, and has led to many remarkable discoveries.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Mix7BRS8y2WHMX1eQfWiRw-88ec3984.D9j5M3nI_ZJpvxM.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Westerbork synthesis radio telescope. And typical Dutch weather:-) Picture made by me on a day the telescope was open for the public. Normally, cars are not allowed here, because they cause interference.&lt;/p&gt;
&lt;p&gt;Of course, technology does not stand still, and modern, more sensitive instruments were developed and built during the four decades (!) that this telescope has been operational. So, the beast was becoming a bit old and grumpy. Not to worry! We are Dutch, and don’t like to waste anything (some say we are cheapskates). So, recently, the receivers that are in the focal points of the dishes were upgraded with brand new ones. Originally, each dish contained only a single sensor, basically producing a single pixel. The new receiver, called APERTIF, actually is an array of sensors, called a Focal Plane Array (FPA). Compare it to a modern sensor in a camera, which produces several megapixels at once. So, this gives us more sensitivity, but especially a much larger window on the sky. We can see more at the same time. This is important if you want to make a survey, searching for objects that you don’t know yet, or which appear suddenly (like supernovae, pulsars, or signals from little green men).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1252&quot; height=&quot;826&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_pIoP_Vd-PXzaiskRPe9XeA-f89960ed.L51EjoUK_13zQ9o.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Focal Plane arrays rock! Picture courtesy ASTRON.&lt;/p&gt;
&lt;p&gt;So, why am I blogging about this? Well because it is cool, duh! And, because we at the &lt;a href=&quot;https://www.esciencecenter.nl/&quot;&gt;Netherlands eScience Center&lt;/a&gt; develop &lt;a href=&quot;https://www.esciencecenter.nl/project/aa-alert&quot;&gt;software to process the data&lt;/a&gt; generated by this instrument. To be more precise, we are working on &lt;a href=&quot;https://www.astron.nl/r-d-laboratory/arts/arts-apertif-radio-transient-system-apertif&quot;&gt;ARTS&lt;/a&gt;, the APERTIF radio transient system. We will, for instance, observe &lt;a href=&quot;https://en.wikipedia.org/wiki/Pulsar&quot;&gt;pulsars&lt;/a&gt;: neutron stars that are spinning quickly, emitting a beam like a light house. For some pulsars, the time between pulses is so constant that they are even more precise than an atomic clock! Pulsars are important for many reasons. One of them is that we hope to use them to detect gravitational waves, learning more about how the universe works.&lt;/p&gt;
&lt;p&gt;It is a privilege for us to write software that will help make these scientific discoveries happen! At the same time, it is a strange but beautiful thing that a site where so many bad things happened to so many people in the past now is one of the pinnacles of science.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_ZOtMneXEYlp6asnBzuEojw-af2965fd.BqK_Wjy2.jpeg" medium="image"/><author>Rob van Nieuwpoort</author></item><item><title>Travis caching and incremental builds</title><link>https://blog2.esciencecenter.nl/posts/2017-02-06---travis-caching-and-incremental-builds</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-06---travis-caching-and-incremental-builds</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_eCqVHpbrSZqs3AeGMUhY3Q-17430e5f.BJJxDGw1_Z2cdya4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update (Aug 7, 2018): added a section at the bottom with new configuration settings and an added time-out step for extending build times beyond the 50 minute limit to bootstrap your build cache.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Original post (Feb 6, 2017):&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I’ve been working on the C++ code &lt;a href=&quot;https://root.cern.ch/&quot;&gt;ROOT&lt;/a&gt;, which is a humongous data analysis package for particle physics. As part of &lt;a href=&quot;https://www.esciencecenter.nl/project/automated-parallel-calculation-of-collaborative-statistical-models&quot;&gt;my current project&lt;/a&gt;, I’m only adding things to a small part (&lt;a href=&quot;https://root.cern.ch/roofit-20-minutes&quot;&gt;RooFit&lt;/a&gt;), but to do so, the full code has to be compiled, which can take hours. Luckily you don’t have to rebuild everything every time you make a small change to one file thanks to smart building tools like &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I decided that I wanted to add continuous integration to my workflow. &lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis CI&lt;/a&gt; is the current go-to solution for us (it’s open, transparent and free!). However, when using Travis, one has to jump through a few hoops to allow quick rebuilds (I guess the same holds for other continuous integration services, but I haven’t tried those…). Speed is absolutely necessary for running tests in ROOT, since the full build on Travis takes more than 45 minutes and the timeout for free Travis accounts is 50 minutes, which I hit regularly, and that’s still without any tests… However, even when I cached my &lt;a href=&quot;https://docs.travis-ci.com/user/caching/&quot;&gt;build directory&lt;/a&gt;, the next time a build was triggered, every file would be compiled all over again. What’s up?&lt;/p&gt;
&lt;h2 id=&quot;build-tool-dependency-resolving&quot;&gt;Build tool dependency resolving&lt;/h2&gt;
&lt;p&gt;One of the main reasons for using &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;ninja&lt;/code&gt; or similar build tools (you can use both with ROOT, since it uses &lt;a href=&quot;https://cmake.org/&quot;&gt;CMake&lt;/a&gt;, which supports both &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;ninja&lt;/code&gt;) is that they incrementally rebuild your code. When you change a single source file, only that file is recompiled to an object file and linked into the final binary. The other object files are reused from the previous build.&lt;/p&gt;
&lt;p&gt;The way these tools find out which files to recompile is by using timestamps, specifically the mtime, or modification time, on Unix systems.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;make&lt;/code&gt; simply checks whether the mtime of a source file is older than the corresponding object file. This makes perfect sense: when the object file is built, it is newer than the source file. When the source file is edited, its mtime will become newer than the object file and the file should and will be rebuilt.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ninja&lt;/code&gt; can store all mtimes of the object and other files it generates in a log file. On the next build, it does the same check as &lt;code&gt;make&lt;/code&gt;, but also checks whether the mtimes of the generated files have changed compared to the times that were stored in the log file. This is used to avoid having to check dependencies between object files.&lt;/p&gt;
&lt;h2 id=&quot;travis-git-and-timestamps&quot;&gt;Travis, Git and timestamps&lt;/h2&gt;
&lt;p&gt;In Travis, we can cache the files that were created in a build, so surely we can reuse these in the next build? The mtimes of the build files are even preserved by the &lt;code&gt;tar&lt;/code&gt; archive that is used for caching. So what’s the problem with Travis?&lt;/p&gt;
&lt;p&gt;On each commit to GitHub a Travis build is triggered. Travis starts up a container or VM with a clean environment. It then installs some tools, the cached files from the previous build are restored and &lt;strong&gt;your GitHub repository is freshly cloned&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git&lt;/code&gt; does not store timestamps, though! It only looks at the contents of your files. A fresh &lt;code&gt;git clone&lt;/code&gt; creates all files in the repo anew. This means that all of a sudden your source files are all newer than the cached build files. Clearly, both &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;ninja&lt;/code&gt; will protest and rebuild!&lt;/p&gt;
&lt;h2 id=&quot;hammer-time&quot;&gt;Hammer time&lt;/h2&gt;
&lt;p&gt;The solution is simple: we simply change some mtimes using &lt;code&gt;touch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most cached object files will not have to be rebuilt on a next build, so their mtimes must be newer than the source files in the git repo.&lt;/p&gt;
&lt;h3 id=&quot;make&quot;&gt;Make&lt;/h3&gt;
&lt;p&gt;In the case of &lt;code&gt;make&lt;/code&gt;, the key is the order of timestamps of dependencies. We can save the order at the end of each build in a file in the cache:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;find &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;printf &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%T+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\t&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;%p&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sort &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cut &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; touch_order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in the next build, after the cache is restored, we can recreate the mtime ordering by touching the files in the saved order:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [[ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f touch_order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt ]]; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while read fn; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    touch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  done &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; touch_order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I added the &lt;code&gt;if&lt;/code&gt; statement for when I delete my cache and the file is gone. Now all cached files are newer than the cloned source files and nothing will be rebuilt… But that’s not really what we want either! We want the files that were changed since the cache was created to be rebuilt. So after creating the &lt;code&gt;touch_order.txt&lt;/code&gt; file, let’s also create a file with the hash of the commit we just built:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cd &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;${TRAVIS_BUILD_DIR}&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; git rev&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HEAD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CACHED_DIR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;previous_git_commit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;$CACHED_DIR&lt;/code&gt; is the directory with the build files, in which the previous order commands were also run. Then before you start building, add a command that uses this information to fix the mtimes of the files that were changed since the previous commit:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cd &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;${TRAVIS_BUILD_DIR}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;read &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;PREVIOUS_GIT_COMMIT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CACHED_DIR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;previous_git_commit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;changed_files&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`git diff &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--name-only $PREVIOUS_GIT_COMMIT HEAD\` &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;touch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`echo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;changed_files&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I put the changed files list in an environment variable so I could easily add some &lt;code&gt;echo&lt;/code&gt; ‘s for debugging. That’s it! Running &lt;code&gt;make&lt;/code&gt; now takes advantage of the already built files and you save tons of time on each build.&lt;/p&gt;
&lt;p&gt;Alternatively, to fix the git repo files’ mtimes, you could use an &lt;a href=&quot;https://github.com/MestreLion/git-tools/blob/master/git-restore-mtime-core&quot;&gt;existing script like this one,&lt;/a&gt; but we don’t need that kind of precision in mtimes here and it comes with an extra download step and Python dependencies, which may take more precious Travis time.&lt;/p&gt;
&lt;h3 id=&quot;ninja&quot;&gt;Ninja&lt;/h3&gt;
&lt;p&gt;Using &lt;code&gt;ninja&lt;/code&gt; for building is usually a lot faster on rebuilds than &lt;code&gt;make&lt;/code&gt;. For ROOT, when I run &lt;code&gt;make&lt;/code&gt; on my laptop without changing any file (so without any actual compiling), the &lt;code&gt;make&lt;/code&gt; run still takes 12 seconds, while &lt;code&gt;ninja&lt;/code&gt; finishes in 0.2 seconds. That’s pure overhead for ya. When actual compiling takes place, the difference can become even larger, since &lt;code&gt;ninja&lt;/code&gt; smartly detects dependencies, so it only recompiles the absolute necessary parts.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;ninja&lt;/code&gt; is not as mainstream as &lt;code&gt;make&lt;/code&gt;. On Travis, &lt;code&gt;make&lt;/code&gt; comes pre-installed, whereas &lt;code&gt;ninja&lt;/code&gt; has to be installed with &lt;code&gt;apt&lt;/code&gt;, which takes an extra download and installation step. The time this costs has to be weighed against the time gained in the build step. Ymmv.&lt;/p&gt;
&lt;p&gt;In any case, rebuilding on Travis with &lt;code&gt;ninja&lt;/code&gt; works slightly differently than with &lt;code&gt;make&lt;/code&gt;, since the absolute mtimes are compared, not just the order. The mtimes of the build files themselves must not be changed. So if we cannot change those, the only other option is to make all the cloned source files older than the oldest build file:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;find &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;printf &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%.10T@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sort &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; read &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;export &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;find &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{TRAVIS_BUILD_DIR} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exec touch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“@$&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Luckily, the order of the source files’ mtimes doesn’t matter, so we just set all of them to the timestamp of the oldest build file, minus one.&lt;/p&gt;
&lt;p&gt;Finally, touch the source files that were changed since the previous build in the same way as with &lt;code&gt;make&lt;/code&gt; above. Lightning fast rebuilds, yay!&lt;/p&gt;
&lt;p&gt;Sure we can.&lt;/p&gt;
&lt;h2 id=&quot;update-7-aug-2018-mate--hajime&quot;&gt;Update (7 Aug, 2018): Mate — Hajime&lt;/h2&gt;
&lt;p&gt;In the one and a half years since publishing this post (as written above), a few things changed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default Travis environment was updated, changing some things for me&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/root-project/root&quot;&gt;ROOT migrated to GitHub&lt;/a&gt;, making forking, PRs, etc a lot easier&lt;/li&gt;
&lt;li&gt;… but it also added a Travis configuration file, which conflicted with mine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result I stopped using my own Travis configuration and went without CI for about a year. Bad idea… but that’s a different story. Last week, however, I decided I wanted it back. I updated my setup to fit the latest Travis environments and it is now fully operational again.&lt;/p&gt;
&lt;p&gt;I now also added a time-out to the building phase (&lt;a href=&quot;https://github.com/roofit-dev/root/blob/travis_trusty2018_update/.travis.yml&quot;&gt;see a working example here&lt;/a&gt;), which automatically stops building after some set time:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;timeout 35m ninja &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;j4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I chose 35 minutes, because loading the cache, Travis setup and storing the cache together took about 10–15 minutes. This way, I automatically stay within the 50 minute limit.&lt;/p&gt;
&lt;p&gt;It turns out this has become crucial, since for some reason building on Travis has become a lot slower for me. Either ROOT has grown substantially, or the Travis setup I chose is less suitable than the one I had previously.&lt;/p&gt;
&lt;p&gt;In any case, I now need at least three Travis “cached build cycles” to fully build ROOT. The way I run multiple build cycles is by simply manually restarting the build after it has “failed” due to the timeout.&lt;/p&gt;</description><pubDate>Mon, 06 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4800&quot; height=&quot;3200&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_eCqVHpbrSZqs3AeGMUhY3Q-17430e5f.BJJxDGw1_Z2cdya4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update (Aug 7, 2018): added a section at the bottom with new configuration settings and an added time-out step for extending build times beyond the 50 minute limit to bootstrap your build cache.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Original post (Feb 6, 2017):&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I’ve been working on the C++ code &lt;a href=&quot;https://root.cern.ch/&quot;&gt;ROOT&lt;/a&gt;, which is a humongous data analysis package for particle physics. As part of &lt;a href=&quot;https://www.esciencecenter.nl/project/automated-parallel-calculation-of-collaborative-statistical-models&quot;&gt;my current project&lt;/a&gt;, I’m only adding things to a small part (&lt;a href=&quot;https://root.cern.ch/roofit-20-minutes&quot;&gt;RooFit&lt;/a&gt;), but to do so, the full code has to be compiled, which can take hours. Luckily you don’t have to rebuild everything every time you make a small change to one file thanks to smart building tools like &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I decided that I wanted to add continuous integration to my workflow. &lt;a href=&quot;https://travis-ci.org/&quot;&gt;Travis CI&lt;/a&gt; is the current go-to solution for us (it’s open, transparent and free!). However, when using Travis, one has to jump through a few hoops to allow quick rebuilds (I guess the same holds for other continuous integration services, but I haven’t tried those…). Speed is absolutely necessary for running tests in ROOT, since the full build on Travis takes more than 45 minutes and the timeout for free Travis accounts is 50 minutes, which I hit regularly, and that’s still without any tests… However, even when I cached my &lt;a href=&quot;https://docs.travis-ci.com/user/caching/&quot;&gt;build directory&lt;/a&gt;, the next time a build was triggered, every file would be compiled all over again. What’s up?&lt;/p&gt;
&lt;h2 id=&quot;build-tool-dependency-resolving&quot;&gt;Build tool dependency resolving&lt;/h2&gt;
&lt;p&gt;One of the main reasons for using &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;ninja&lt;/code&gt; or similar build tools (you can use both with ROOT, since it uses &lt;a href=&quot;https://cmake.org/&quot;&gt;CMake&lt;/a&gt;, which supports both &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;ninja&lt;/code&gt;) is that they incrementally rebuild your code. When you change a single source file, only that file is recompiled to an object file and linked into the final binary. The other object files are reused from the previous build.&lt;/p&gt;
&lt;p&gt;The way these tools find out which files to recompile is by using timestamps, specifically the mtime, or modification time, on Unix systems.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;make&lt;/code&gt; simply checks whether the mtime of a source file is older than the corresponding object file. This makes perfect sense: when the object file is built, it is newer than the source file. When the source file is edited, its mtime will become newer than the object file and the file should and will be rebuilt.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ninja&lt;/code&gt; can store all mtimes of the object and other files it generates in a log file. On the next build, it does the same check as &lt;code&gt;make&lt;/code&gt;, but also checks whether the mtimes of the generated files have changed compared to the times that were stored in the log file. This is used to avoid having to check dependencies between object files.&lt;/p&gt;
&lt;h2 id=&quot;travis-git-and-timestamps&quot;&gt;Travis, Git and timestamps&lt;/h2&gt;
&lt;p&gt;In Travis, we can cache the files that were created in a build, so surely we can reuse these in the next build? The mtimes of the build files are even preserved by the &lt;code&gt;tar&lt;/code&gt; archive that is used for caching. So what’s the problem with Travis?&lt;/p&gt;
&lt;p&gt;On each commit to GitHub a Travis build is triggered. Travis starts up a container or VM with a clean environment. It then installs some tools, the cached files from the previous build are restored and &lt;strong&gt;your GitHub repository is freshly cloned&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git&lt;/code&gt; does not store timestamps, though! It only looks at the contents of your files. A fresh &lt;code&gt;git clone&lt;/code&gt; creates all files in the repo anew. This means that all of a sudden your source files are all newer than the cached build files. Clearly, both &lt;code&gt;make&lt;/code&gt; and &lt;code&gt;ninja&lt;/code&gt; will protest and rebuild!&lt;/p&gt;
&lt;h2 id=&quot;hammer-time&quot;&gt;Hammer time&lt;/h2&gt;
&lt;p&gt;The solution is simple: we simply change some mtimes using &lt;code&gt;touch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most cached object files will not have to be rebuilt on a next build, so their mtimes must be newer than the source files in the git repo.&lt;/p&gt;
&lt;h3 id=&quot;make&quot;&gt;Make&lt;/h3&gt;
&lt;p&gt;In the case of &lt;code&gt;make&lt;/code&gt;, the key is the order of timestamps of dependencies. We can save the order at the end of each build in a file in the cache:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;find &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;printf &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%T+&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\t&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;%p&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sort &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; cut &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; touch_order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in the next build, after the cache is restored, we can recreate the mtime ordering by touching the files in the saved order:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [[ &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;f touch_order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt ]]; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  while read fn; &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    touch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  done &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; touch_order&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I added the &lt;code&gt;if&lt;/code&gt; statement for when I delete my cache and the file is gone. Now all cached files are newer than the cloned source files and nothing will be rebuilt… But that’s not really what we want either! We want the files that were changed since the cache was created to be rebuilt. So after creating the &lt;code&gt;touch_order.txt&lt;/code&gt; file, let’s also create a file with the hash of the commit we just built:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cd &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;${TRAVIS_BUILD_DIR}&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x26;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; git rev&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;parse &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;HEAD&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CACHED_DIR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;previous_git_commit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;$CACHED_DIR&lt;/code&gt; is the directory with the build files, in which the previous order commands were also run. Then before you start building, add a command that uses this information to fix the mtimes of the files that were changed since the previous commit:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;cd &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;${TRAVIS_BUILD_DIR}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;read &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;PREVIOUS_GIT_COMMIT&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;CACHED_DIR&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;previous_git_commit&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;changed_files&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`git diff &lt;/span&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;--name-only $PREVIOUS_GIT_COMMIT HEAD\` &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;touch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`echo &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;changed_files&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I put the changed files list in an environment variable so I could easily add some &lt;code&gt;echo&lt;/code&gt; ‘s for debugging. That’s it! Running &lt;code&gt;make&lt;/code&gt; now takes advantage of the already built files and you save tons of time on each build.&lt;/p&gt;
&lt;p&gt;Alternatively, to fix the git repo files’ mtimes, you could use an &lt;a href=&quot;https://github.com/MestreLion/git-tools/blob/master/git-restore-mtime-core&quot;&gt;existing script like this one,&lt;/a&gt; but we don’t need that kind of precision in mtimes here and it comes with an extra download step and Python dependencies, which may take more precious Travis time.&lt;/p&gt;
&lt;h3 id=&quot;ninja&quot;&gt;Ninja&lt;/h3&gt;
&lt;p&gt;Using &lt;code&gt;ninja&lt;/code&gt; for building is usually a lot faster on rebuilds than &lt;code&gt;make&lt;/code&gt;. For ROOT, when I run &lt;code&gt;make&lt;/code&gt; on my laptop without changing any file (so without any actual compiling), the &lt;code&gt;make&lt;/code&gt; run still takes 12 seconds, while &lt;code&gt;ninja&lt;/code&gt; finishes in 0.2 seconds. That’s pure overhead for ya. When actual compiling takes place, the difference can become even larger, since &lt;code&gt;ninja&lt;/code&gt; smartly detects dependencies, so it only recompiles the absolute necessary parts.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;ninja&lt;/code&gt; is not as mainstream as &lt;code&gt;make&lt;/code&gt;. On Travis, &lt;code&gt;make&lt;/code&gt; comes pre-installed, whereas &lt;code&gt;ninja&lt;/code&gt; has to be installed with &lt;code&gt;apt&lt;/code&gt;, which takes an extra download and installation step. The time this costs has to be weighed against the time gained in the build step. Ymmv.&lt;/p&gt;
&lt;p&gt;In any case, rebuilding on Travis with &lt;code&gt;ninja&lt;/code&gt; works slightly differently than with &lt;code&gt;make&lt;/code&gt;, since the absolute mtimes are compared, not just the order. The mtimes of the build files themselves must not be changed. So if we cannot change those, the only other option is to make all the cloned source files older than the oldest build file:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;find &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;printf &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;%.10T@&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; sort &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; read &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;export &lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;=$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;find &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{TRAVIS_BUILD_DIR} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;type f &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;exec touch &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;c &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;m &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;d &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;“@$&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;OLDEST_MTIME&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {} &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;\&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Luckily, the order of the source files’ mtimes doesn’t matter, so we just set all of them to the timestamp of the oldest build file, minus one.&lt;/p&gt;
&lt;p&gt;Finally, touch the source files that were changed since the previous build in the same way as with &lt;code&gt;make&lt;/code&gt; above. Lightning fast rebuilds, yay!&lt;/p&gt;
&lt;p&gt;Sure we can.&lt;/p&gt;
&lt;h2 id=&quot;update-7-aug-2018-mate--hajime&quot;&gt;Update (7 Aug, 2018): Mate — Hajime&lt;/h2&gt;
&lt;p&gt;In the one and a half years since publishing this post (as written above), a few things changed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default Travis environment was updated, changing some things for me&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/root-project/root&quot;&gt;ROOT migrated to GitHub&lt;/a&gt;, making forking, PRs, etc a lot easier&lt;/li&gt;
&lt;li&gt;… but it also added a Travis configuration file, which conflicted with mine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result I stopped using my own Travis configuration and went without CI for about a year. Bad idea… but that’s a different story. Last week, however, I decided I wanted it back. I updated my setup to fit the latest Travis environments and it is now fully operational again.&lt;/p&gt;
&lt;p&gt;I now also added a time-out to the building phase (&lt;a href=&quot;https://github.com/roofit-dev/root/blob/travis_trusty2018_update/.travis.yml&quot;&gt;see a working example here&lt;/a&gt;), which automatically stops building after some set time:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;timeout 35m ninja &lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;j4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I chose 35 minutes, because loading the cache, Travis setup and storing the cache together took about 10–15 minutes. This way, I automatically stay within the 50 minute limit.&lt;/p&gt;
&lt;p&gt;It turns out this has become crucial, since for some reason building on Travis has become a lot slower for me. Either ROOT has grown substantially, or the Travis setup I chose is less suitable than the one I had previously.&lt;/p&gt;
&lt;p&gt;In any case, I now need at least three Travis “cached build cycles” to fully build ROOT. The way I run multiple build cycles is by simply manually restarting the build after it has “failed” due to the timeout.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_eCqVHpbrSZqs3AeGMUhY3Q-17430e5f.BJJxDGw1.jpeg" medium="image"/><author>Patrick Bos</author></item><item><title>What games can teach you (about science)</title><link>https://blog2.esciencecenter.nl/posts/2017-02-06---what-games-can-teach-you-about-science</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-06---what-games-can-teach-you-about-science</guid><description>&lt;p&gt;If you know me at all, you have probably heard me talk about computer games at least once. Games are such a huge part of how I spend my free time, it is hard for me to not talk about them in the best of circumstances, but if there is at least one other enthusiast present, you will find me going off on a tangent &lt;a href=&quot;http://www.urbandictionary.com/define.php?term=soon+%28tm%29&quot;&gt;soon(tm)&lt;/a&gt;. That goes for professional settings as well — because the interfaces they use to convey complex information in simple terms are a great source of inspiration for my work as eScience Research Engineer. In this blog I’d like to share this passion, and more specifically the passion I have for science-related games.&lt;/p&gt;
&lt;p&gt;Many of the younger generation of readers might not realize this, but when I grew up in the late 20th century, games were considered a complete waste of time by anyone and everyone. Even if the entire reason for your complete English vocabulary (I am not a native speaker) was gained from playing games like King’s Quest and Space Quest, and your analytical thinking was stimulated as well. Anyway, enough ranting about my childhood issues, let’s get to the point.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;387&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vJnXbj2xAmkwMKfjraOPDw-d5bd3260.BTWduDak_Z24oNq7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;King’s quest, by Sierra Online. Where I had to learn English to survive.&lt;/p&gt;
&lt;h3 id=&quot;into-the-sandbox-a-broader-perspective-on-games&quot;&gt;Into the sandbox: A broader perspective on games&lt;/h3&gt;
&lt;p&gt;In 2017, the video games market has changed from having an overabundance of ‘classic’ AAA titles funded by large production companies to a much broader spectrum of titles. This development was largely set in motion due to &lt;a href=&quot;http://store.steampowered.com/&quot;&gt;Valve’s Steam store&lt;/a&gt; making sure smaller titles could grab the spotlight without having an enormous marketing budget to back them up. These self-funded ‘Indie’ (aka Independent) titles ==now got== more attention and were allowed to grow.&lt;/p&gt;
&lt;p&gt;The first of the hugely successful Indie titles is, by now, a legend. Minecraft took the world by storm in 2010. This game singlehandedly showed the large production companies that they had been wrong all along, instead of having set goals, a lot of people wanted to express their creativity in games. They wanted a digital sandbox. Sales of this game with procedurally generated content and the ugliest graphics of any game in 10 years went through the roof. Minecraft is now the second most sold game in history, after Tetris. And, as a further measure of success, the Intellectual Property was bought by Microsoft for 2.5 Billion Dollars in 2014.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r-luqA5NbzVzH5ziw3W2AQ-a0ac21f9.Y-YVkvBi_29W6KF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Creativity and architecture in the sandbox of Minecraft, by Mojang.&lt;/p&gt;
&lt;p&gt;With Minecraft’s success the way was clear for others to follow. Indie titles popped up everywhere and showed the investors of the world that the sandbox game was here to stay.&lt;/p&gt;
&lt;h3 id=&quot;orbital-mechanics&quot;&gt;Orbital Mechanics!&lt;/h3&gt;
&lt;p&gt;In 2014 I found this little game called Kerbal Space Program, a side project of a developer for a marketing company. Back then, it was a little sandbox game where you could slap some rockets together using a catalog of parts and try to launch them into space to do science. Still in the ‘alpha’ stage of development, the game had little functionality, even less tutorials and plenty of bugs.&lt;/p&gt;
&lt;p&gt;I’ve always been interested in space, science fiction was my first real love in literature, and science is obviously my thing. It was &lt;em&gt;perfect&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;866&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IQRFPF0oYsVQOymkwHysQQ-55282d32.CTrs8VEs_Z3MfK4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Just a simple Hohmann Transfer to Tylo”, a Screenshot from Kerbal Space Program, by Squad&lt;/p&gt;
&lt;p&gt;It was also the reason I realized I knew nothing about orbital mechanics.&lt;/p&gt;
&lt;p&gt;If you haven’t studied physics since high school, you probably have some vague idea on how the physics of the solar system work. You have some notion of gravity, and some idea of aerodynamics. Well, unless you’ve grasped all of these concepts a lot better than the average person, &lt;a href=&quot;http://knowyourmeme.com/memes/you-know-nothing-jon-snow&quot;&gt;you know nothing, Jon Snow.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sure, I had heard people say before that orbiting a planet is the same as continuously falling and missing the ground because you’re going too fast, I had heard it, and disregarded it as nonsense or maybe an abstraction. I even thought I understood the &lt;a href=&quot;https://www.nasa.gov/mission_pages/station/expeditions/expedition30/tryanny.html&quot;&gt;tyranny of the Rocket equation&lt;/a&gt;. Sure, I’ve heard people say that flying to the moon is hard, or that it was such a long trip to Mars, or using gravity assists, and I thought I understood that too. &lt;em&gt;But, at the same time, I argued for nuclear fission as a waste free alternative power because we could always just launch our nuclear waste into the sun for destruction afterwards…&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;enter-the-community-aerodynamics&quot;&gt;Enter the community: Aerodynamics&lt;/h3&gt;
&lt;p&gt;Even though this game was perfect at the start, I had no idea it would get so much better over time. The greatest asset of Kerbal Space Program was not its game engine, its content or even its idea. These all paled in comparison to its &lt;em&gt;community&lt;/em&gt;. So many people who were interested in the same things found this game and its forums, and started to write mods (short for modification).&lt;/p&gt;
&lt;p&gt;While the underlying physics of Kerbal Space Program’s aerodynamics had seemed decent up until now, the addition of the mods called “Ferram Aerospace Research” and “Deadly Reentry” taught me I was wrong there too. Gone was everything I had learned about rocket flight trajectories and the ins and outs of Single Stage To Orbit space-plane construction (a plane that can boost itself into space from a horizontal launch, without dropping any components in the process). These mods introduced a working model of aerodynamics that made the original hide in a corner in shame.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SIXzLhRMuafEKrYrQMvaGw-75d36b16.Cbkj28tE_Z1z0yOl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Designing spaceplanes with Ferram Aerospace Research, a Screenshot from Kerbal Space Program, by Squad&lt;/p&gt;
&lt;p&gt;Suddenly I had to be concerned with things like the center of lift on my plane and the center of mass, and how they relate to each other. I found myself researching concepts like ==sideslip angle and stability derivatives==, changing aerodynamic conditions during the transition to supersonic speeds, and designing for in-flight changing mass because of fuel usage. When my original designs had happily used Aerobreaking in the atmosphere of Jool (a gas giant modeled after Jupiter), Deadly Reentry taught me this was not as viable a strategy as I thought without bringing the extra mass of a decent heat shield:)&lt;/p&gt;
&lt;h3 id=&quot;even-more-physics-rocket-fuel&quot;&gt;Even more physics: Rocket fuel&lt;/h3&gt;
&lt;p&gt;And then there was “Realism Overhaul”, oh my. A collection of mods dedicated to making your life completely miserable. Concepts in Rocket science I hadn’t even considered until now suddenly became a whole new obstacle. Engines that need some form of ignition which has limited use, and cannot throttle from 1% to 100% (like in the standard game), fuel tanks that allow the fuel to float in the middle of the tank in zero-G and therefore not reach the engine, or fuel that needs to be kept at cryogenic temperatures to not boil off through the tank walls. Fuel types that auto-ignite when joined together for reaction control thrusters (the kind that allow you to do small maneuvers) and the different levels of efficiency and thrust to be gained with each.&lt;/p&gt;
&lt;h3 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h3&gt;
&lt;p&gt;Realism overhaul and the things Kerbal can teach you do not stop here, but in the interest of keeping things short, I will break off this tangent and allow you to experience these wonders on your own. And, if you will not take my word for it, please heed the words of the immortal Randall Munroe:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;878&quot; height=&quot;579&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_z3unaHOG6jxnZ4icWb9yqA-18b8bb40.DJUab47T_Z1Kgdhw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://imgs.xkcd.com/comics/orbital_mechanics_2x.png&quot;&gt;https://imgs.xkcd.com/comics/orbital_mechanics_2x.png&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;inspiration&quot;&gt;Inspiration&lt;/h3&gt;
&lt;p&gt;==My job at the Netherlands eScience Center is to visualize scientific data for insight and understanding, but also in a large part, for inspiration. Visual analysis of data can lead to knowledge in learning what we know, but also what we do== ==&lt;em&gt;not&lt;/em&gt;== ==know.==&lt;/p&gt;
&lt;p&gt;Games and the interfaces they use to convey complex information in simple terms are a great source of inspiration for my own work, as well as the reason I got into Computer Science in the first place. But, at the same time, science will always be my passion and the reason that I do what I do. Without the science to back it up, a visualization is just a pretty picture.&lt;/p&gt;</description><pubDate>Mon, 06 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you know me at all, you have probably heard me talk about computer games at least once. Games are such a huge part of how I spend my free time, it is hard for me to not talk about them in the best of circumstances, but if there is at least one other enthusiast present, you will find me going off on a tangent &lt;a href=&quot;http://www.urbandictionary.com/define.php?term=soon+%28tm%29&quot;&gt;soon(tm)&lt;/a&gt;. That goes for professional settings as well — because the interfaces they use to convey complex information in simple terms are a great source of inspiration for my work as eScience Research Engineer. In this blog I’d like to share this passion, and more specifically the passion I have for science-related games.&lt;/p&gt;
&lt;p&gt;Many of the younger generation of readers might not realize this, but when I grew up in the late 20th century, games were considered a complete waste of time by anyone and everyone. Even if the entire reason for your complete English vocabulary (I am not a native speaker) was gained from playing games like King’s Quest and Space Quest, and your analytical thinking was stimulated as well. Anyway, enough ranting about my childhood issues, let’s get to the point.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;580&quot; height=&quot;387&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_vJnXbj2xAmkwMKfjraOPDw-d5bd3260.BTWduDak_Z24oNq7.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;King’s quest, by Sierra Online. Where I had to learn English to survive.&lt;/p&gt;
&lt;h3 id=&quot;into-the-sandbox-a-broader-perspective-on-games&quot;&gt;Into the sandbox: A broader perspective on games&lt;/h3&gt;
&lt;p&gt;In 2017, the video games market has changed from having an overabundance of ‘classic’ AAA titles funded by large production companies to a much broader spectrum of titles. This development was largely set in motion due to &lt;a href=&quot;http://store.steampowered.com/&quot;&gt;Valve’s Steam store&lt;/a&gt; making sure smaller titles could grab the spotlight without having an enormous marketing budget to back them up. These self-funded ‘Indie’ (aka Independent) titles ==now got== more attention and were allowed to grow.&lt;/p&gt;
&lt;p&gt;The first of the hugely successful Indie titles is, by now, a legend. Minecraft took the world by storm in 2010. This game singlehandedly showed the large production companies that they had been wrong all along, instead of having set goals, a lot of people wanted to express their creativity in games. They wanted a digital sandbox. Sales of this game with procedurally generated content and the ugliest graphics of any game in 10 years went through the roof. Minecraft is now the second most sold game in history, after Tetris. And, as a further measure of success, the Intellectual Property was bought by Microsoft for 2.5 Billion Dollars in 2014.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;960&quot; height=&quot;533&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_r-luqA5NbzVzH5ziw3W2AQ-a0ac21f9.Y-YVkvBi_29W6KF.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Creativity and architecture in the sandbox of Minecraft, by Mojang.&lt;/p&gt;
&lt;p&gt;With Minecraft’s success the way was clear for others to follow. Indie titles popped up everywhere and showed the investors of the world that the sandbox game was here to stay.&lt;/p&gt;
&lt;h3 id=&quot;orbital-mechanics&quot;&gt;Orbital Mechanics!&lt;/h3&gt;
&lt;p&gt;In 2014 I found this little game called Kerbal Space Program, a side project of a developer for a marketing company. Back then, it was a little sandbox game where you could slap some rockets together using a catalog of parts and try to launch them into space to do science. Still in the ‘alpha’ stage of development, the game had little functionality, even less tutorials and plenty of bugs.&lt;/p&gt;
&lt;p&gt;I’ve always been interested in space, science fiction was my first real love in literature, and science is obviously my thing. It was &lt;em&gt;perfect&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;866&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_IQRFPF0oYsVQOymkwHysQQ-55282d32.CTrs8VEs_Z3MfK4.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;“Just a simple Hohmann Transfer to Tylo”, a Screenshot from Kerbal Space Program, by Squad&lt;/p&gt;
&lt;p&gt;It was also the reason I realized I knew nothing about orbital mechanics.&lt;/p&gt;
&lt;p&gt;If you haven’t studied physics since high school, you probably have some vague idea on how the physics of the solar system work. You have some notion of gravity, and some idea of aerodynamics. Well, unless you’ve grasped all of these concepts a lot better than the average person, &lt;a href=&quot;http://knowyourmeme.com/memes/you-know-nothing-jon-snow&quot;&gt;you know nothing, Jon Snow.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sure, I had heard people say before that orbiting a planet is the same as continuously falling and missing the ground because you’re going too fast, I had heard it, and disregarded it as nonsense or maybe an abstraction. I even thought I understood the &lt;a href=&quot;https://www.nasa.gov/mission_pages/station/expeditions/expedition30/tryanny.html&quot;&gt;tyranny of the Rocket equation&lt;/a&gt;. Sure, I’ve heard people say that flying to the moon is hard, or that it was such a long trip to Mars, or using gravity assists, and I thought I understood that too. &lt;em&gt;But, at the same time, I argued for nuclear fission as a waste free alternative power because we could always just launch our nuclear waste into the sun for destruction afterwards…&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;enter-the-community-aerodynamics&quot;&gt;Enter the community: Aerodynamics&lt;/h3&gt;
&lt;p&gt;Even though this game was perfect at the start, I had no idea it would get so much better over time. The greatest asset of Kerbal Space Program was not its game engine, its content or even its idea. These all paled in comparison to its &lt;em&gt;community&lt;/em&gt;. So many people who were interested in the same things found this game and its forums, and started to write mods (short for modification).&lt;/p&gt;
&lt;p&gt;While the underlying physics of Kerbal Space Program’s aerodynamics had seemed decent up until now, the addition of the mods called “Ferram Aerospace Research” and “Deadly Reentry” taught me I was wrong there too. Gone was everything I had learned about rocket flight trajectories and the ins and outs of Single Stage To Orbit space-plane construction (a plane that can boost itself into space from a horizontal launch, without dropping any components in the process). These mods introduced a working model of aerodynamics that made the original hide in a corner in shame.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_SIXzLhRMuafEKrYrQMvaGw-75d36b16.Cbkj28tE_Z1z0yOl.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Designing spaceplanes with Ferram Aerospace Research, a Screenshot from Kerbal Space Program, by Squad&lt;/p&gt;
&lt;p&gt;Suddenly I had to be concerned with things like the center of lift on my plane and the center of mass, and how they relate to each other. I found myself researching concepts like ==sideslip angle and stability derivatives==, changing aerodynamic conditions during the transition to supersonic speeds, and designing for in-flight changing mass because of fuel usage. When my original designs had happily used Aerobreaking in the atmosphere of Jool (a gas giant modeled after Jupiter), Deadly Reentry taught me this was not as viable a strategy as I thought without bringing the extra mass of a decent heat shield:)&lt;/p&gt;
&lt;h3 id=&quot;even-more-physics-rocket-fuel&quot;&gt;Even more physics: Rocket fuel&lt;/h3&gt;
&lt;p&gt;And then there was “Realism Overhaul”, oh my. A collection of mods dedicated to making your life completely miserable. Concepts in Rocket science I hadn’t even considered until now suddenly became a whole new obstacle. Engines that need some form of ignition which has limited use, and cannot throttle from 1% to 100% (like in the standard game), fuel tanks that allow the fuel to float in the middle of the tank in zero-G and therefore not reach the engine, or fuel that needs to be kept at cryogenic temperatures to not boil off through the tank walls. Fuel types that auto-ignite when joined together for reaction control thrusters (the kind that allow you to do small maneuvers) and the different levels of efficiency and thrust to be gained with each.&lt;/p&gt;
&lt;h3 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h3&gt;
&lt;p&gt;Realism overhaul and the things Kerbal can teach you do not stop here, but in the interest of keeping things short, I will break off this tangent and allow you to experience these wonders on your own. And, if you will not take my word for it, please heed the words of the immortal Randall Munroe:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;878&quot; height=&quot;579&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_z3unaHOG6jxnZ4icWb9yqA-18b8bb40.DJUab47T_Z1Kgdhw.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://imgs.xkcd.com/comics/orbital_mechanics_2x.png&quot;&gt;https://imgs.xkcd.com/comics/orbital_mechanics_2x.png&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;inspiration&quot;&gt;Inspiration&lt;/h3&gt;
&lt;p&gt;==My job at the Netherlands eScience Center is to visualize scientific data for insight and understanding, but also in a large part, for inspiration. Visual analysis of data can lead to knowledge in learning what we know, but also what we do== ==&lt;em&gt;not&lt;/em&gt;== ==know.==&lt;/p&gt;
&lt;p&gt;Games and the interfaces they use to convey complex information in simple terms are a great source of inspiration for my own work, as well as the reason I got into Computer Science in the first place. But, at the same time, science will always be my passion and the reason that I do what I do. Without the science to back it up, a visualization is just a pretty picture.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_vJnXbj2xAmkwMKfjraOPDw-d5bd3260.BTWduDak.png" medium="image"/><author>Maarten van Meersbergen</author></item><item><title>What happened during the “Historic newspapers as ‘big data’” congress</title><link>https://blog2.esciencecenter.nl/posts/2017-02-06---what-happened-during-the-historic-newspapers-as-big-data</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-06---what-happened-during-the-historic-newspapers-as-big-data</guid><description>&lt;p&gt;On Friday 20th of January 2017, the Royal Library (a.k.a. &lt;a href=&quot;http://kb.nl/&quot;&gt;Koninklijke Bibilotheek&lt;/a&gt; or KB) hosted the second congress on &lt;a href=&quot;https://www.kb.nl/nieuws/2016/historische-kranten-als-big-data-ii-concepten-op-drift&quot;&gt;Historic newspapers as big data&lt;/a&gt;, with the central topic of Concept Drift. Slides and photos can be found in the &lt;a href=&quot;https://www.kb.nl/nieuws/2017/historisch-onderzoek-in-digitale-kranten-verslag-van-het-big-data-congres&quot;&gt;KB website&lt;/a&gt;. Concept Drift is the study of how a concept is modified as time goes by — this is a topic which interests me as it relates to one of my previous projects, &lt;a href=&quot;https://www.esciencecenter.nl/project/mining-shifting-concepts-through-time-shico&quot;&gt;ShiCo&lt;/a&gt;. It was a very well attended event, where many familiar faces were present.&lt;/p&gt;
&lt;h2 id=&quot;historische-kranten-als-big-data-ii-concepten-op-drift&quot;&gt;&lt;a href=&quot;https://www.kb.nl/nieuws/2016/historische-kranten-als-big-data-ii-concepten-op-drift?source=post_page-----1cc557b46ddf---------------------------------------&quot;&gt;Historische kranten als ‘big data’ II: Concepten op drift&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;op-het-congres-krijgen-wetenschappers-uit-diverse-disciplines-het-woord-variërend-van-historici-tot-computationeel&quot;&gt;Op het congres krijgen wetenschappers uit diverse disciplines het woord, variërend van historici tot computationeel…&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.kb.nl&quot;&gt;www.kb.nl&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;morning-keynotes&quot;&gt;Morning keynotes&lt;/h2&gt;
&lt;p&gt;During the morning session, Lily Knibbeler highlighted the importance of &lt;a href=&quot;http://www.delpher.nl/&quot;&gt;Delpher&lt;/a&gt;, as a research resource for exploring historic news papers. Delpher is a data store where you can find digitalized newspaper articles in Dutch. He emphasized the KB’s desire of fostering an open community where we can work and learn from each other. This is definitely something I feel is extremely important — we should all work together more closely and make the most of the fantastic resources (data and expertise) which are available at the KB and other organisations.&lt;/p&gt;
&lt;p&gt;During his keynote speech, Steven Claeyssens noted how libraries themselves are changing and drifting towards being more inclusive for machines. This brought up the topic of the quality of OCR (&lt;a href=&quot;https://en.wikipedia.org/wiki/Optical_character_recognition&quot;&gt;optical character recognition&lt;/a&gt;) technology. It is an issue the community at large acknowledges and is actively working on; it is also an issue where one of our engineers, &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-janneke-van-der-zwaan&quot;&gt;Janneke&lt;/a&gt;, has a personal interest (which she expressed during her &lt;a href=&quot;#7d00&quot;&gt;Flash presentation&lt;/a&gt;). The last keynote speech by Hein van den Berg focused on detailed definitions of concept schemas and their importance to understand concept drift.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AASpN8mEA0hBKxlmvacFiw-0d5fa319.BV_ETvwq_Z21YSI2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lunch time was occupied by interesting conversations as well as a number of demos scattered across the room.&lt;/p&gt;
&lt;h2 id=&quot;afternoon-session&quot;&gt;Afternoon session&lt;/h2&gt;
&lt;p&gt;After lunch, the dynamic duo, Pim Huijnen and Melvin Wevers, spoke about digital tools they use in historical research (both of which have eScience center connection): &lt;a href=&quot;http://texcavator.hum.uu.nl/&quot;&gt;Texcavator&lt;/a&gt; (on which Janneke worked) and &lt;a href=&quot;https://github.com/NLeSC/ShiCo&quot;&gt;ShiCo&lt;/a&gt; (on which &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-carlos-martinez-ortiz&quot;&gt;I worked&lt;/a&gt;). It is great to see eScience tools being used by domain experts!&lt;/p&gt;
&lt;p&gt;The first round of flash presentations featured Janneke, pitching her idea for deep learning based OCR post-correction — a member of the public mentioned &lt;a href=&quot;https://github.com/tmbdev/ocropy&quot;&gt;OCRopus&lt;/a&gt; as a possible alternative, which would be interesting to look into to find out whether it is suitable or not. Martin Reynaert also talked about OCR — hot topic!&lt;/p&gt;
&lt;p&gt;The afternoon session continued with an interesting talk by Laura Hollink on the use of tools for evaluating concept shifts on linked data, Hennie Brugman presenting &lt;a href=&quot;http://www.nederlab.nl/onderzoeksportaal/&quot;&gt;Nederlab&lt;/a&gt;, Marieke van Erp also discussed the difficulties of analysing semantic changes and how this can be tackled with tools (with nice connections to &lt;a href=&quot;http://www.clariah.nl/&quot;&gt;CLARIAH&lt;/a&gt;). Finally Lotte Wilms also sneak previewed &lt;a href=&quot;http://www.kbresearch.nl/genre/&quot;&gt;tools&lt;/a&gt; from &lt;a href=&quot;http://lab.kbresearch.nl/&quot;&gt;KB Lab&lt;/a&gt;. So many cool tools! I would love to play with all of them!&lt;/p&gt;
&lt;p&gt;The final session of the day featured Jaap Kamps discussing how the libraries are changing and the effect that has in how people use libraries for doing research. Serge ter Braake also discussed how research practice has changed with digital tools.&lt;/p&gt;
&lt;p&gt;During the second round of flash presentations I was particularly interested in the idea pitched by Astrid van Aggelen and Milan van Lange, regarding mining shifts in sentiment in newspapers — this seems like an interesting use case for ShiCo. This actually goes back to the point made during the morning presentations: we should try to work together!&lt;/p&gt;
&lt;h2 id=&quot;closing-time&quot;&gt;Closing time&lt;/h2&gt;
&lt;p&gt;From the final words of Joris van Eijnattten during his last minutes as KB fellow, 3 things stood out as important to me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The importance of analyzing networks of words and concepts&lt;/li&gt;
&lt;li&gt;The importance of classification of words and concepts&lt;/li&gt;
&lt;li&gt;The importance of analyzing language variations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is clear that there are still many interesting challenges in this community, and I for one would be very excited to continue collaborating with everyone in this field.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Q4uNpqEcwTFD39dn3-mniA-1a67b0fe.BOUYVebn_13LMnJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Closing remarks by Joris van Eijnattten&lt;/p&gt;</description><pubDate>Mon, 06 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;On Friday 20th of January 2017, the Royal Library (a.k.a. &lt;a href=&quot;http://kb.nl/&quot;&gt;Koninklijke Bibilotheek&lt;/a&gt; or KB) hosted the second congress on &lt;a href=&quot;https://www.kb.nl/nieuws/2016/historische-kranten-als-big-data-ii-concepten-op-drift&quot;&gt;Historic newspapers as big data&lt;/a&gt;, with the central topic of Concept Drift. Slides and photos can be found in the &lt;a href=&quot;https://www.kb.nl/nieuws/2017/historisch-onderzoek-in-digitale-kranten-verslag-van-het-big-data-congres&quot;&gt;KB website&lt;/a&gt;. Concept Drift is the study of how a concept is modified as time goes by — this is a topic which interests me as it relates to one of my previous projects, &lt;a href=&quot;https://www.esciencecenter.nl/project/mining-shifting-concepts-through-time-shico&quot;&gt;ShiCo&lt;/a&gt;. It was a very well attended event, where many familiar faces were present.&lt;/p&gt;
&lt;h2 id=&quot;historische-kranten-als-big-data-ii-concepten-op-drift&quot;&gt;&lt;a href=&quot;https://www.kb.nl/nieuws/2016/historische-kranten-als-big-data-ii-concepten-op-drift?source=post_page-----1cc557b46ddf---------------------------------------&quot;&gt;Historische kranten als ‘big data’ II: Concepten op drift&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;op-het-congres-krijgen-wetenschappers-uit-diverse-disciplines-het-woord-variërend-van-historici-tot-computationeel&quot;&gt;Op het congres krijgen wetenschappers uit diverse disciplines het woord, variërend van historici tot computationeel…&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.kb.nl&quot;&gt;www.kb.nl&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;morning-keynotes&quot;&gt;Morning keynotes&lt;/h2&gt;
&lt;p&gt;During the morning session, Lily Knibbeler highlighted the importance of &lt;a href=&quot;http://www.delpher.nl/&quot;&gt;Delpher&lt;/a&gt;, as a research resource for exploring historic news papers. Delpher is a data store where you can find digitalized newspaper articles in Dutch. He emphasized the KB’s desire of fostering an open community where we can work and learn from each other. This is definitely something I feel is extremely important — we should all work together more closely and make the most of the fantastic resources (data and expertise) which are available at the KB and other organisations.&lt;/p&gt;
&lt;p&gt;During his keynote speech, Steven Claeyssens noted how libraries themselves are changing and drifting towards being more inclusive for machines. This brought up the topic of the quality of OCR (&lt;a href=&quot;https://en.wikipedia.org/wiki/Optical_character_recognition&quot;&gt;optical character recognition&lt;/a&gt;) technology. It is an issue the community at large acknowledges and is actively working on; it is also an issue where one of our engineers, &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-janneke-van-der-zwaan&quot;&gt;Janneke&lt;/a&gt;, has a personal interest (which she expressed during her &lt;a href=&quot;#7d00&quot;&gt;Flash presentation&lt;/a&gt;). The last keynote speech by Hein van den Berg focused on detailed definitions of concept schemas and their importance to understand concept drift.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_AASpN8mEA0hBKxlmvacFiw-0d5fa319.BV_ETvwq_Z21YSI2.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lunch time was occupied by interesting conversations as well as a number of demos scattered across the room.&lt;/p&gt;
&lt;h2 id=&quot;afternoon-session&quot;&gt;Afternoon session&lt;/h2&gt;
&lt;p&gt;After lunch, the dynamic duo, Pim Huijnen and Melvin Wevers, spoke about digital tools they use in historical research (both of which have eScience center connection): &lt;a href=&quot;http://texcavator.hum.uu.nl/&quot;&gt;Texcavator&lt;/a&gt; (on which Janneke worked) and &lt;a href=&quot;https://github.com/NLeSC/ShiCo&quot;&gt;ShiCo&lt;/a&gt; (on which &lt;a href=&quot;https://www.esciencecenter.nl/profile/dr.-carlos-martinez-ortiz&quot;&gt;I worked&lt;/a&gt;). It is great to see eScience tools being used by domain experts!&lt;/p&gt;
&lt;p&gt;The first round of flash presentations featured Janneke, pitching her idea for deep learning based OCR post-correction — a member of the public mentioned &lt;a href=&quot;https://github.com/tmbdev/ocropy&quot;&gt;OCRopus&lt;/a&gt; as a possible alternative, which would be interesting to look into to find out whether it is suitable or not. Martin Reynaert also talked about OCR — hot topic!&lt;/p&gt;
&lt;p&gt;The afternoon session continued with an interesting talk by Laura Hollink on the use of tools for evaluating concept shifts on linked data, Hennie Brugman presenting &lt;a href=&quot;http://www.nederlab.nl/onderzoeksportaal/&quot;&gt;Nederlab&lt;/a&gt;, Marieke van Erp also discussed the difficulties of analysing semantic changes and how this can be tackled with tools (with nice connections to &lt;a href=&quot;http://www.clariah.nl/&quot;&gt;CLARIAH&lt;/a&gt;). Finally Lotte Wilms also sneak previewed &lt;a href=&quot;http://www.kbresearch.nl/genre/&quot;&gt;tools&lt;/a&gt; from &lt;a href=&quot;http://lab.kbresearch.nl/&quot;&gt;KB Lab&lt;/a&gt;. So many cool tools! I would love to play with all of them!&lt;/p&gt;
&lt;p&gt;The final session of the day featured Jaap Kamps discussing how the libraries are changing and the effect that has in how people use libraries for doing research. Serge ter Braake also discussed how research practice has changed with digital tools.&lt;/p&gt;
&lt;p&gt;During the second round of flash presentations I was particularly interested in the idea pitched by Astrid van Aggelen and Milan van Lange, regarding mining shifts in sentiment in newspapers — this seems like an interesting use case for ShiCo. This actually goes back to the point made during the morning presentations: we should try to work together!&lt;/p&gt;
&lt;h2 id=&quot;closing-time&quot;&gt;Closing time&lt;/h2&gt;
&lt;p&gt;From the final words of Joris van Eijnattten during his last minutes as KB fellow, 3 things stood out as important to me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The importance of analyzing networks of words and concepts&lt;/li&gt;
&lt;li&gt;The importance of classification of words and concepts&lt;/li&gt;
&lt;li&gt;The importance of analyzing language variations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is clear that there are still many interesting challenges in this community, and I for one would be very excited to continue collaborating with everyone in this field.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;788&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Q4uNpqEcwTFD39dn3-mniA-1a67b0fe.BOUYVebn_13LMnJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Closing remarks by Joris van Eijnattten&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_AASpN8mEA0hBKxlmvacFiw-0d5fa319.BV_ETvwq.jpeg" medium="image"/><author>Carlos Martinez-Ortiz</author></item><item><title>Easier Docker in Python</title><link>https://blog2.esciencecenter.nl/posts/2017-02-03---easier-docker-in-python</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-03---easier-docker-in-python</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1334&quot; height=&quot;567&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_68X2g8ziJ_aHdtiHqajr3Q-d11b7e7e.B2AFr4Yz_220Sp0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; is a tool that creates a stack of virtual environments on top of a running Linux kernel. This allows you to run tools (and web services) in an encapsulated environment. I use Docker to call binary codes from Python in the context of a broader scientific/computational workflow. Using docker containers for this makes it infinitely easier to share the results of such a workflow. There is a &lt;a href=&quot;https://docker-py.readthedocs.io/en/stable/&quot;&gt;Python module&lt;/a&gt; for the API, but this is not the easiest to use, certainly not as easy as the docker command-line.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;461&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ChkdKbYyM7mIITvaUkHaDw-d1d6674b.CKmILOgM_1NBBJp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Exterminate!&lt;/p&gt;
&lt;p&gt;So, my goal is to make an easy interface to Docker that allows me to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create a container&lt;/li&gt;
&lt;li&gt;upload some input files&lt;/li&gt;
&lt;li&gt;run one or more commands&lt;/li&gt;
&lt;li&gt;retrieve results&lt;/li&gt;
&lt;li&gt;==exterminate==!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A Docker container can be thought of as a virtual machine, sharing resources with other containers that run on the same image. When we have a container running, we can communicate with it by sending it commands, talking to services and we can read or write to the file system. This last action is performed through tar archives.&lt;/p&gt;
&lt;p&gt;All of this makes a Python program that uses Docker directly through the &lt;code&gt;docker&lt;/code&gt; &lt;a href=&quot;https://docker-py.readthedocs.io/en/stable/&quot;&gt;module&lt;/a&gt; rather unreadable. Here, I show an example of how to fix this situation using only small amounts of additional Python code. If you like to play with this example, &lt;a href=&quot;http://github.com/jhidding/easy-docker.py&quot;&gt;get the code in this post from github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the spirit of &lt;a href=&quot;https://blog.thesoftwarecraft.com/2013/11/wishful-programming.html&quot;&gt;wishful programming&lt;/a&gt;, I show how we can express a simple Docker session after all this is complete. Usually a docker container contains one or more binary packages that provide some service; to keep this example minimal, we use the BusyBox container which has a very small footprint (the download is less than 1MB!). This example decrypts a secret message using Sed. Sed stands for Stream Editor; it is present on any decent Unix system, and used primarily to extract data from text files. The script used here was taken from the great &lt;a href=&quot;https://rosettacode.org/wiki/Rot-13#AWK&quot;&gt;Rosetta Code&lt;/a&gt; website.&lt;/p&gt;
&lt;p&gt;I introduced two classes to make this example work: &lt;code&gt;Archive&lt;/code&gt; and &lt;code&gt;DockerContainer&lt;/code&gt;. The &lt;code&gt;Archive&lt;/code&gt; class handles the construction of a tar-ball, while the &lt;code&gt;DockerContainer&lt;/code&gt; class manages the communication with the Docker daemon. By implementing this last class as a &lt;a href=&quot;https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/&quot;&gt;context-manager&lt;/a&gt;, the Docker container is removed immediately after we are done with it, hence no need for Daleks on that account.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code&gt;Archive.add_text_file&lt;/code&gt; methods returns &lt;code&gt;self&lt;/code&gt;. This is good behaviour for methods that only modify an existing object, since it allows chaining these methods and assigning the end result of this chain of method calls in one statement.&lt;/p&gt;
&lt;p&gt;This example code is concise and only focuses on &lt;em&gt;what&lt;/em&gt; we intend to do, not &lt;em&gt;how&lt;/em&gt; we make Docker understand. You could open a shell, copy the above sed-script and message into individual files and run the script using the same commands that you already see.&lt;/p&gt;
&lt;p&gt;Let’s start with a nicer interface to create a tar-ball. Docker uses tar-files to communicate data, so that multiple files can be transmitted in a single stream. Python has a built-in module for creating tar-files, however we are not interested in actually storing the file anywhere. We just need the data in a buffer so that we can send it to Docker with no further ado. This is why the &lt;code&gt;tarfile.open&lt;/code&gt; function is passed an instance of &lt;code&gt;io.BytesIO&lt;/code&gt;. This last class acts like a normal file, however it just stores in memory, not on disk.&lt;/p&gt;
&lt;p&gt;Next, the Docker container. Most of this code is just an object-oriented wrapper around the Python Docker SDK. The interface in the SDK is spartan by choice. Every user has different needs; rather than cater to every one of those, the Docker team chose to offer a very thin layer around the HTTP API. This is a &lt;em&gt;good thing&lt;/em&gt;. It just means we have to try a bit harder to write good code with it.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;DockerContainer&lt;/code&gt; class presented here has the nice feature that it optionally stores a working directory in &lt;code&gt;self.working_dir&lt;/code&gt;, which reflects the given &lt;code&gt;working_dir&lt;/code&gt; when the container was started. If the user tries to add files with a relative target path (in stead of an absolute one, that start with &lt;code&gt;/&lt;/code&gt;), the &lt;code&gt;working_dir&lt;/code&gt; is automatically joined with the given path.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;DockerContainer.run&lt;/code&gt; method is made to reflect the native Python &lt;code&gt;subprocess.run&lt;/code&gt; superficially. This makes its use much easier to remember!&lt;/p&gt;
&lt;p&gt;Right at the end, the &lt;code&gt;__enter__&lt;/code&gt; and &lt;code&gt;__exit__&lt;/code&gt; methods implement the so called context-manager, allowing the use of &lt;code&gt;with DockerContainer(...) as c:&lt;/code&gt; etc. If you’ve never seen that before, do read &lt;a href=&quot;https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/&quot;&gt;this post&lt;/a&gt; by Jeff Knupp, or the &lt;a href=&quot;https://www.jeffknupp.com/writing-idiomatic-python-ebook/&quot;&gt;Idiomatic Python&lt;/a&gt; book by the same author!&lt;/p&gt;
&lt;p&gt;I hope to have convinced you that with just a little bit of effort, its possible to write much nicer (top-level) code. In this case its about talking to Docker, but the same message holds for many interfaces. First think on how you would express a problem (or rather a solution) in an ideal world, then build interfaces that make it a reality.&lt;/p&gt;
&lt;p&gt;If you’d like to use this code to talk to Docker, just &lt;a href=&quot;https://github.com/jhidding/easy-docker.py&quot;&gt;fork the github repo&lt;/a&gt; and add your own functionality; it’s licensed under Apache v2.&lt;/p&gt;</description><pubDate>Fri, 03 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1334&quot; height=&quot;567&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_68X2g8ziJ_aHdtiHqajr3Q-d11b7e7e.B2AFr4Yz_220Sp0.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; is a tool that creates a stack of virtual environments on top of a running Linux kernel. This allows you to run tools (and web services) in an encapsulated environment. I use Docker to call binary codes from Python in the context of a broader scientific/computational workflow. Using docker containers for this makes it infinitely easier to share the results of such a workflow. There is a &lt;a href=&quot;https://docker-py.readthedocs.io/en/stable/&quot;&gt;Python module&lt;/a&gt; for the API, but this is not the easiest to use, certainly not as easy as the docker command-line.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;350&quot; height=&quot;461&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_ChkdKbYyM7mIITvaUkHaDw-d1d6674b.CKmILOgM_1NBBJp.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Exterminate!&lt;/p&gt;
&lt;p&gt;So, my goal is to make an easy interface to Docker that allows me to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create a container&lt;/li&gt;
&lt;li&gt;upload some input files&lt;/li&gt;
&lt;li&gt;run one or more commands&lt;/li&gt;
&lt;li&gt;retrieve results&lt;/li&gt;
&lt;li&gt;==exterminate==!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A Docker container can be thought of as a virtual machine, sharing resources with other containers that run on the same image. When we have a container running, we can communicate with it by sending it commands, talking to services and we can read or write to the file system. This last action is performed through tar archives.&lt;/p&gt;
&lt;p&gt;All of this makes a Python program that uses Docker directly through the &lt;code&gt;docker&lt;/code&gt; &lt;a href=&quot;https://docker-py.readthedocs.io/en/stable/&quot;&gt;module&lt;/a&gt; rather unreadable. Here, I show an example of how to fix this situation using only small amounts of additional Python code. If you like to play with this example, &lt;a href=&quot;http://github.com/jhidding/easy-docker.py&quot;&gt;get the code in this post from github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the spirit of &lt;a href=&quot;https://blog.thesoftwarecraft.com/2013/11/wishful-programming.html&quot;&gt;wishful programming&lt;/a&gt;, I show how we can express a simple Docker session after all this is complete. Usually a docker container contains one or more binary packages that provide some service; to keep this example minimal, we use the BusyBox container which has a very small footprint (the download is less than 1MB!). This example decrypts a secret message using Sed. Sed stands for Stream Editor; it is present on any decent Unix system, and used primarily to extract data from text files. The script used here was taken from the great &lt;a href=&quot;https://rosettacode.org/wiki/Rot-13#AWK&quot;&gt;Rosetta Code&lt;/a&gt; website.&lt;/p&gt;
&lt;p&gt;I introduced two classes to make this example work: &lt;code&gt;Archive&lt;/code&gt; and &lt;code&gt;DockerContainer&lt;/code&gt;. The &lt;code&gt;Archive&lt;/code&gt; class handles the construction of a tar-ball, while the &lt;code&gt;DockerContainer&lt;/code&gt; class manages the communication with the Docker daemon. By implementing this last class as a &lt;a href=&quot;https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/&quot;&gt;context-manager&lt;/a&gt;, the Docker container is removed immediately after we are done with it, hence no need for Daleks on that account.&lt;/p&gt;
&lt;p&gt;Note that the &lt;code&gt;Archive.add_text_file&lt;/code&gt; methods returns &lt;code&gt;self&lt;/code&gt;. This is good behaviour for methods that only modify an existing object, since it allows chaining these methods and assigning the end result of this chain of method calls in one statement.&lt;/p&gt;
&lt;p&gt;This example code is concise and only focuses on &lt;em&gt;what&lt;/em&gt; we intend to do, not &lt;em&gt;how&lt;/em&gt; we make Docker understand. You could open a shell, copy the above sed-script and message into individual files and run the script using the same commands that you already see.&lt;/p&gt;
&lt;p&gt;Let’s start with a nicer interface to create a tar-ball. Docker uses tar-files to communicate data, so that multiple files can be transmitted in a single stream. Python has a built-in module for creating tar-files, however we are not interested in actually storing the file anywhere. We just need the data in a buffer so that we can send it to Docker with no further ado. This is why the &lt;code&gt;tarfile.open&lt;/code&gt; function is passed an instance of &lt;code&gt;io.BytesIO&lt;/code&gt;. This last class acts like a normal file, however it just stores in memory, not on disk.&lt;/p&gt;
&lt;p&gt;Next, the Docker container. Most of this code is just an object-oriented wrapper around the Python Docker SDK. The interface in the SDK is spartan by choice. Every user has different needs; rather than cater to every one of those, the Docker team chose to offer a very thin layer around the HTTP API. This is a &lt;em&gt;good thing&lt;/em&gt;. It just means we have to try a bit harder to write good code with it.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;DockerContainer&lt;/code&gt; class presented here has the nice feature that it optionally stores a working directory in &lt;code&gt;self.working_dir&lt;/code&gt;, which reflects the given &lt;code&gt;working_dir&lt;/code&gt; when the container was started. If the user tries to add files with a relative target path (in stead of an absolute one, that start with &lt;code&gt;/&lt;/code&gt;), the &lt;code&gt;working_dir&lt;/code&gt; is automatically joined with the given path.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;DockerContainer.run&lt;/code&gt; method is made to reflect the native Python &lt;code&gt;subprocess.run&lt;/code&gt; superficially. This makes its use much easier to remember!&lt;/p&gt;
&lt;p&gt;Right at the end, the &lt;code&gt;__enter__&lt;/code&gt; and &lt;code&gt;__exit__&lt;/code&gt; methods implement the so called context-manager, allowing the use of &lt;code&gt;with DockerContainer(...) as c:&lt;/code&gt; etc. If you’ve never seen that before, do read &lt;a href=&quot;https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/&quot;&gt;this post&lt;/a&gt; by Jeff Knupp, or the &lt;a href=&quot;https://www.jeffknupp.com/writing-idiomatic-python-ebook/&quot;&gt;Idiomatic Python&lt;/a&gt; book by the same author!&lt;/p&gt;
&lt;p&gt;I hope to have convinced you that with just a little bit of effort, its possible to write much nicer (top-level) code. In this case its about talking to Docker, but the same message holds for many interfaces. First think on how you would express a problem (or rather a solution) in an ideal world, then build interfaces that make it a reality.&lt;/p&gt;
&lt;p&gt;If you’d like to use this code to talk to Docker, just &lt;a href=&quot;https://github.com/jhidding/easy-docker.py&quot;&gt;fork the github repo&lt;/a&gt; and add your own functionality; it’s licensed under Apache v2.&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_ChkdKbYyM7mIITvaUkHaDw-d1d6674b.CKmILOgM.jpeg" medium="image"/><author>Johan Hidding</author></item><item><title>Breaking jargon barriers at Talking eScience 2017</title><link>https://blog2.esciencecenter.nl/posts/2017-02-02---breaking-jargon-barriers-at-talking-escience-2017</link><guid isPermaLink="true">https://blog2.esciencecenter.nl/posts/2017-02-02---breaking-jargon-barriers-at-talking-escience-2017</guid><description>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_irNnyEX0lJaUbYyoGjXmHg-7432c0b6.DgSrs31i_Z148f86.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From the humanities to computer science: Our team of eScience Research Engineers and eScience Principal Investigators&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What do ecology, psychology and medical science have in common? And what digital technologies do we need to engage in those shared challenges, how do we bridge gaps between disciplines, and how do we combine expertise from different domains with expertise from computer and data science?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_d_vwW9J0npk3yuoUbuaVag-d78a9eb5.BSq6iSd-_xYjlv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Rob van Nieuwpoort, Ronald van Haren, Lars de Ridder and Anand Gavai from the eScience Center discuss the future of multi-scale modelling&lt;/p&gt;
&lt;p&gt;On Monday 30 January our team of eScience Research Engineers and eScience Principal Investigators came together to talk about shared challenges across different research disciplines. &lt;a href=&quot;https://www.flickr.com/photos/esciencecenter/albums/72157676211557443&quot;&gt;View the photo album on Flickr&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;breaking-the-jargon-barrier&quot;&gt;Breaking the jargon barrier&lt;/h2&gt;
&lt;p&gt;Starting the day with a talkshow illustrated the potential as well as the difficulty of bringing such diverse fields of research together. Ecologists and meteorologists discussed the possibilities of sharing data. Communication challenges also quickly became apparent when psychologists and computer scientists started talking about language (“are we talking about human language or programming language?”) and different interpretations of concepts (“what is the difference between text mining and natural language processing?”).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bzhr7X9boon-XZj7FIgGGA-2e095585.BDy-Z8rZ_poLfP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It shows the value of organizing a day like this, where we can try to work on shared understandings, break the jargon barrier, and inspire each other with unexpected perspectives.&lt;/p&gt;
&lt;h2 id=&quot;topics-to-follow-up&quot;&gt;Topics to follow-up&lt;/h2&gt;
&lt;p&gt;After many discussions, six topics were identified as relevant for a follow-up colloquium:&lt;/p&gt;
&lt;p&gt;1. Deep Learning in Science&lt;br&gt;
2. Data analytics&lt;br&gt;
3. Visualization&lt;br&gt;
4. Multi-scale modelling&lt;br&gt;
5. Data integration&lt;br&gt;
6. Tools and access to e-infrastructure&lt;/p&gt;
&lt;p&gt;The topics were discussed in in-depth sessions, after which each in-depth group presented a short pitch on why the eScience Center should organize a colloquium on this topic. While each topic is absolutely worth a colloquium, the most suitable topic was judged to be Visualization. Sign up for our &lt;a href=&quot;http://eepurl.com/Szzyf&quot;&gt;mailing list&lt;/a&gt; to stay up to date on this colloquium!&lt;/p&gt;
&lt;h2 id=&quot;why-are-these-topics-so-relevant-today&quot;&gt;Why are these topics so relevant today?&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UR7VKbV1BWaoWrCg4PHMkg-842267d3.Cn08U35o_1Nuzxy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Technical Lead Willem van Hage pitches for deep learning in science&lt;/p&gt;
&lt;h2 id=&quot;deep-learning-in-science&quot;&gt;Deep learning in science&lt;/h2&gt;
&lt;p&gt;Machine learning is a fast-growing and exciting field in research, and deep learningrepresents its state-of-the-art. Machine Learning and Deep Learning involve feeding a computer system a lot of data, which it can use to make decisions about other data. Deep Learning enables many researchers to scale up their machine learning in ways they couldn’t do before.&lt;/p&gt;
&lt;p&gt;That opens new avenues to ask new questions in many fields. When there are too many features to pre-code in your models, and you want to explore the field, Deep Learning saves you time for the creative part of science instead of spending too much time on the mundane technical data.&lt;/p&gt;
&lt;p&gt;What do we need to make progress with the application of Deep Learning in scientific research? A great start would be symposium for various fields of science that can profit from Deep Learning. Because it’s so fast, and so new, it’s very hard to stay up to date with current developments. You need to discuss new technological developments, but also new applications. It would be very useful to share prototype implementations in various fields so you can see commonalities and differences. And to share what is the best learning material to get you started.&lt;/p&gt;
&lt;p&gt;We need MOOCS and not books — we need online material that can change as the field changes. And we need access and examples of how to gain access to infrastructure with specific support — for example with GPU clusters but also with high-speed networks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UUpG16t9t9Nv0_zBPmBqoQ-b68efb5d.iMl9r399_q5MnT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineers and eScience Principal Investigators talking about the future of data analytics&lt;/p&gt;
&lt;h2 id=&quot;data-analytics&quot;&gt;Data analytics&lt;/h2&gt;
&lt;p&gt;We use models to make predictions about the future. For example, to fight or prevent poverty, or to detect where slums are evolving in cities. To develop and analyze these models we need a set of tools.&lt;/p&gt;
&lt;p&gt;However, there are so many methods available that we are blinded by the complexity. And we do not always know what the real truth is — because what is the truth in the future? We simply cannot evaluate these methods, and do not know which is the best one. We have so many different fields of expertise, but there is a gap between those fields which is preventing us from combining methods it in the best way.&lt;/p&gt;
&lt;p&gt;A course of action could be to start bringing those diverse fields of expertise together, to develop the communication between those fields. Not only between technical and scientific aspects but also between these and methodological aspects. We need communication beyond documented coding — collaborating with each other, also on an international scale, and with companies.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_G2o5y9u_-LElDAlz3BvDpw-8747d838.YKRmqCx6_29ja6k.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Coordinator Adriënne Mendrik pitches for visualization&lt;/p&gt;
&lt;h2 id=&quot;visualization&quot;&gt;Visualization&lt;/h2&gt;
&lt;p&gt;Visualization is a way to simplify complex data and make it more attractive to people, and therefore very important not only to go from data to information but also to inspire.&lt;/p&gt;
&lt;p&gt;A big challenge is for domain researchers to ‘trust’ the visualization. In any visualization choices are made to translate a set of data into a visualization that is more easily interpreted — inherently a process in which data is manipulated.&lt;/p&gt;
&lt;p&gt;It is important that people are educated so they understand how visualizations come about. At the same time, it is important that researchers realize what is possible by using visualization as a tool — because there is so much potential.&lt;/p&gt;
&lt;p&gt;Visualization is very difficult to generalize. Each research question requires a different kind of visualization. To get the most out of this technology, it is therefore important that researchers are aware of the possibilities. That enables researchers to communicate their wishes, and makes it easier for computer scientists to understand those wishes.&lt;/p&gt;
&lt;p&gt;A symposium would be a great way to show domain scientists the potential of translating their complex data into a ‘simplified’ visualization that helps to interpret the data and inspire other researchers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__wn0938lnjoWnSV-gJuFjg-2e15e069.CgMRKTFg_ZqhoGs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Coordinator Lars Ridder pitching for multi-scale modelling&lt;/p&gt;
&lt;h2 id=&quot;multi-scale-modelling&quot;&gt;Multi-scale modelling&lt;/h2&gt;
&lt;p&gt;Going from very small level to a very high level: from cells to society, from butterflies to global climate. From the Universe to a screen. Multi-scale modelling is trending.&lt;/p&gt;
&lt;p&gt;Why do we need multi-scale modelling? One reason is because we want to take short-cuts: We cannot compute whole systems at the lowest level of detail. Another reason is that we have data at all different levels now. This is new. And we have compute systems at different scales.&lt;/p&gt;
&lt;p&gt;There’s a good case for multi-scale modelling. The questions we asked ourselves is: Are there generic aspects that are true for multi-scale modelling in all the different domains? For example, can we find generic rules for how to separate different scales? Can we define best practices for the interfaces between the different scales? Do we have ways of validation for these complex multi-scale models? Do we know how to map the multi-scale models to a multi-scale complex compute infrastructure?&lt;/p&gt;
&lt;p&gt;There are many more questions than answers at this moment. That’s why we really need a workshop to work this out. We want to bring together scientists from different domains to sit together and see what the properties of their multi-scale models are and extract generic aspects that we can solve as eScience Center.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PfUaD7k4gaiM_hFPVUjukQ-d5551c6e.5c08-Yox_Z2i9Wfm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Principal Investigator Chris de Graaf pitching for data integration&lt;/p&gt;
&lt;h2 id=&quot;data-integration&quot;&gt;Data integration&lt;/h2&gt;
&lt;p&gt;Data integration allows users to see a unified view of heterogeneous data. It involves combining data from several disparate sources, which are stored using various technologies. Data integration is becoming essential to do science.&lt;/p&gt;
&lt;p&gt;There are four things to consider: different formats, different modalities of data, ontology (a set of concepts and categories in a subject area), and also linked to that epistemology (different ontologies in different communities).&lt;/p&gt;
&lt;p&gt;Data integration challenges can be illustrated by the following two ‘billion dollar research questions’: 1) How can you use allele and gene information to predict the size and also the robustness of crops or plants? 2) How can we combine biological activity and chemical structure information to predict polypharmacological action of drug molecules on multiple protein targets? We tried to find some common themes between the research questions&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_z3Zme-T2tNf83s47wdsOSQ-cd65895b.DTNUoHno_1A4HWJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We realized initially that we have different problems. Namely, for the polypharmacological question we had the problem that there were certain data integration tools not available that we need to invest in, while for the crop prediction the whole infrastructure and ontology has to be developed and there are a lot of epistemological questions to deal with. We realized when moving to a cell based system, polypharmacological questions would have a similar problem in terms of infrastructure and ontology.&lt;/p&gt;
&lt;p&gt;That’s why we need a symposium where we want to have case studies presented that reflect not only the challenges of this essential work but also the success stories of the science to convince people of the urgency of tackling this challnge — based on the different aspects of data integration we will come to discussion groups. And then in the end, if we get to speak the same language on either one of those elements, that will be a big success.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-JR2X2SQJpuPUEgOd778AA-5639babc.BiqeWTrH_2qYJxb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineers and eScience Principal Investigators talking about streaming data&lt;/p&gt;
&lt;h2 id=&quot;streaming-data&quot;&gt;Streaming data&lt;/h2&gt;
&lt;p&gt;The case for a symposium on streaming data is very compelling. Imagine, you have an up to date view of all your data as it streams in. The participants in this session all shared a dream. All work with networks of sensors — be they wearables, weather buoys to collect weather and ocean data for climate research or antennas to study the universe. And it turns out that we need to study the data of these sensors continuously as they come in. We found out that we need to identify which of this real-time processing can be done by software and which by hardware. Sometimes there is so much data that you need to get it reduced in seconds.&lt;/p&gt;
&lt;p&gt;Some of it you can run on commodity hardware, others need specialty hardware. But we, the users, don’t want to know. We need this hardware to be fault-tolerant, sustainable, and we need it to have reasoning build in. Therefore, we need a one-day workshop in which we are going to build enthusiasm for a flagship project on stream reasoning.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography by Elodie Burrillon, HUCOPIX&lt;/em&gt;&lt;/p&gt;</description><pubDate>Thu, 02 Feb 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_irNnyEX0lJaUbYyoGjXmHg-7432c0b6.DgSrs31i_Z148f86.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;From the humanities to computer science: Our team of eScience Research Engineers and eScience Principal Investigators&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What do ecology, psychology and medical science have in common? And what digital technologies do we need to engage in those shared challenges, how do we bridge gaps between disciplines, and how do we combine expertise from different domains with expertise from computer and data science?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_d_vwW9J0npk3yuoUbuaVag-d78a9eb5.BSq6iSd-_xYjlv.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Rob van Nieuwpoort, Ronald van Haren, Lars de Ridder and Anand Gavai from the eScience Center discuss the future of multi-scale modelling&lt;/p&gt;
&lt;p&gt;On Monday 30 January our team of eScience Research Engineers and eScience Principal Investigators came together to talk about shared challenges across different research disciplines. &lt;a href=&quot;https://www.flickr.com/photos/esciencecenter/albums/72157676211557443&quot;&gt;View the photo album on Flickr&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;breaking-the-jargon-barrier&quot;&gt;Breaking the jargon barrier&lt;/h2&gt;
&lt;p&gt;Starting the day with a talkshow illustrated the potential as well as the difficulty of bringing such diverse fields of research together. Ecologists and meteorologists discussed the possibilities of sharing data. Communication challenges also quickly became apparent when psychologists and computer scientists started talking about language (“are we talking about human language or programming language?”) and different interpretations of concepts (“what is the difference between text mining and natural language processing?”).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_Bzhr7X9boon-XZj7FIgGGA-2e095585.BDy-Z8rZ_poLfP.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It shows the value of organizing a day like this, where we can try to work on shared understandings, break the jargon barrier, and inspire each other with unexpected perspectives.&lt;/p&gt;
&lt;h2 id=&quot;topics-to-follow-up&quot;&gt;Topics to follow-up&lt;/h2&gt;
&lt;p&gt;After many discussions, six topics were identified as relevant for a follow-up colloquium:&lt;/p&gt;
&lt;p&gt;1. Deep Learning in Science&lt;br&gt;
2. Data analytics&lt;br&gt;
3. Visualization&lt;br&gt;
4. Multi-scale modelling&lt;br&gt;
5. Data integration&lt;br&gt;
6. Tools and access to e-infrastructure&lt;/p&gt;
&lt;p&gt;The topics were discussed in in-depth sessions, after which each in-depth group presented a short pitch on why the eScience Center should organize a colloquium on this topic. While each topic is absolutely worth a colloquium, the most suitable topic was judged to be Visualization. Sign up for our &lt;a href=&quot;http://eepurl.com/Szzyf&quot;&gt;mailing list&lt;/a&gt; to stay up to date on this colloquium!&lt;/p&gt;
&lt;h2 id=&quot;why-are-these-topics-so-relevant-today&quot;&gt;Why are these topics so relevant today?&lt;/h2&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2048&quot; height=&quot;1365&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UR7VKbV1BWaoWrCg4PHMkg-842267d3.Cn08U35o_1Nuzxy.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Technical Lead Willem van Hage pitches for deep learning in science&lt;/p&gt;
&lt;h2 id=&quot;deep-learning-in-science&quot;&gt;Deep learning in science&lt;/h2&gt;
&lt;p&gt;Machine learning is a fast-growing and exciting field in research, and deep learningrepresents its state-of-the-art. Machine Learning and Deep Learning involve feeding a computer system a lot of data, which it can use to make decisions about other data. Deep Learning enables many researchers to scale up their machine learning in ways they couldn’t do before.&lt;/p&gt;
&lt;p&gt;That opens new avenues to ask new questions in many fields. When there are too many features to pre-code in your models, and you want to explore the field, Deep Learning saves you time for the creative part of science instead of spending too much time on the mundane technical data.&lt;/p&gt;
&lt;p&gt;What do we need to make progress with the application of Deep Learning in scientific research? A great start would be symposium for various fields of science that can profit from Deep Learning. Because it’s so fast, and so new, it’s very hard to stay up to date with current developments. You need to discuss new technological developments, but also new applications. It would be very useful to share prototype implementations in various fields so you can see commonalities and differences. And to share what is the best learning material to get you started.&lt;/p&gt;
&lt;p&gt;We need MOOCS and not books — we need online material that can change as the field changes. And we need access and examples of how to gain access to infrastructure with specific support — for example with GPU clusters but also with high-speed networks.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_UUpG16t9t9Nv0_zBPmBqoQ-b68efb5d.iMl9r399_q5MnT.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineers and eScience Principal Investigators talking about the future of data analytics&lt;/p&gt;
&lt;h2 id=&quot;data-analytics&quot;&gt;Data analytics&lt;/h2&gt;
&lt;p&gt;We use models to make predictions about the future. For example, to fight or prevent poverty, or to detect where slums are evolving in cities. To develop and analyze these models we need a set of tools.&lt;/p&gt;
&lt;p&gt;However, there are so many methods available that we are blinded by the complexity. And we do not always know what the real truth is — because what is the truth in the future? We simply cannot evaluate these methods, and do not know which is the best one. We have so many different fields of expertise, but there is a gap between those fields which is preventing us from combining methods it in the best way.&lt;/p&gt;
&lt;p&gt;A course of action could be to start bringing those diverse fields of expertise together, to develop the communication between those fields. Not only between technical and scientific aspects but also between these and methodological aspects. We need communication beyond documented coding — collaborating with each other, also on an international scale, and with companies.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_G2o5y9u_-LElDAlz3BvDpw-8747d838.YKRmqCx6_29ja6k.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Coordinator Adriënne Mendrik pitches for visualization&lt;/p&gt;
&lt;h2 id=&quot;visualization&quot;&gt;Visualization&lt;/h2&gt;
&lt;p&gt;Visualization is a way to simplify complex data and make it more attractive to people, and therefore very important not only to go from data to information but also to inspire.&lt;/p&gt;
&lt;p&gt;A big challenge is for domain researchers to ‘trust’ the visualization. In any visualization choices are made to translate a set of data into a visualization that is more easily interpreted — inherently a process in which data is manipulated.&lt;/p&gt;
&lt;p&gt;It is important that people are educated so they understand how visualizations come about. At the same time, it is important that researchers realize what is possible by using visualization as a tool — because there is so much potential.&lt;/p&gt;
&lt;p&gt;Visualization is very difficult to generalize. Each research question requires a different kind of visualization. To get the most out of this technology, it is therefore important that researchers are aware of the possibilities. That enables researchers to communicate their wishes, and makes it easier for computer scientists to understand those wishes.&lt;/p&gt;
&lt;p&gt;A symposium would be a great way to show domain scientists the potential of translating their complex data into a ‘simplified’ visualization that helps to interpret the data and inspire other researchers.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1__wn0938lnjoWnSV-gJuFjg-2e15e069.CgMRKTFg_ZqhoGs.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Coordinator Lars Ridder pitching for multi-scale modelling&lt;/p&gt;
&lt;h2 id=&quot;multi-scale-modelling&quot;&gt;Multi-scale modelling&lt;/h2&gt;
&lt;p&gt;Going from very small level to a very high level: from cells to society, from butterflies to global climate. From the Universe to a screen. Multi-scale modelling is trending.&lt;/p&gt;
&lt;p&gt;Why do we need multi-scale modelling? One reason is because we want to take short-cuts: We cannot compute whole systems at the lowest level of detail. Another reason is that we have data at all different levels now. This is new. And we have compute systems at different scales.&lt;/p&gt;
&lt;p&gt;There’s a good case for multi-scale modelling. The questions we asked ourselves is: Are there generic aspects that are true for multi-scale modelling in all the different domains? For example, can we find generic rules for how to separate different scales? Can we define best practices for the interfaces between the different scales? Do we have ways of validation for these complex multi-scale models? Do we know how to map the multi-scale models to a multi-scale complex compute infrastructure?&lt;/p&gt;
&lt;p&gt;There are many more questions than answers at this moment. That’s why we really need a workshop to work this out. We want to bring together scientists from different domains to sit together and see what the properties of their multi-scale models are and extract generic aspects that we can solve as eScience Center.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_PfUaD7k4gaiM_hFPVUjukQ-d5551c6e.5c08-Yox_Z2i9Wfm.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Principal Investigator Chris de Graaf pitching for data integration&lt;/p&gt;
&lt;h2 id=&quot;data-integration&quot;&gt;Data integration&lt;/h2&gt;
&lt;p&gt;Data integration allows users to see a unified view of heterogeneous data. It involves combining data from several disparate sources, which are stored using various technologies. Data integration is becoming essential to do science.&lt;/p&gt;
&lt;p&gt;There are four things to consider: different formats, different modalities of data, ontology (a set of concepts and categories in a subject area), and also linked to that epistemology (different ontologies in different communities).&lt;/p&gt;
&lt;p&gt;Data integration challenges can be illustrated by the following two ‘billion dollar research questions’: 1) How can you use allele and gene information to predict the size and also the robustness of crops or plants? 2) How can we combine biological activity and chemical structure information to predict polypharmacological action of drug molecules on multiple protein targets? We tried to find some common themes between the research questions&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1400&quot; height=&quot;933&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_z3Zme-T2tNf83s47wdsOSQ-cd65895b.DTNUoHno_1A4HWJ.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We realized initially that we have different problems. Namely, for the polypharmacological question we had the problem that there were certain data integration tools not available that we need to invest in, while for the crop prediction the whole infrastructure and ontology has to be developed and there are a lot of epistemological questions to deal with. We realized when moving to a cell based system, polypharmacological questions would have a similar problem in terms of infrastructure and ontology.&lt;/p&gt;
&lt;p&gt;That’s why we need a symposium where we want to have case studies presented that reflect not only the challenges of this essential work but also the success stories of the science to convince people of the urgency of tackling this challnge — based on the different aspects of data integration we will come to discussion groups. And then in the end, if we get to speak the same language on either one of those elements, that will be a big success.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2000&quot; height=&quot;1333&quot; src=&quot;https://blog2.esciencecenter.nl/_astro/1_-JR2X2SQJpuPUEgOd778AA-5639babc.BiqeWTrH_2qYJxb.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;eScience Research Engineers and eScience Principal Investigators talking about streaming data&lt;/p&gt;
&lt;h2 id=&quot;streaming-data&quot;&gt;Streaming data&lt;/h2&gt;
&lt;p&gt;The case for a symposium on streaming data is very compelling. Imagine, you have an up to date view of all your data as it streams in. The participants in this session all shared a dream. All work with networks of sensors — be they wearables, weather buoys to collect weather and ocean data for climate research or antennas to study the universe. And it turns out that we need to study the data of these sensors continuously as they come in. We found out that we need to identify which of this real-time processing can be done by software and which by hardware. Sometimes there is so much data that you need to get it reduced in seconds.&lt;/p&gt;
&lt;p&gt;Some of it you can run on commodity hardware, others need specialty hardware. But we, the users, don’t want to know. We need this hardware to be fault-tolerant, sustainable, and we need it to have reasoning build in. Therefore, we need a one-day workshop in which we are going to build enthusiasm for a flagship project on stream reasoning.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photography by Elodie Burrillon, HUCOPIX&lt;/em&gt;&lt;/p&gt;</content:encoded><media:content url="https://blog2.esciencecenter.nl/_astro/1_d_vwW9J0npk3yuoUbuaVag-d78a9eb5.BSq6iSd-.jpeg" medium="image"/><author>Lode Kulik</author></item></channel></rss>